Tag Archives: Workflow

How To : Use a Site mailbox to collaborate with your team

Share documents with others

Image

Every team has documents of some kind that need to be stored somewhere, and usually need to be shared with others. If you store your team’s documents on your SharePoint site, you can easily leverage the Site Mailbox app to share those documents with those who have site access.

 Important    When users view a site mailbox in Outlook, they will see a list of all the documents in that site’s document libraries. Site mailboxes present the same list of documents to all users, so some users may see documents they do not have access to open.

If you’re using Exchange, your documents will also appear in a folder in Outlook, making it even easier to forward documents to others.

Forwarding a document from the site mailbox

Organizations, and teams within organizations, often have several different email threads going in all directions at one time. It’s easy for lines to cross, information to get lost or overlooked, and for communication to break down. Site mailboxes enable you to store team or project-related email in one place, so that everyone on the team can see all communication.

On the Quick Launch, click Mailbox.

Mailbox on the Quick Launch

The site mailbox opens as a second, separate inbox and folder structure, next to your personal email account. Mail sent to and from the site mailbox account will be shared between all those who have Contributor permissions on the SharePoint site.

 Tip    Did you know you can also use a site mailbox to collaborate on documents?

Add a site mailbox as a mail recipient

By including the site mailbox on an important email thread, you ensure that a copy of the information in that thread is stored in a location that can be accessed by anyone on the team.

Simply add the site mailbox in the To, CC, or BCC line of an email message.

Email message with site mailbox included in CC field.

You could even consider adding the site mailbox email address to any team contact groups or distribution lists. That way, relevant email automatically gets stored in the team’s site mailbox.

Send email from the site mailbox

When you write and send email from the site mailbox, it will look as though it came from you.

Because everyone with Contributor permissions on a site can access the site mailbox, several people can work together to draft an email message.

To compose a message, simply click New Mail.

New mail button for site mailboxes.

This will open a new message in your site mailbox.

New mail message in a site mailbox.

Architecture and Practical Application – BizTalk Adapter for mySAP Business Suite

Architecture for BizTalk Adapter for mySAP Business Suite

f36f4-netvjava

The Microsoft BizTalk Adapter for mySAP Business Suite implements a Windows Communication Foundation (WCF) custom binding, which contains a single custom transport binding element that enables communication with an SAP system.

biztalk-accelerator

The SAP adapter is wrapped by the Microsoft Windows Communication Foundation (WCF) Line of Business (LOB) Adapter SDK runtime and is exposed to applications through the WCF channel architecture. The SAP adapter communicates with the SAP system through either the 64-bit or 32-bit version of the SAP Unicode RFC SDK (librfc32u.dll).

The following figure shows the end-to-end architecture for solutions that are developed by using the SAP adapter.
SAP End-to-End Architecture
Consuming the Adapter

The SAP adapter exposes the SAP system as a WCF service to client applications. Client applications exchange SOAP messages with the SAP adapter through WCF channels to perform operations and to access data on the SAP system. The preceding figure shows four ways in which the SAP adapter can be consumed.

image
• Through a WCF channel application that performs operations on the SAP system by using the WCF channel model to exchange SOAP messages directly with the SAP adapter. For more information about developing solutions for the SAP adapter by using WCF channel model programming, see Developing Applications by Using the WCF Channel Model.

• Through a WCF service model application that calls methods on a WCF client to perform operations on the SAP system. A WCF client models the operations exposed by the SAP adapter as .NET methods. You can use the Microsoft Windows Communication Foundation (WCF) Line of Business (LOB) Adapter SDK or the svcutil.exe tool to create a WCF client class from metadata exposed by the SAP adapter. For more information about WCF service model programming and the SAP adapter, see Developing Applications by Using the WCF Service Model.

• Through a BizTalk port that is configured to use the BizTalk WCF-Custom adapter with the SAP Binding configured as the binding for the WCF-Custom transport type in a BizTalk Server application. The BizTalk WCF-Custom adapter enables communication between a BizTalk Server application and a WCF service.

The BizTalk WCF-Custom adapter supports custom WCF bindings through its WCF-Custom transport type, which enables you to configure any WCF binding exposed to the configuration system as the binding used by the BizTalk WCF-Custom adapter. For more information about how to use the SAP adapter in BizTalk Server solutions, see Developing BizTalk Applications. BizTalk transactions are supported by the BizTalk Layered Channel binding element which can be loaded by setting a binding property on the SAP Binding.

• Through an IIS-hosted Web service. In this scenario, the SAP adapter is exposed through a WCF Service proxy, which is hosted in IIS by using one of the standard WCF HTTP bindings.

• Through the .NET Framework Data Provider for mySAP Business Suite. The Data Provider for SAP runs on top of the SAP adapter and provides an ADO.NET interface to an SAP system.

The SAP adapter and the SAP RFC library are always hosted in-process with the application or service that consumes the adapter.

The SAP Adapter and WCF

WCF presents a programming model based on the exchange of SOAP messages over channels between clients and services. These messages are sent between endpoints exposed by a communicating client and service.

An endpoint consists of an endpoint address which specifies the location at which messages are received, a binding which specifies the communication protocols used to exchange messages, and a contract which specifies the operations and data types exposed by the endpoint.

A binding consists of one or more binding elements that stack on top of each other to define how messages are exchanged with the endpoint.

 

At a minimum, a binding must specify the transport and encoding used to exchange messages with the endpoint. Message exchange between endpoints occurs over a channel stack that is composed of one or more channels. Each channel is a concrete implementation of one of the binding elements in the binding configured for the endpoint.

For more information about WCF and the WCF programming model, see “Windows Communication Foundation” at http://go.microsoft.com/fwlink/?LinkId=89726.

The Microsoft BizTalk Adapter for mySAP Business Suite exposes a WCF custom binding, the SAP Binding (Microsoft.Adapters.SAP.SAPBinding). By default, this binding contains a single custom transport binding element, the SAP Adapter Binding Element (Microsoft.Adapters.SAP.SAPAdapter), which enables operations on an SAP system. When using the SAP adapter with BizTalk Server, you can set the EnableBizTalkCompatibilityMode binding property to load a custom binding element, the BizTalk Layered Channel Binding Element, on top of the SAP Adapter Binding Element. The BizTalk Layered Channel Binding Element is implemented internally by the SAP adapter and is not exposed outside the SAP Binding.

Microsoft.Adapters.SAP.SAPBinding (the SAP Binding) and Microsoft.Adapters.SAP.SAPAdapter (the SAP Adapter Binding Element) are public classes and are also exposed to the configuration system. Because the SAP Adapter Binding Element is exposed publicly, you can build your own custom WCF bindings capable of extending the functionality of the SAP adapter. For example, you could implement a custom binding to support Enterprise Single Sign-On (SSO) in a WCF channel or a WCF service model programming solution, to aggregate database operations into a single multifunction operation, or to perform schema transformation between operations implemented by a custom application and operations on the SAP system.

The SAP adapter is built on top of the Microsoft Windows Communication Foundation (WCF) Line of Business (LOB) Adapter SDK and runs on top of the WCF LOB Adapter SDK runtime. The WCF LOB Adapter SDK provides a software framework and tooling infrastructure that the SAP adapter leverages to provide a rich set of features to users and adapter clients.

The Connection to the SAP System

The SAP adapter connects with the SAP system through the SAP Unicode RFC SDK Library (librfc32u.dll). The SAP adapter supports both the 32 bit and the 64 bit versions of the SAP RFC SDK. The SAP RFC SDK enables external programs to call ABAP functions on a SAP system.

You establish a connection to an SAP system by providing a connection URI to the SAP adapter. The SAP adapter supports the following kinds of connections to an SAP system:
• An application host–based connection (A), in which the SAP adapter connects directly to an SAP application server.

• A load balancing connection (B), in which the SAP adapter connects to an SAP messaging server.

• A destination-based connection (D), in which the connection to the SAP system is specified by a destination in the saprfc.ini configuration file. A, B, and R type connections are supported.

• A listener connection (R), in which the adapter receives RFCs, tRFC and IDOCs through an RFC Destination on the SAP system that is specified by a listener host, a listener gateway service, and a listener program ID, either directly in the connection URI or by an R-based destination in the saprfc.ini configuration file.

Architecture for BizTalk Adapter for mySAP Business Suite

This topic has not yet been rated – Rate this topic

The Microsoft BizTalk Adapter for mySAP Business Suite implements a Windows Communication Foundation (WCF) custom binding, which contains a single custom transport binding element that enables communication with an SAP system. The SAP adapter is wrapped by the Microsoft Windows Communication Foundation (WCF) Line of Business (LOB) Adapter SDK runtime and is exposed to applications through the WCF channel architecture. The SAP adapter communicates with the SAP system through either the 64-bit or 32-bit version of the SAP Unicode RFC SDK (librfc32u.dll). The following figure shows the end-to-end architecture for solutions that are developed by using the SAP adapter.
SAP End-to-End Architecture
Consuming the Adapter

The SAP adapter exposes the SAP system as a WCF service to client applications. Client applications exchange SOAP messages with the SAP adapter through WCF channels to perform operations and to access data on the SAP system. The preceding figure shows four ways in which the SAP adapter can be consumed.
• Through a WCF channel application that performs operations on the SAP system by using the WCF channel model to exchange SOAP messages directly with the SAP adapter. For more information about developing solutions for the SAP adapter by using WCF channel model programming, see Developing Applications by Using the WCF Channel Model.

• Through a WCF service model application that calls methods on a WCF client to perform operations on the SAP system. A WCF client models the operations exposed by the SAP adapter as .NET methods. You can use the Microsoft Windows Communication Foundation (WCF) Line of Business (LOB) Adapter SDK or the svcutil.exe tool to create a WCF client class from metadata exposed by the SAP adapter. For more information about WCF service model programming and the SAP adapter, see Developing Applications by Using the WCF Service Model.

• Through a BizTalk port that is configured to use the BizTalk WCF-Custom adapter with the SAP Binding configured as the binding for the WCF-Custom transport type in a BizTalk Server application. The BizTalk WCF-Custom adapter enables communication between a BizTalk Server application and a WCF service.

The BizTalk WCF-Custom adapter supports custom WCF bindings through its WCF-Custom transport type, which enables you to configure any WCF binding exposed to the configuration system as the binding used by the BizTalk WCF-Custom adapter. For more information about how to use the SAP adapter in BizTalk Server solutions, see Developing BizTalk Applications.

BizTalk transactions are supported by the BizTalk Layered Channel binding element which can be loaded by setting a binding property on the SAP Binding.

• Through an IIS-hosted Web service. In this scenario, the SAP adapter is exposed through a WCF Service proxy, which is hosted in IIS by using one of the standard WCF HTTP bindings.

• Through the .NET Framework Data Provider for mySAP Business Suite. The Data Provider for SAP runs on top of the SAP adapter and provides an ADO.NET interface to an SAP system.

The SAP adapter and the SAP RFC library are always hosted in-process with the application or service that consumes the adapter.

The SAP Adapter and WCF

WCF presents a programming model based on the exchange of SOAP messages over channels between clients and services. These messages are sent between endpoints exposed by a communicating client and service.

An endpoint consists of an endpoint address which specifies the location at which messages are received, a binding which specifies the communication protocols used to exchange messages, and a contract which specifies the operations and data types exposed by the endpoint. A binding consists of one or more binding elements that stack on top of each other to define how messages are exchanged with the endpoint.

At a minimum, a binding must specify the transport and encoding used to exchange messages with the endpoint. Message exchange between endpoints occurs over a channel stack that is composed of one or more channels. Each channel is a concrete implementation of one of the binding elements in the binding configured for the endpoint.

For more information about WCF and the WCF programming model, see “Windows Communication Foundation” at http://go.microsoft.com/fwlink/?LinkId=89726.

The Microsoft BizTalk Adapter for mySAP Business Suite exposes a WCF custom binding, the SAP Binding (Microsoft.Adapters.SAP.SAPBinding). By default, this binding contains a single custom transport binding element, the SAP Adapter Binding Element (Microsoft.Adapters.SAP.SAPAdapter), which enables operations on an SAP system. When using the SAP adapter with BizTalk Server, you can set the EnableBizTalkCompatibilityMode binding property to load a custom binding element, the BizTalk Layered Channel Binding Element, on top of the SAP Adapter Binding Element. The BizTalk Layered Channel Binding Element is implemented internally by the SAP adapter and is not exposed outside the SAP Binding.

Microsoft.Adapters.SAP.SAPBinding (the SAP Binding) and Microsoft.Adapters.SAP.SAPAdapter (the SAP Adapter Binding Element) are public classes and are also exposed to the configuration system. Because the SAP Adapter Binding Element is exposed publicly, you can build your own custom WCF bindings capable of extending the functionality of the SAP adapter. For example, you could implement a custom binding to support Enterprise Single Sign-On (SSO) in a WCF channel or a WCF service model programming solution, to aggregate database operations into a single multifunction operation, or to perform schema transformation between operations implemented by a custom application and operations on the SAP system.

The SAP adapter is built on top of the Microsoft Windows Communication Foundation (WCF) Line of Business (LOB) Adapter SDK and runs on top of the WCF LOB Adapter SDK runtime. The WCF LOB Adapter SDK provides a software framework and tooling infrastructure that the SAP adapter leverages to provide a rich set of features to users and adapter clients.

The Connection to the SAP System

The SAP adapter connects with the SAP system through the SAP Unicode RFC SDK Library (librfc32u.dll). The SAP adapter supports both the 32 bit and the 64 bit versions of the SAP RFC SDK. The SAP RFC SDK enables external programs to call ABAP functions on a SAP system.

You establish a connection to an SAP system by providing a connection URI to the SAP adapter. The SAP adapter supports the following kinds of connections to an SAP system:
• An application host–based connection (A), in which the SAP adapter connects directly to an SAP application server.

• A load balancing connection (B), in which the SAP adapter connects to an SAP messaging server.

• A destination-based connection (D), in which the connection to the SAP system is specified by a destination in the saprfc.ini configuration file. A, B, and R type connections are supported.

• A listener connection (R), in which the adapter receives RFCs, tRFC and IDOCs through an RFC Destination on the SAP system that is specified by a listener host, a listener gateway service, and a listener program ID, either directly in the connection URI or by an R-based destination in the saprfc.ini configuration file.

So – How Do I Use a Custom Web Part?

This topic has not yet been rated – Rate this topic

This section provides information about using a custom Web Part with Microsoft Office SharePoint Server. To use a custom Web Part, you must do the following:
1. Create a custom Web Part

  1. Deploy the custom Web Part to a SharePoint portal
  2. Configure the SharePoint portal to use the custom Web Part

Before You Begin

Before you create a custom Web Part:
• Publish the SAP artifacts as a WCF service. For more information, see Step 1: Publish the SAP Artifacts as a WCF Service in Tutorial 1: Presenting Data from an SAP System on a SharePoint Site.

• Create an application definition file for the SAP artifacts using the Business Data Catalog in Microsoft Office SharePoint Server. For more information, see Step 2: Create an Application Definition File for the SAP Artifacts in Tutorial 1: Presenting Data from an SAP System on a SharePoint Site.

Step 1: Create a custom Web Part

To create a custom Web Part using Visual Studio, do the following:
1. Start Visual Studio, and then create a project.

  1. In the New Project dialog box, from the Project types pane, select Visual C#. From the Templates pane, select Class Library.
  • Specify a name and location for the solution. For this topic, specify CustomWebPart in the Name and Solution Name boxes. Specify a location, and then click OK.

  • Add a reference to the System.Web component into the project. Right-click the project name in Solution Explorer, and then click Add Reference. In the Add Reference dialog box, select System.Web in the .NET tab, and then click OK. The System.Web component contains the required namespace of System.Web.UI.WebControls.WebParts.

  • Add the required code based on your issue in the project. For the code sample that is relevant to a certain issue, see “Issues Involving Custom Web Parts” in Considerations While Using the SAP Adapter with Microsoft Office SharePoint Server.

  • Build the project. On successful build of the project, a .dll file, CustomWebPart.dll, will be generated in the /bin/Debug folder.

  • Only for 64-bit computer: Sign the CustomWebPart.dll file with a strong name before performing the following steps. Otherwise, you will not be able to import, and hence use the CustomWebPart.dll in the SharePoint portal in “Step 3: Configure the SharePoint Portal to use the custom Web Part.” For information about how to sign an assembly with a strong name, see http://go.microsoft.com/fwlink/?LinkId=197171.

  • Step 2: Deploy the custom Web Part to a SharePoint Portal

    You must do the following to make the CustomWebPart.dll file (custom Web Part) that is created in “Step 1: Create a custom Web Part” of this topic usable on the SharePoint portal:
    • Copy the CustomWebPart.dll file to the bin folder of the SharePoint Portal: Microsoft Office SharePoint Server creates portals under the :\Inetpub\wwwroot\wss\VirtualDirectories folder. A folder is created for each portal, and can be identified with the port number. You must copy the CustomWebPart.dll file created in “Step 1: Create a custom Web Part” of this topic to the :\Inetpub\wwwroot\wss\VirtualDirectories\bin folder. For example, if the port number of your SharePoint portal is 13614, you must copy the CustomWebPart.dll file to the :\Inetpub\wwwroot\wss\VirtualDirectories\13614\bin folder.

    TipTip

    Another way to find the folder location of your SharePoint portal is by using the Internet Information Services (IIS) Manager window (Start > Run > inetmgr). Locate your SharePoint portal in the Internet Information Services (IIS) Manager window ([computer_name] > Web Sites > [Portal-Name]), right-click, and then click Properties in the shortcut menu. In the properties dialog box of the SharePoint portal, click the Home Directory tab, and then select the Local path box.

    • Add the Safe Control Entry in the web.config File: Because the CustomWebPart.dll file will be used on different computers and by multiple users, you must declare the file as “safe.” To do so, open the web.config file located in the SharePoint portal folder at :\Inetpub\wwwroot\wss\VirtualDirectories. Under the section of the web.config file, add the following safe control entry:

    ◦On 32-bit computer:

    Copy

     

    ◦On 64-bit computer:

    Copy

     

    Save the web.config file, and then close it.

    Step 3: Configure the SharePoint portal to use the custom Web Part

    You need to add the custom Web Part to the Microsoft Office SharePoint Server Web Part Gallery, so that you can use it on your SharePoint portal. To do so:

    1. Start SharePoint 3.0 Central Administration. Click Start, point to All Programs, point to Microsoft Office Server, and then click SharePoint 3.0 Central Administration.
  • In the left navigation pane, click the name of the Shared Service Provider (SSP) to which you want to add the custom Web Part.

  • On the Shared Services Administration page, in the upper-right corner, click Site Actions, and then click Create.

  • On the Site Settings page, click Web Parts under the Galleries column.

  • On the Web Part Gallery page, to add the custom Web Part to the gallery, click New. At this point the custom Web Part is not available in the Web Part Gallery page.

  • On the New Web Parts page, locate CustomWebPart (name of the custom Web Part) in the list, select the check box on the left, and then click Populate Gallery on the top of the page. This will add the CustomWebPart entry in the Web Part Gallery page.

  • Now you can use the custom Web Part (CustomWebPart) to create Web Parts in your SharePoint portal. The custom Web Part (CustomWebPart) will appear under the Miscellaneous section in the Add Web Parts page.

     

    Expand

    BizTalk Adapter for mySAP Business Suite and the WCF LOB Adapter SDK

    This topic has not yet been rated Rate this topic

    The Microsoft BizTalk Adapter for mySAP Business Suite implements a set of core components that leverage functionality provided by the Microsoft Windows Communication Foundation (WCF) Line of Business (LOB) Adapter SDK and provide connectivity to the SAP system through the SAP Unicode RFC SDK Library (librfc32u.dll).

    The WCF LOB Adapter SDK serves as the software layer through which the SAP adapter interfaces with Windows Communication Foundation (WCF), and the RFC SDK serves as the layer through which the SAP adapter interfaces with the SAP system.

    The following figure shows the relationships between the internal components of the SAP adapter and between these components and the RFC SDK.

    The relationship of internal adapter components

    See

     

    When should I choose to create a mail app versus an add-in for Outlook?

    When should I choose to create a mail app versus an add-in for Outlook?

    Rate This
    PoorPoorFairFairAverageAverageGoodGoodExcellentExcellent

    Some of you may or may not be aware that alongside with the legacy COM-based Office client object models, Office 2013 supports a new apps for Office developer platform. This blog post is intended to help new and existing Office developers understand the main differences between the COM-based object models and the apps for Office platform. In particular, this post focuses on Outlook, suggests why you should consider developing solutions as mail apps, and identifies those exceptional scenarios where add-ins may still be the more appropriate choice.

    Contents:

    An introduction to the apps for Office platform

    Architectural differences between add-in model and apps for Office platform

    Main features available to mail apps

    Major objects for mail apps

    Reasons to create mail apps instead of add-ins for Outlook

    Reasons to choose add-ins

    Conclusion

    Further references

    An introduction to the apps for Office platform

    The apps for Office platform includes a JavaScript API for Office and a schema for apps for Office manifests. You can use this platform to extend web services and content into the context of rich and web clients of Office. An app for Office is a webpage that is developed using common web technologies, hosted inside an Office client application (such as Outlook) on-premises or in the cloud. Of the three types of apps for Office, the type that Outlook supports is called mail apps. While you use the legacy APIs—the object model, PIA, and MAPI—to automate Outlook at an application level, you can use the JavaScript API for Office in a mail app to interact at an item level with the content and properties of an email message, meeting request, or appointment. You can publish mail apps in the Office Store or in an internal Exchange catalog. End users and administrators can install mail apps for an Exchange 2013 mailbox, and use mail apps in the Outlook rich client as well as Outlook Web App. As a developer, you can choose to make your mail app available for end users on only the desktop, or also on the tablet or smart phone. You can find more information about the apps for Office platform by starting here: Overview of apps for Office.

    Architectural differences between add-in model and apps for Office platform

    Add-in model

    The Office add-in model offers individual object models for most of the Office rich clients. Each object model is intended to automate the corresponding Office client, and allows an add-in to integrate closely with the behavior of that client. The same add-in can integrate with one or multiple Office applications, such as Outlook, Word, and Excel, by calling into each of the Outlook, Word, and Excel object models. Figure 1 describes a few examples of 1:1 relationships between an Office rich client and its object model.

    Figure 1. The legacy Office development architecture is composed of individual client object models.

     

    Apps for Office platform

    The apps for Office platform includes an apps for Office schema. Using this schema, each app specifies a manifest that describes the permissions it requests, its requirements for its host applications (for example, a mail app requires the host to support the mailbox capability), its support for the default and any extra locales, display details for one or more form factors, and activation rules for a mail app to be available in the app bar.

    In addition to the schema, the apps for Office platform includes the JavaScript API for Office. This API spans across all supporting Office clients and allows apps to move toward a single code base. Rather than automating or extending a particular Office client at the application level, the apps for Office platform allows apps to connect to services and extend them into the context of a document, message, or appointment item in a rich or web client. Figure 2 shows Office applications with their rich and web clients sharing a common app platform.

    Figure 2. The apps for Office development architecture is composed of a common platform and individual object models.

     

    One main difference of note is that the object models were designed to integrate tightly with the corresponding Office client applications. However, this tight integration has a side effect of requiring an add-in to run in the same process as the rich client. The reliability and performance of an add-in often affects the perceived performance of the rich client. Unlike client add-ins, an app for Office doesn’t integrate as tightly with the host application, does not share the same process as the rich client, and instead runs in its own isolated runtime environment. This environment offers a privacy and permission model that allows users and IT administrators to monitor their ecosystem of apps and enjoy enhanced security.

    Main features available to mail apps

    Contextual activation: Mail app activation is contextual, based on the app’s activation rules and current circumstances, including the item that is currently displayed in the Reading Pane or inspector. A mail app is activated and becomes available to end users when such circumstances satisfy the activation rules in the app manifest.

    Matching known entities or regular expression: A mail app can specify certain entities (such as a phone number or address) or regular expressions in its activation rules. If a match for entities or regular expressions occurs in the item’s subject or body, the mail app can access the match for further processing.

    Roaming settings: A mail app can save data that is specific to Outlook and the user’s Exchange mailbox for access in a subsequent Outlook session.

    Accessing item properties: A mail app can access built-in properties of the current item, such as the sender, recipients, and subject of a message, or the location, start, end, organizer, and attendees of a meeting request.

    Creating item-level custom properties: A mail app can save item-specific data in the user’s Exchange mailbox for access in a subsequent Outlook session.

    Accessing user profile: A mail app can access the display name, email address, and time zone in the user’s profile.

    Authentication by identity tokens: A mail app can authenticate a user by using a token that identifies the user’s email account on an Exchange Server.

    Using Exchange Web Services: A mail app can perform more complex operations or get further data about an item through Exchange Web Services.

    Permissions model and governance: Mail apps support a three-tier permissions model. This model provides the basis for privacy and security for end users of mail apps.

    Major objects for mail apps

    For mail apps, you can look at the JavaScript API for Office object model in three layers:

    1. In the first layer, there are a few objects shared by all three types of apps for Office: Office, Context, and AsyncResult.
    2. The second layer in the API that is applicable and specific to mail apps includes the Mailbox, Item, and UserProfile objects, which support accessing information about the user and the item currently selected in the user’s mailbox.
    3. The third layer describes the data-level support for mail apps:
      1. There are CustomProperties and RoamingSettings that support persisting properties set up by the mail app for the selected item and for the user’s mailbox, respectively.
      2. There are the supported item objects, Appointment and Message, that inherit from Item, and the MeetingRequest object that inherits from Message. These objects represent the types of Outlook items that support mail apps: calendar items of appointments and meetings, and message items such as email messages, meeting requests, responses, and cancellations.
      3. Then there are the item-level properties (such as Appointment.subject) as well as objects and properties that support certain known Entities objects (for example Contact, MeetingSuggestion, PhoneNumber, and TaskSuggestion).

    Figure 3 shows the major objects: Mailbox, Item, UserProfile, Appointment, Message, Entities, and their members.

    Figure 3. Major objects and their members used by mail apps in the JavaScript API for Office.

    Figure 4 shows all of the objects and enumerations in the JavaScript API for Office that pertain to mail apps.

    Figure 4. All objects for mail apps in the JavaScript API for Office.

    Figure 5 is a thumbnail of a diagram with all the objects and members that mail apps use. Zoom into the diagram at http://go.microsoft.com/fwlink/?LinkId=317271.

    Figure 5. All objects and members used by mail apps in the JavaScript API for Office.

    The following are common reasons why mail apps are a better choice for developers than add-ins:

    • You can use existing knowledge of and the benefits of web technologies such as HTML, JavaScript, and CSS. For power users and new developers, XML, HTML, and JavaScript require less significant ramp-up time than COM-based APIs such as the Outlook object      model.
    • You can use a simple web deployment model to update your mail app (including the web services that the app uses) on your web server without any complex installation on the Outlook client. In fact, any updates to the mail app, with the exception of the app manifest, do not require any updating on the Office client. You can update the code or user interface of the mail app conveniently just on the web server. This presents a significant advantage over the administrative overhead involved in updating add-ins.
    • You can use a common web development platform for mail apps that can roam across the Outlook rich client and Outlook Web App on the desktop, tablet, and smartphone. On the other hand, add-ins use the object model for the Outlook rich client and, hence, can run on only that rich client on a desktop form factor.
    • You can enjoy rapid turnaround of building and releasing apps via the Office Store.
    • Because of the three-tier permissions model, users and administrators can appreciate better security and privacy in mail apps than add-ins, which have full access to the content of each account in the user’s profile. This, in turn, encourages user consumption of apps.
    • Depending on your scenarios, there are features unique to mail apps that you can take advantage of and that are not supported by add-ins:
      • You can specify a mail app to activate only for certain contexts (for example, Outlook displays the app in the app bar only if the message class of the user-selected appointment is IPM.Appointment.Contoso, or if the body of an email contains a package       tracking number or a customer identifier).
      • You can activate a mail app if the selected message contains some known entities, such as an address, contact, email address, meeting suggestion, or task suggestion.
      • You can take advantage of authentication by identity tokens and of Exchange Web Services.

    Reasons to choose add-ins

    The following features are unique to add-ins and may make them a more appropriate choice than mail apps in some circumstances:

    • You can use add-ins to extend or automate Outlook at an application-level, because the object model and PIA have extensive integration with Outlook features (such as all Outlook item types, user interface, sessions, and rules). At the item-level, add-ins can interact with an item in read or compose mode. With mail apps, you cannot automate Outlook at the application level, and you can extend Outlook’s functionality in the context of only the read-mode of the supported items (messages and appointments) in the user’s mailbox.
    • You can specify custom business logic for a new item type.
    • You can modify and add custom commands in the ribbon and Backstage view.
    • You can display a custom form page or form region.
    • You can detect events such as sending an item or modifying properties of an item.
    • You can use add-ins on Outlook 2013 and Exchange Server 2013, as well as earlier versions of Outlook and Exchange. On the other hand, mail apps work with Outlook and Exchange starting in Outlook 2013 and Exchange Server 2013, but not earlier versions.

    Conclusion

    When you are considering creating a solution for Outlook, first verify whether the supported major features and objects of the apps for Office platform meet your needs. Develop your solution as a mail app, if possible, to take advantage of the platform’s support across Outlook clients over the desktop, tablet, and smartphone form factors. Note that there are still some circumstances where add-ins are more appropriate, and you should prioritize the goals of your solution before making a decision.

    Further references

    Apps for Office and mail apps

    How To : Customize the Duet Workflow Task form in InfoPath 2013

    Contents

    • Introduction
    • Displaying the SAP business properties
    • Adding and deleting controls on the form
    • Adding heading images to the form and applying a theme

    Duet

    Introduction

    After a task site is published through SharePoint Designer, the task form ApprovalProcess.xsn is generated. The form has a default layout. But we may also want to display the SAP business properties, add some more controls relevant to the use of the form, or delete some irrelevant controls. We may also want to give a nice look and feel to the form. We can do these customizations easily with the help of InfoPath 2013.

    Scenario

    We have published a task site of the task type TestTask using SharePoint Designer 2013. The task form has the default layout shown below. We want to customize the form to include a SAP business property, add a control, remove a control, add a heading image, and apply a theme.

    Figure 1. TestTask task form with default layout

    Figure 1. TestTask task form with default layout

    Displaying the SAP business properties

    Prerequisite: We can display the SAP business properties in the workflow task form provided that we have included the properties in the Extended Business Properties text box while creating the task site.

    Steps:

    1. In SharePoint Designer, click ApprovalProcess.xsn.

    Figure 2. ApprovalProcess.xsn in SharePoint Designer

    Figure 2. ApprovalProcess.xsn in SharePoint Designer

    InfoPath Designer opens with an auto-generated layout of the form.

    Figure 3. InfoPath Designer with auto-generated layout of the TestTask form

    Figure 3. InfoPath Designer with auto-generated layout of the TestTask form

    2. Insert a new row, wherever you want, for the business property LeaveDaysUsedTillToday that you want to display in the form.

    a. In the first column, enter the field name as you want to see it displayed in the form, for example,Leaves Used Till Today.

    Figure 4. Entering field name in the first column
    Figure 4. Entering field name in the first column

    b. In the second column, we need to get the value for the business property LeavesUsedTillTodayfrom the Workflow Business Document Library. Thus, we need to create a secondary data connection with the Workflow Business Document Library.

    3. Create a secondary data connection with the Workflow Business Document Library as follows: 

    a. Under Actions, click Manage Data Connections.

    Figure 5. Clicking Manage Data Connections in InfoPath
    Figure 5. Clicking Manage Data Connections in InfoPath

    The Data Connections dialog box appears.

    Figure 6. Data Connections dialog box

    Figure 6. Data Connections dialog box

    b. In the Data Connections dialog box, select Context  from the list of Data Connections for the form template, and click Add. The Data Connection Wizard starts.

    Figure 7. Data Connection Wizard

    Figure 7. Data Connection Wizard

    c. Click Next without changing any settings. The wizard now asks for the source of data. SelectSharePoint library or list as the source of data.

    Figure 8. Selecting SharePoint library or list in the Data Connection Wizard

    Figure 8. Selecting SharePoint library or list in the Data Connection Wizard

    d. Click Next. The wizard now prompts you to enter the location of the SharePoint site.

    e. Enter the URL of the task site, and click Next.

    Figure 9. Entering task site location in the Data Connection Wizard

    Figure 9. Entering task site location in the Data Connection Wizard

    f. Select the Workflow Business Data Document Library for the data connection, and click Next.

    Figure 10. Selecting Workflow Business Data Document Library for the data connection

    Figure 10. Selecting Workflow Business Data Document Library for the data connection

    g. Select the Title and LeavesUsedTillToday fields, and click Next. The Title field will help us filter the data corresponding to a task from the Workflow Business Data Document Library. The Title field is the concatenation of the Related Content field in the main data connection and the string “.xml“.

    Figure 11. Selecting the Title field and LeaveDaysUsedTillToday field

    Figure 11. Selecting the Title field and LeaveDaysUsedTillToday field

    h. Click Next.

    Figure 12. Data Connection Wizard

    Figure 12. Data Connection Wizard

    i. Click Finish.

    Figure 13. Finishing the Data Connection Wizard

    Figure 13. Finishing the Data Connection Wizard

    j. Close the Data Connections dialog box that now has the data connection to the Workflow Business Data Document Library.

    Figure 14. Data Connections dialog box with the new data connection

    Figure 14. Data Connections dialog box with the new data connection

    4. Click in the second column of the new row that we inserted in step 3. On the Home tab in the ribbon, click Calculated Value (fx) button in the Controls pane.

    Figure 15. Choosing Calculated Value in InfoPath

    Figure 15. Choosing Calculated Value in InfoPath

    The Insert Calculated Value dialog box appears.

    5. Click the fx button next to the XPath text box.

    Figure 16. Insert Calculated Value dialog box

    Figure 16. Insert Calculated Value dialog box

    The Insert Formula dialog box appears as shown in the following figure.

    6. Click Insert Field or Group.

    Figure 17. Insert Field or Group button

    Figure 17. Insert Field or Group button

    The Select a Field or Group dialog box appears, as shown in the following figure.

    7. Click Show advanced view.

    Figure 18. Show advanced view link

    Figure 18. Show advanced view link

    Now, we have the option to select the data connection also. 

    Figure 19. Select a Field or Group dialog box

    Figure 19. Select a Field or Group dialog box

    8. Select the secondary data connection to the Workflow Business Document Library from the drop-down list.

    Figure 20. Choosing a secondary data connection

    Figure 20. Choosing a secondary data connection

    9. Expand the dataFields tree structure until you see LeaveDaysUsedTillToday. SelectLeaveDaysUsedTillToday. Since we want to get only the business property for the corresponding task, we need to filter the data received from the data connection. Click Filter Data.

    Figure 21. Filter Data button

    Figure 21. Filter Data button

    10. The Filter Data dialog box appears. Click Add.

    Figure 22. Add button in the Filter Data dialog box

    Figure 22. Add button in the Filter Data dialog box

    The Specify Filter Conditions dialog box appears.

    Figure 23. Specify Filter Conditions dialog box

    Figure 23. Specify Filter Conditions dialog box

    11. Specify the filter conditions as follows:

    a. In the first drop-down list, choose Select a field or group.

    Figure 24. Choosing Select a field or group
    Figure 24. Choosing Select a field or group

    b. Choose Workflow Business Data Document Library as the data source.

    c. Expand the dataFields tree structure until you see Title. Select Title, and then click OK.

    Figure 25. Title in the Select a Field or Group dialog box

    Figure 25. Title in the Select a Field or Group dialog box

    d. In the second drop-down list in the Specify Filter Conditions dialog box, select is equal to.

    e. In the third drop-down list in the Specify Filter Conditions dialog box, select Use a formula.

    Figure 26. Selecting Use a formula in the list

    Figure 26. Selecting Use a formula in the list

    f. The Insert Formula dialog box opens. Click Insert Function.

    Figure 27. Insert Function button

    Figure 27. Insert Function button

    The Insert Function dialog box opens.

    Figure 28. Insert Function dialog box

    Figure 28. Insert Function dialog box

    g. Select Text in the Categories list, and then select concat in the Functions list. Click OK.

    Figure 29. Choosing category and function

    Figure 29. Choosing category and function

    The formula corresponding to the selection appears in the Insert Formula dialog box.

    Figure 30. Concat Formula prototype (skeleton) in the Insert Formula dialog box

    Figure 30. Concat Formula prototype (skeleton) in the Insert Formula dialog box

    h. Double-click the first argument in the concat function. The Select a Field or Group dialog box opens. Under the Main data connection, expand the dataFields tree structure till you see Related Content. Select the subfield :Description under Related Content. Click OK.

    Figure 31. :Description subfield under Related Content

    Figure 31. :Description subfield under Related Content

    i. Write the string “.xml” as the second argument in the concat function. Delete the comma following the second argument and the third argument.

    The updated formula is as shown in the following figure. Click OK.

    Figure 32. Updated concat formula (with provided arguments) in Insert Formula dialog box

    Figure 32. Updated concat formula (with provided arguments) in Insert Formula dialog box

    j. Click OK in the dialog boxes in the order: Specify Filter Conditions, Filter Data, Select a Field or Group.

    The final overall formula appears in the Insert Formula dialog box. (This dialog box was opened in step 5 and is still open)

    Figure 33. Final formula in the Insert Formula dialog box

    Figure 33. Final formula in the Insert Formula dialog box

    12. Click OK in the Insert Formula dialog box (shown above) to return to the Insert Calculated Valuedialog box where the XPath corresponding to our selections has been updated.

    Figure 34. Updated XPath in the Insert Calculated Value dialog box

    Figure 34. Updated XPath in the Insert Calculated Value dialog box

    Click OK.

    13. Click the File tab on the ribbon. Click Quick Publish.

    Figure 35. Publish your form

    Figure 35. Publish your form

    14. The Save As dialog box opens.

    Figure 36. Saving the form template

    Figure 36. Saving the form template

    15. Click Save. The Microsoft InfoPath dialog box stating the successful publishing of the form template appears. Click OK.

    Figure 37. Form template published successfully

    Figure 37. Form template published successfully

    16. Open the task site and look up any of the tasks. The task appears as shown in the following figure. The SAP business property LeavesUsedTillToday has the value 10 in this task.

    Figure 38. Task on the task site with LeavesUsedTillToday business property

    Figure 38. Task on the task site with LeavesUsedTillToday business property

    Adding and deleting controls on a form

    Suppose we want to add a control—for example, ID—from the main data connection to the workflow task form, and delete the control Consolidated Comments from the form.

    1. Insert a new row for the ID field.

    Figure 39. Inserting a new row for the ID field

    Figure 39. Inserting a new row for the ID field

    2.  Drag the ID field from the Fields task pane onto the canvas. The label for the control appears automatically in the left column when you drag the field into the right column of the table. However, this is true only if you highlight both columns when you release the mouse.

    Figure 40. ID field in right column

    Figure 40. ID field in right column

    3. Delete the row containing the control for Consolidated Comments.

    Figure 41. Consolidated Comments row deleted

    Figure 41. Consolidated Comments row deleted

    3. Click the File tab on the ribbon. Click Quick Publish. The Microsoft InfoPath dialog box stating the successful publishing of the form template appears.

    4. Click OK.

    5. Open the task site and look up any of the tasks. The task appears as shown in the following figure. The task has the ID field with value 1 and no Consolidated Comments control.

    Figure 42. Task on the task site with ID control and without Consolidated Comments control
    Figure 42. Task on the task site with ID control and without Consolidated Comments control

    Adding heading images to the form and applying a theme

    1. Place your cursor in the title area of the page layout. Add a title—for example, MyTask—in the required format and font.

    Figure 43. Title area of the page layout

    Figure 43. Title area of the page layout

    2. Add the heading image to the form by inserting a picture from the Insert tab on the ribbon.

    3. On the Page Design tab, apply the Professional – Standard theme. The easiest way to select the theme is to expand the Themes gallery by clicking the arrow at the lower-right corner. Professional – Standard is the first theme in the Professional section.

    Figure 44. Page Design tab

    Figure 44. Page Design tab

    The title, heading image, and page design should now resemble the following figure.

    Figure 45. New title, heading image, and page design

    Figure 45. New title, heading image, and page design

    4. Click the File tab on the ribbon. Click Quick Publish. The Microsoft InfoPath dialog box stating the successful publishing of the form template appears.

    5. Click OK.

    6. Open the task site and look up any of the tasks. The task appears as shown in the following figure. The task has the desired heading image and theme.

    Figure 46. Task on the task site with desired heading image and theme

    Figure 46. Task on the task site with desired heading image and theme

    SharePoint Development roles urgently needs to be filled at MS Gold Partner – Contact me now for more information (Sorry, No recruiters, i am filling private positions)

    Senior SharePoint Developers needed urgently for MS Gold Partner in Sandton/Bryanston :

    3 – 5 years of development experience.

    2 year experience in SharePoint.

    3 years experience in C#.

    A minimum of 3 years experience in Visual Studio .NET 2005 – 2008.

    A minimum of 3 years experience in ASP.NET , HTML web development.

    A minimum of 3 years experience with Javascript.

    A minimum of 3 years experience with Windows XP, Windows 2003 and Windows Vista.

    A minimum of 3 years experience in relational database design and implementation with SQL Server
    Advantageous (nice-to-have):

    • Windows SharePoint Server.
    • Microsoft Office SharePoint Server.
    • BizTalk
    • Web Analytics
    • Microsoft CRM
    • K2

    Creating Nintex Workflow Custom Actions

    Nintex is a great product to create Workflows with within SharePoint. Much more flexible than SharePoint Designer, and far less complicated than using Visual Studio. There is an extensive list of Actions already for Nintex Workflow sometimes you need a Custom Action that is specific for your business such as bring back data from your bespoke application, or UNIX text file. This blog will explain the different parts of creating a custom action to you.

    Above picture showing you collection of Actions that comes with Nintex Workflow.

    To build a custom action, unfortunately, there is a collection of files you are require to create, even though there is only one real section that performs the actual business logic. The rest of it is all supporting code. Below is a basic project setup of all the files you need. I will explain each section throughout this post. With a walkthrough at the end of how to create a ReadFromPropertyBag Custom Action.

    References

    Before we can even start we require the following References.

    • System.Workflow.Activities.dll (Not shown in above picture. Forgot to add before took picture.)
    • Microsoft.SharePoint.dll
    • Microsoft.SharePoint.WorkflowActions.dll
    • System.Workflow.ComponentModel.dll
    • Nintex.Workflow.dll – Can be found at C:\Program Files\Nintex\Nintex Workflow 2010\Binaries.
    • Nintex.Workflow.ServerControls.dll – Can be found at C:\Program Files\Nintex\Nintex Workflow 2010\Binaries. (Not shown in above picture. Forgot to add before took picture.)

    Features

    A WebApplication feature that when activated it will add the Custom Action to the Web Application and authorize it to be used within the web application.

    CustomActions –ActionName – NWAFile

    An element file, which holds an XML file which is all the required details for a NintexWorkflowActivity. It is this file that is read in by the Feature receiver to be able to add the custom action to the web application.

    CustomActions – ActionName – ActionNameActivity

    A class that is inherited by Nintex.Workflow.Activities.ProgressTrackingActivity. This file contains all the Dependency properties to the activity. The Dependency Properties are object properties that can be bound to other elements of a workflow, such as workflow variables or dependency properties of other activities. They are used to store the data that the activity will require or to output data from the activity. This is also the file that contains the execution of the actual business logic.

    CustomActions – ActionName – ActionNameAdapter

    A class that is inherited by Nintex.Workflow.Activities.Adapters.GenericRenderingAction. You will need to implement the abstract class of GenericRenderingAction. These implementations

    • GetDefaultConfig() – define the parameters that the user can configure for this action and sets the default label for the action.
    • ValidateConfig() – Adds logic to validate the configuration here, and will display any error messages to the user if there is an issue.
    • AddActivityToWorkflow() – Creates an instance of the Activity and set its properties based on config. Then it adds it to the parent activity.
    • GetConfig() – Reads the property from the context.Activity and update the values in the NWActionConfig.
    • BuildSummary() – Constructs an Action Summary class to display details about this action.

    I find the Adapter is very similar for every Action. Once you have the basic of one, just by adding an extra parameter or removing one you can quickly put an adapter together for any Custom Action.

    Layouts – NintexWorkflow – CustomActions – ActionName – Images

    I have two icon .png files in here. One is sized at 49×49 pixels and the other at 30×30 pixels. These files are referenced in the NWAFile, and used to display the custom action to the user in the toolbox area (30×30), or in the actual workflow itself (49×49).

    You could add a third one here for Warning Icon. This is where the custom action isn’t configured. This would be a 49×49 pixel too.

    Layouts – NintexWorkflow – CustomActions – ActionName – ActionNameDialog

    An application page inherited from Nintex.Workflow.ServerControls.NintexLayoutBase. The dialog is what appears to the user when they have to configure the custom action through the browser. Here there is no code behind. You mainly display the controls in the aspx and set up two javascript functions to read in and read out the configuration on load and save.

    Walkthrough creating ReadFromPropertyBag Custom Action.

    Now that you understand the basic roles of all the files required to make one custom action I will walk through creating a custom action that will read from the current SPWeb property bag. The user will pass in the “Property name” to obtain the value.

    If you create a Solution with the similar layout my solution layout above, replacing “ActionName” with ReadFromPropertyBag. Your solution and file layouts should look similar to below.

    ReadFromPropertyBagActivity.cs

    Starting with the ReadFromPropertyBagActivity file. This inherits Nintex.Workflow.Activities.ProgressTrackingActivity. We will first add all the public static DependencyProperties. The default ones are __ListItem, __Context and __ListId. Then we will add 2 of our own, One to hold the the Property Name and the ResultOuput. You can delete the designer.cs file.

    Each DependencyProperty will have its own public property.

    using System;
    using System.Workflow.ComponentModel;
    using Microsoft.SharePoint.Workflow;
    using Microsoft.SharePoint.WorkflowActions;
    using Nintex.Workflow;
    using Microsoft.SharePoint;
    namespace CFSP.CustomActions.ReadFromPropertyBag
    {
        public class ReadFromPropertyBagActivity : Nintex.Workflow.Activities.ProgressTrackingActivity
        {
            public static DependencyProperty __ListItemProperty = DependencyProperty.Register("__ListItem", typeof (SPItemKey), typeof (ReadFromPropertyBagActivity));
            public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context", typeof (WorkflowContext), typeof (ReadFromPropertyBagActivity));
     
            public static DependencyProperty __ListIdProperty = DependencyProperty.Register("__ListId", typeof (string),typeof (ReadFromPropertyBagActivity));
            public static DependencyProperty PropertyProperty = DependencyProperty.Register("Property", typeof (string), typeof (ReadFromPropertyBagActivity));
            public static DependencyProperty ResultOutputProperty = DependencyProperty.Register("ResultOutput", typeof (string), typeof (ReadFromPropertyBagActivity));
     
            public WorkflowContext __Context
            {
                get { return (WorkflowContext) base.GetValue(__ContextProperty); }
                set { base.SetValue(__ContextProperty, value); }
            }
     
            public SPItemKey __ListItem
            {
                get { return (SPItemKey) base.GetValue(__ListItemProperty); }
                set { base.SetValue(__ListItemProperty, value); }
            }
     
            public string __ListId
            {
                get { return (string) base.GetValue(__ListIdProperty); }
                set { base.SetValue(__ListIdProperty, value);}
            }
     
            public string Property
            {
                get { return (string) base.GetValue(PropertyProperty); }
                set { base.SetValue(PropertyProperty, value);}
            }
     
            public string ResultOutput
            {
                get { return (string) base.GetValue(ResultOutputProperty); }
                set {base.SetValue(ResultOutputProperty, value);}
            }
     
            public ReadFromPropertyBagActivity()
            {
            }
     
           protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
            {
            }
            protected override ActivityExecutionStatus HandleFault(ActivityExecutionContext executionContext, Exception exception)
            {
            }
        }
    }

    Now we will need to override the Execute() method. This is the main business logic of your Custom Action.

    protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
         {
             //Standard Nintex code to obtain context.
             ActivityActivationReference.IsAllowed(this, __Context.Web);
             NWWorkflowContext ctx = NWWorkflowContext.GetContext(
                this.__Context,
                new Guid(this.__ListId),
                this.__ListItem.Id,
                this.WorkflowInstanceId,
                this);
     
             base.LogProgressStart(ctx);
             //Get the property value.
             string resolvedProperty = ctx.AddContextDataToString(this.Property);
     
             var result = "";
     
             //Using the context get the property if it exists.
             if (ctx.Web.AllProperties.ContainsKey(resolvedProperty))
             {
                 result = ctx.Web.AllProperties[resolvedProperty].ToString();
             }
             //store the result.
             this.ResultOutput = result;
     
             //End Execution.
             base.LogProgressEnd(ctx, executionContext);
             return ActivityExecutionStatus.Closed;
        }

    The last thing we need to do in this class is to handle if there is a fault during execution. Overwrite the HandleFault code with the following. You can make the error say whatever you like. I’m just referencing the item that called the workflow.

    protected override ActivityExecutionStatus HandleFault(ActivityExecutionContext executionContext, Exception exception)
            {
                Nintex.Workflow.Diagnostics.ActivityErrorHandler.HandleFault(executionContext, exception,
                    this.WorkflowInstanceId, "Error Reading from Property Bag", __ListItem.Id, __ListId, __Context);
                return base.HandleFault(executionContext, exception);
            }

    ReadFromPropertyBagAdapter.cs

    Moving onto the Adapter file now. This class inherits the Nintex.Workflow.Activies.Adapters.GenericRenderingAction and needs to implement 5 overrides. I have also included two private constants strings. These are the property names we declared in the Activity class. Ensure these names match, or you will encounter errors later which takes a while to debug.

    using System;
    using System.Collections.Generic;
    using System.Workflow.ComponentModel;
    using Microsoft.SharePoint;
    using Nintex.Workflow;
    using Nintex.Workflow.Activities.Adapters;
     
    namespace CFSP.CustomActions.ReadFromPropertyBag
    {
        public class ReadFromPropertyBagAdapter : GenericRenderingAction
        {
           //Values should match the property names in the ReadFromPropertyBagActivity class.
            private const string PropertyProperty = "Property";
            private const string ResultOutputProperty = "ResultOutput";
     
           public override NWActionConfig GetDefaultConfig(GetDefaultConfigContext context)
            {
                throw new NotImplementedException();
            }
     
            public override bool ValidateConfig(ActivityContext context)
            {
                throw new NotImplementedException();
            }
            public override CompositeActivity AddActivityToWorkflow(PublishContext context)
            {
                throw new NotImplementedException();
            }
     
            public override NWActionConfig GetConfig(RetrieveConfigContext context)
            {
                throw new NotImplementedException();
            }
     
            public override ActionSummary BuildSummary(ActivityContext context)
            {
                throw new NotImplementedException();
            }
       }
    }

    I will explain each override before showing you the code.

    GetDefaultConfig sections allows you to set up the parameters for user input and outputs. If you wish the user to freely type a value use a PrimitiveValue. If you would like the user to use a predefined value that would be a variable somewhere in the workflow then use NWWorkflowVariable value. Typically the output would always be written back to a Workflow Variable so this will be a Variable type of NWWorkflowVariable. Add an ActivityParameter for each property.

    public override NWActionConfig GetDefaultConfig(GetDefaultConfigContext context)
           {
                NWActionConfig config = new NWActionConfig(this);
                //define the number of parameters one for each custom parameter.
                config.Parameters = new ActivityParameter[2];
                //define the parameters that the user can configure for this action.
                config.Parameters[0] = new ActivityParameter();
                config.Parameters[0].Name = PropertyProperty;
                config.Parameters[0].PrimitiveValue = new PrimitiveValue();
                config.Parameters[0].PrimitiveValue.Value = string.Empty;
                config.Parameters[0].PrimitiveValue.ValueType = SPFieldType.Text.ToString();
     
                config.Parameters[1] = new ActivityParameter();
                config.Parameters[1].Name = ResultOutputProperty;
                config.Parameters[1].Variable = new NWWorkflowVariable();
     
                //set the default label for the action.
                config.TLabel = ActivityReferenceCollection.FindByAdapter(this).Name;
                return config;
           }

    ValidateConfig section allows you to validate the values entered. Here I’m just ensuring the value are not blank. You would add a validation for each input property.

    public override bool ValidateConfig(ActivityContext context)
    {
                //Add logic to validate the configuration here.
                bool isValid = true;
                Dictionary<string, ActivityParameterHelper> parameters = context.Configuration.GetParameterHelpers();
                if (!parameters[PropertyProperty].Validate(typeof(string), context))
                {
                    isValid &= false;
                    validationSummary.AddError("Property Bag", ValidationSummaryErrorType.CannotBeBlank);
                }
                return isValid;
    }

    Validation is shown in image below.

    AddActivityToWorkflow creates an instance of the Activity and set its properties based on config. You also bind the default properties. Assign each parameter you have here. Lastly attach the Activity Flags. Then add it all to the parent activity.

    <strong>  </strong>public override CompositeActivity AddActivityToWorkflow(PublishContext context)
            {
                Dictionary<string, ActivityParameterHelper> parameters = context.Config.GetParameterHelpers();
                ReadFromPropertyBagActivity activity = new ReadFromPropertyBagActivity();
     
                parameters[PropertyProperty].AssignTo(activity, ReadFromPropertyBagActivity.PropertyProperty, context);
                parameters[ResultOutputProperty].AssignTo(activity, ReadFromPropertyBagActivity.ResultOutputProperty, context);
                activity.SetBinding(ReadFromPropertyBagActivity.__ContextProperty, new ActivityBind(context.ParentWorkflow.Name, StandardWorkflowDataItems.__context));
                activity.SetBinding(ReadFromPropertyBagActivity.__ListItemProperty, new ActivityBind(context.ParentWorkflow.Name, StandardWorkflowDataItems.__item));
     
                activity.SetBinding(ReadFromPropertyBagActivity.__ListIdProperty, new ActivityBind(context.ParentWorkflow.Name, StandardWorkflowDataItems.__list));
     
                ActivityFlags f = new ActivityFlags();
                f.AddLabelsFromConfig(context);
                f.AssignTo(activity);
     
                context.ParentActivity.Activities.Add(activity);
                return null;
            }

    GetConfig reads the properties from the context.Activity and updates the values in the NWActionConfig. Add a new parameter for each property. You can see when we RetrieveValue from our activity, we are grabbing the corresponding DependencyProperty from our activity.

    public override NWActionConfig GetConfig(RetrieveConfigContext context)
            {
                //Read the properties from the context.ACtivity and update the values in the NWActionConfig
     
                NWActionConfig config = this.GetDefaultConfig(context);
                Dictionary<string, ActivityParameterHelper> parameters = config.GetParameterHelpers();
                parameters[PropertyProperty].RetrieveValue(context.Activity, ReadFromPropertyBagActivity.PropertyProperty, context);
                parameters[ResultOutputProperty].RetrieveValue(context.Activity, ReadFromPropertyBagActivity.ResultOutputProperty, context);
     
                return config;
     
            }

    BuildSummary is the last implemented override method. The code here writes out the summary displayed to the user after that have configured the action and hovered the mouse over the custom action.

    public override ActionSummary BuildSummary(ActivityContext context)
            {
               // Construct an ActionSummary class to display details about this action.
     
                Dictionary<string, ActivityParameterHelper> parameters = context.Configuration.GetParameterHelpers();
                return new ActionSummary("Retrieve the following Property bag: {0}", parameters[PropertyProperty].Value);
     
            }

    BuildSummary is displayed below on mouse hover once item has been configured.

    ReadFromPropertyBagDialog.aspx

    The code behind for this aspx file inherits from Nintex.Workflow.ServerControls.NintexLayoutsBase. Apart from changing the inheriting type, there is no need to do anything else in the .cs file. In the aspx file we would have the basic structure. This structure contains the link up to your page behind, register all the Nintex controls required, the two main JavaScript functions to read and save the configuration, and lastly the display section of your page.

    <%@ Page Language="C#" DynamicMasterPageFile="~masterurl/default.master" AutoEventWireup="true" CodeBehind="ReadFromPropertyBagDialog.aspx.cs" EnableEventValidation="false"
     
        Inherits="CFSP.CustomActions.ReadFromPropertyBag.ReadFromPropertyBagDialog, $SharePoint.Project.AssemblyFullName$" %>
    <%@ Register TagPrefix="Nintex" Namespace="Nintex.Workflow.ServerControls" Assembly="Nintex.Workflow.ServerControls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=913f6bae0ca5ae12" %>
     
    <%@ Register TagPrefix="Nintex" TagName="ConfigurationPropertySection" src="~/_layouts/NintexWorkflow/ConfigurationPropertySection.ascx" %>
     
    <%@ Register TagPrefix="Nintex" TagName="ConfigurationProperty" src="~/_layouts/NintexWorkflow/ConfigurationProperty.ascx" %>
     
    <%@ Register TagPrefix="Nintex" TagName="DialogLoad" Src="~/_layouts/NintexWorkflow/DialogLoad.ascx" %>
     
    <%@ Register TagPrefix="Nintex" TagName="DialogBody" Src="~/_layouts/NintexWorkflow/DialogBody.ascx" %>
     
    <%@ Register TagPrefix="Nintex" TagName="SingleLineInput" Src="~/_layouts/NintexWorkflow/SingleLineInput.ascx" %>
     
    <%@ Register TagPrefix="Nintex" TagName="PlainTextWebControl" Src="~/_layouts/NintexWorkflow/PlainTextWebControl.ascx" %>
     
    <asp:Content ID="ContentHead" ContentPlaceHolderID="PlaceHolderAdditionalPageHead" runat="server">
     
        <Nintex:DialogLoad runat="server" />
        <script type="text/javascript" language="javascript">
            function TPARetrieveConfig() {
           //To Do
            }
     
            function TPAWriteConfig() {
            //To Do
            }
     
            onLoadFunctions[onLoadFunctions.length] = function () {
                dialogSectionsArray["<%= MainControls1.ClientID %>"] = true;
            };
        </script>
    </asp:Content>
     
    <asp:Content ID="ContentBody" ContentPlaceHolderID="PlaceHolderMain" runat="Server">
      <Nintex:ConfigurationPropertySection runat="server" Id="MainControls1">
                 <TemplateRowsArea>
                       <!--ToDo-->
                  </TemplateRowsArea>
     </Nintex:ConfigurationPropertySection>
     
      <Nintex:DialogBody runat="server" id="DialogBody">
      </Nintex:DialogBody>
    </asp:Content>

    First section we will fill in will be the Nintex:ConfigurationPropertySection within the ContentPlaceHolderID PlaceHolderMain. In here we need to create a Nintex:ConfigurationProperty for each configuration property. In our case here that will be the Property Bag Name and the Result. You can see from below for consistency I have given the ID of the controls the same name as the Dependency Properties. Also note that the output because I’m want the user to assign the results to a workflow property, I’m using the Nintex:VariableSelector control.

    <Nintex:ConfigurationProperty runat="server" FieldTitle="Property Bag Property" RequiredField="True">
           <TemplateControlArea>
                <Nintex:SingleLineInput clearFieldOnInsert="true" filter="number" runat="server" id="propertyProperty"></Nintex:SingleLineInput>
          </TemplateControlArea>
        </Nintex:ConfigurationProperty>
        <Nintex:ConfigurationProperty runat="server" FieldTitle="Result Output" RequiredField="False">
          <TemplateControlArea>
            <Nintex:VariableSelector id="resultOutput" runat="server" IncludeTextVars="True"></Nintex:VariableSelector>
          </TemplateControlArea>
     
        </Nintex:ConfigurationProperty>

    Next we are going to look at the two JavaScript files. When the dialog page is rendered and saved it passed an XML file, known as the configXml. We need to read out and read into the XML file using XPath. Please note when you come to deploying, if you find that your dialog control loads, however the ribbon bar is disabled at the top of the dialog, it is most likely that you have an error in the JavaScript. This took me a while to diagnose, but now I know what causes the issue, it allowed me to fix it straight away.

    From the TPARetrieveConfig code the [@Name=’ ‘] will always be the public property name you gave it in the ReadFromPropertyBagActivity.cs file. As you can see from the code below there is a different way to obtain the value depending if the configuration property is a PrimitiveValue or a WorkflowVariable. This you defined in the GetDefaultConfig() method within the ReadFromPropertyBagAdapter.cs file. Lastly if you are still having problems getting the value, ensure your XPath is correct by debugging the Javascript and viewing the configXML variable.

    function TPARetrieveConfig() {
               setRTEValue('<%=propertyProperty.ClientID%>', configXml.selectSingleNode("/NWActionConfig/Parameters/Parameter[@Name='Property']/PrimitiveValue/@Value").text);
     
               document.getElementById('<%=resultOutput.ClientID%>').value = configXml.selectSingleNode("/NWActionConfig/Parameters/Parameter[@Name='ResultOutput']/Variable/@Name").text;
     
           }

    From the TPAWriteConfig code it is basically doing the opposite of TPARetrieveConfig, just it checks the dropdown control (resultOutput) that a value has been selected before saving.

    function TPAWriteConfig() {
               configXml.selectSingleNode("/NWActionConfig/Parameters/Parameter[@Name='Property']/PrimitiveValue/@Value").text = getRTEValue('<%=propertyProperty.ClientID%>');
     
               var resultOuputCtrl = document.getElementById('<%=resultOutput.ClientID%>');
     
               if (resultOuputCtrl.value.length > 0) {
                   configXml.selectSingleNode("/NWActionConfig/Parameters/Parameter[@Name='ResultOutput']/Variable/@Name").text = resultOuputCtrl.value;
               }
     
               return true;
           }

    ReadFromPropertyBagAction.nwa

    The NWA file as stated previously is just an XML file. This file is used by the Feature Receiver to register the custom action within SharePoint WebApplication.

    First thing we need to do is from the properties window (press F4) we need to change the build action from None to Content, change the deployment type to ElementFile and remove the Path “\NWAFile”.

    From within the XML file, remove all text and then place the following in.

    <NintexWorkflowActivity>
      <Name>Retrieve from Property Bag</Name>
      <Category>CannonFodder Category</Category>
      <Description>A custom action to retrieve a property from the SharePoint Web Property Bag.</Description>
      <ActivityType>CFSP.CustomActions.ReadFromPropertyBag.ReadFromPropertyBagActivity</ActivityType>
      <ActivityAssembly>$SharePoint.Project.AssemblyFullName$</ActivityAssembly>
      <AdapterType>CFSP.CustomActions.ReadFromPropertyBag.ReadFromPropertyBagAdapter</AdapterType>
      <AdapterAssembly>$SharePoint.Project.AssemblyFullName$</AdapterAssembly>
      <HandlerUrl>ActivityServer.ashx</HandlerUrl>
      <Icon>/_layouts/NintexWorkflow/CustomActions/ReadFromPropertyBag/Images/ReadFromPropertyBagIcon49x49.png</Icon>
      <ToolboxIcon>/_layouts/NintexWorkflow/CustomActions/ReadFromPropertyBag/Images/ReadFromPropertyBagIconSmall30x30.png</ToolboxIcon>
      <ConfigurationDialogUrl>CustomActions/ReadFromPropertyBag/ReadFromPropertyBagDialog.aspx</ConfigurationDialogUrl>
      <ShowInCommonActions>yes</ShowInCommonActions>
      <DocumentLibrariesOnly>no</DocumentLibrariesOnly>
    </NintexWorkflowActivity>

    Let me explain each line to you.

    • Name – The display name of the custom action
    • Category – The category in the toolbox area that the custom action will be displayed under.
    • Description – A description of the category.
    • ActivityType – The Namespace of the Activity.cs file.
    • ActivityAssembly – The Full assembly name. (I’m using a token, which I’ll show how to set up afterwards)
    • AdapterType – The Namespace of the Adapter.cs file.
    • AdapterAssembly – The full assembly name. (I’m using a token, which I’ll show how to set up afterwards)
    • HandlerUrl – The Nintex handler, this will always be ActivityServer.ashx
    • Icon – The URL to the larger Icon.
    • ToolboxIcon – The URL to the smaller icon.
    • WarningIcon – The URL to the Warning Icon <-Not used in the above XML.
    • ConfigurationDialogUrl – The URL to the Action Dialog file. Note that we don’t put /_layouts/NintexWorkflow at the front.
    • ShowInCommonActions – If this custom action shows up in CommonActions on the toolbox.
    • DocumentLibrariesOnly – If this custom action should only be used in DocumentLibraries or not.

    Getting the Token $SharePoint.Project.AssemblyFullName$ to replace on a build.

    At this point, save and close your solution. Now open up your .csproj file in Notepad or Notepad++. At the bottom of your first <PropertyGroup> section add the following XML. Save the file and re-open your solution in Visual Studio.

    <TokenReplacementFileExtensions>nwa</TokenReplacementFileExtensions>

    When you build your solution, Visual Studio will replace your token with the actual Full Assembly Name. More information about TokenReplacementFileExtensions.

    WebApplication – Custom Action EventReceiver.cs

    The Feature Event receiver is the final piece to our custom action. This will deploy or remove our custom action and make it available to the Web Application by modifying the Web.Config and registering the Action with Nintex within the farm. To add the custom action we use the nwa file. To remove it we need to know the namespace of the adapter, and assembly name. As you build more custom actions you can reuse this feature and just de-activate and re-activate each time you deploy a new custom action.

    using System;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Xml;
    using Microsoft.SharePoint;
    using Microsoft.SharePoint.Administration;
    using Nintex.Workflow;
    using Nintex.Workflow.Administration;
    using Nintex.Workflow.Common;
    using System.Reflection;
    namespace CFSP.CustomActions.Features.WebApplication___Custom_Actions
    {
        [Guid("07607091-449b-422b-94e4-84e6d863eb9e")]
        public class WebApplication___Custom_ActionsEventReceiver : SPFeatureReceiver
        {
            public override void FeatureActivated(SPFeatureReceiverProperties properties)
            {
                SPWebApplication parent = (SPWebApplication) properties.Feature.Parent;
                AddCustomAction(parent, properties, "ReadFromPropertyBagAction.nwa");
               //Add additional Custom Actions nwa files here.
            }
            public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
            {
                SPWebApplication parent = (SPWebApplication) properties.Feature.Parent;
                RemoveCustomAction(parent, properties,
                    "CFSP.CustomActions.ReadFromPropertyBag.ReadFromPropertyBagAdapter",
                    Assembly.GetExecutingAssembly().FullName);
               //Remove additional Custom Actions here.
            }
     
            protected void AddCustomAction(SPWebApplication parent, SPFeatureReceiverProperties properties,
                string pathToNWAFile)
            {
                // First step is register the action to the Nintex Workflow database
                XmlDocument nwaXml = GetNWADefinition(properties, pathToNWAFile);
     
                ActivityReference newActivityReference = ActivityReference.ReadFromNWA(nwaXml);
     
                ActivityReference action = ActivityReferenceCollection.FindByAdapter(newActivityReference.AdapterType,
                    newActivityReference.AdapterAssembly);
     
                if (action != null)
                {
                    // update the details if the adapter already exists
                    ActivityReferenceCollection.UpdateActivity(action.ActivityId, newActivityReference.Name,
                        newActivityReference.Description, newActivityReference.Category,
                        newActivityReference.ActivityAssembly, newActivityReference.ActivityType,
                        newActivityReference.AdapterAssembly, newActivityReference.AdapterType,
                        newActivityReference.HandlerUrl, newActivityReference.ConfigPage,
                        newActivityReference.RenderBehaviour, newActivityReference.Icon, newActivityReference.ToolboxIcon,
                        newActivityReference.WarningIcon, newActivityReference.QuickAccess,
                        newActivityReference.ListTypeFilter);
                }
                else
                {
                    ActivityReferenceCollection.AddActivity(newActivityReference.Name, newActivityReference.Description,
                        newActivityReference.Category, newActivityReference.ActivityAssembly,
                        newActivityReference.ActivityType, newActivityReference.AdapterAssembly,
                        newActivityReference.AdapterType, newActivityReference.HandlerUrl, newActivityReference.ConfigPage,
                        newActivityReference.RenderBehaviour, newActivityReference.Icon, newActivityReference.ToolboxIcon,
                        newActivityReference.WarningIcon, newActivityReference.QuickAccess,
                        newActivityReference.ListTypeFilter);
                    action = ActivityReferenceCollection.FindByAdapter(newActivityReference.AdapterType,
                        newActivityReference.AdapterAssembly);
                }
     
                // Second step is to modify the web.config file to allow use of the activity in declarative workflows
                string activityTypeName = string.Empty;
                string activityNamespace = string.Empty;
     
                Utility.ExtractNamespaceAndClassName(action.ActivityType, out activityTypeName, out activityNamespace);
                AuthorisedTypes.InstallAuthorizedWorkflowTypes(parent, action.ActivityAssembly, activityNamespace,
                    activityTypeName);
                // Third step is to activate the action for the farm
                ActivityActivationReference reference = new ActivityActivationReference(action.ActivityId, Guid.Empty,
                    Guid.Empty);
     
                reference.AddOrUpdateActivationReference();
            }
            protected void RemoveCustomAction(SPWebApplication parent, SPFeatureReceiverProperties properties,
                string adapterType, string adapterAssembly)
            {
                ActivityReference action = ActivityReferenceCollection.FindByAdapter(adapterType, adapterAssembly);
                if (action != null)
                {
                    // Remove the action definition from the workflow configuration database if the Feature is not activated elsewhere
                    if (!IsFeatureActivatedInAnyWebApp(parent, properties.Definition.Id))
                        ActivityReferenceCollection.RemoveAction(action.ActivityId);
                    string activityTypeName = string.Empty;
                    string activityNamespace = string.Empty;
                    Utility.ExtractNamespaceAndClassName(action.ActivityType, out activityTypeName, out activityNamespace);
     
                    // Remove the web.config entry
                    Collection<SPWebConfigModification> modifications = parent.WebConfigModifications;
     
                    foreach (SPWebConfigModification modification in modifications)
                    {
                        if (modification.Owner == AuthorisedTypes.OWNER_TOKEN)
                            // OWNER_TOKEN is the owner for any web config modification added by Nintex Workflow
                        {
                            if (IsAuthorizedTypeMatch(modification.Value, action.ActivityAssembly, activityTypeName,
                                activityNamespace))
                            {
                                modifications.Remove(modification);
                                parent.Farm.Services.GetValue<SPWebService>().ApplyWebConfigModifications();
                               break;
                            }
                        }
                    }
                }
            }
            private bool IsAuthorizedTypeMatch(string modification, string activityAssembly, string activityType,
                string activityNamespace)
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(modification);
     
                if (doc.FirstChild.Name == "authorizedType")
                {
                    return (doc.SelectSingleNode("//@TypeName").Value == activityType
                            && doc.SelectSingleNode("//@Namespace").Value == activityNamespace
                            && doc.SelectSingleNode("//@Assembly").Value == activityAssembly);
                }
                return false;
            }
     
            private bool IsFeatureActivatedInAnyWebApp(SPWebApplication thisWebApplication, Guid thisFeatureId)
            {
                SPWebService webService = SPWebService.ContentService;
                if (webService == null)
                    throw new ApplicationException("Cannot access ContentService");
                SPWebApplicationCollection webApps = webService.WebApplications;
                foreach (SPWebApplication webApp in webApps)
                {
                    if (webApp != thisWebApplication)
                        if (webApp.Features[thisFeatureId] != null)
                            return true;
                }
     
                return false;
            }
     
            private XmlDocument GetNWADefinition(SPFeatureReceiverProperties properties, string pathToNWAFile)
            {
                using (Stream stream = properties.Definition.GetFile(pathToNWAFile))
                {
                    XmlDocument nwaXml = new XmlDocument();
                    nwaXml.Load(stream);
                    return nwaXml;
                }
            }
       }
    }

    Deploying and checking everything has worked.

    If you have done everything correctly, at the point go ahead and deploy your solution. Ensure your feature has been activated for a given web application. Then open Central Admin. Under the Nintex Workflow Management section select Manage allowed actions.

    In Manage Allowed action you should see your Action, and that it is ticked. Meaning it is allowed to be used.

    Let us go to our site now, and create a new Nintex Workflow for our custom list. My list has a Single line of text called Title and another one called PropertyValue. In the toolbar panel of my Nintex Workflow, I can now see my CannonFodder Category, and my custom action.

    Drag this onto your page. If you find it doesn’t stick to your workflow page, go back and check your nwa file that all your Types and Assemblies match up correctly. Once it is on your page, configure this custom action. Your dialog will be presented to you.

    Assign the Property Bag Property to the Item Property Title.

    Create a new Workflow Variable and name this PBResult. Then assign Result Output to PBResult. Click Save on the dialog.


    Under Libraries and List find the action Set field value and drag this onto the form underneath our custom action. Then configure it so that it sets our column PropertyValue to Workflow Data called PBResult that we created in the last step. Click Save on the dialog.

    Lastly before we test this out, on the ribbon bar of the workflow page, under the Nintex Workflow 2010 tab, click Workflow Settings. Configure it so that it Starts when items are created.

    Save and Publish the workflow.

    Testing

    I already have a value in my property bag called cann0nf0dderpb. So I’m going to create a new item in my list, and set the title to cann0nf0dderpb and save the form.

    After a moment or two the workflow has kicked in. Once I refresh my list I can see that in PropertyValue, the value of my PropertyBag item is displayed. I purposely made the property bag value say ‘Nintex Workflow Worked’.

    Debugging SharePoint 2013 workflows using Visual Studio 2013

       Learn about the new tools for remotely debugging workflows in Visual Studio 2012

     

    In Office Developer Tools for Visual Studio 2012, we enabled remote event debugging using Windows Azure Service Bus.

    Now, in Visual Studio 2013, we have implemented a similar approach for remotely debugging workflows in apps for SharePoint.

    The new and re-worded debugging options are available on the SharePoint tab under the Properties page of your app for SharePoint project, as shown in Figure 1.

    Figure 1. Configure remote event and workflow debuggingFigure 1. Configure remote event and workflow debugging

    To debug workflows on Office 365, select the “Enable Workflow debugging” and “Enable debugging via Windows Azure Service Bus” check boxes and enter the Service Bus endpoint connection string. If you try to debug without providing a connection string, you will be prompted to supply one.

    Figure 2. Prompt for a connection stringFigure 2. Prompt for a connection string

    As mentioned in the previous blog post, you’ll need to follow these steps to use the Windows Azure Service Bus for debugging remote events:

    1. Register for a Windows Azure account and then create a Service Bus namespace.
    2. See Managing Service Bus Service Namespaces for more information about managing namespaces.
    3. To get the Service Bus connection string, select your service namespace, choose Access Key, and then copy the Connection String.

    After you have enabled remote event debugging and configured the Service Bus connection string, you can debug remote events.

    FAQ

    1. How can I turn on/off the notification from Visual Studio that tells me to provide a Service Bus connection string?      If you are debugging an Office 365 workflow in your project and have not configured Service Bus debugging, Visual Studio will prompt you to configure it (see Figure 2). You can change this behavior by clearing the Notify me if Windows Azure Service Bus debugging is not configured check box on the SharePoint project property page.
    2. When do I need to enable the Service Bus debugging for workflows?      You must enable Service Bus debugging if you want to debug workflows on Office 365. If your project targets SharePoint installed on your local network, you do not need to enable Service Bus debugging. Instead, you need to open incoming connections to TCP port 12292. If you use Windows Firewall with Advanced Security, you can simply enable the rule “Workflow Manager Tools 1.0 for Visual Studio 2012 – Test Service Host”. If you try to debug against a SharePoint host on the local network without opening the port, Visual Studio will prompt you to enable the rule.
    3. Do I have to enable Service Bus debugging for every project?      Even though you configure the settings in project properties, Service Bus debugging settings are saved for the current user of the workstation so that you can reuse the settings across different projects. However, this setting is not saved into source control (TFS), so if they are needed by a different user or on a different machine, they need to be entered again.
    4. Will I be charged for Service Bus usage?      Yes. Remote event debugging uses the Relay Service component of the Service Bus. Refer to the Service Bus Pricing FAQ for more information.       If you are currently a Visual Studio Professional, Premium, or Ultimate with MSDN subscriber, you can check out the special offer on Windows Azure, which provides Service Bus Relay Hours of up to 1,500, 3,000, and 3,000 respectively.
    5. Do I have to change debugging settings before I publish my app to the marketplace or to the Corporate Gallery?      No. The package created by the Publish command in Visual Studio has the .app extension and does not contain any debugging information. A separate package, having the .debugapp extension is the only one used during debugging.
    6. Can I use Service Bus to debug workflows in SharePoint sandbox or farm solutions?      No. SharePoint solutions can only be debugged against SharePoint installed on the developer’s workstation.
    7. Can I use Service Bus to debug SharePoint 2010 workflows?      No. You can only use it for debugging apps for SharePoint, and apps cannot contain SharePoint 2010 workflows.

    SharePoint Samurai