Working with bpm'online objects over the OData protocol WCF-client
Glossary Item Box
General
The access to bpm'online entities over the OData protocol is provided by the EntityDataService.svc web-service:
Address of the OData service
http[s]://<server_name>/<bpm'online_application_name> + "/0/ServiceModel/EntityDataService.svc/"
Example of the OData service address
http://myserver.com/bpm'onlineWebApp/0/ServiceModel/EntityDataService.svc
Generating proxy classes of the EntityDataService.svc service
General
The key point in the organization of the WCF client operation is receiving metadata of the service and creating client proxy classes. A client application will use these mediation classes to exchange data with the web-service.
The following must be performed to implement the .NET client application that could work with the OData service of bpm'online:
- Create a .NET project where the integration with bpm'online will be implemented.
- Generate client proxy classes of the EntityDataService.svc service.
- Create an instance of the execute environment for the EntityDataService.svc service.
- Implement the client business logic of integration using the methods of the created proxy class instance.
Proxy classes may be generated on the client by several methods considered below.
Creating proxy classes using the DataServiceModel Metadata Utility Tool (DataSvcutil.exe) utility
DataSvcUtil.exe is a command string program provided by WCF Data Services services. The program uses the OData channel and forms client classes of the data service required for access to the data service from the .NET Framework client application. This program forms data classes using the following sources of metadata:
- WSDL — a document of metadata of the service describing the data model provided by the data service.
- Data model file (CSDL) determined using the language for determining the conceptual schema (CSDL) described in the specification [MC–CSDL]: format of the file determining the conceptual schema.
- EDMX file created with the help of programs for work with the EDM model being a part of Entity Framework. Additional data are given in the specification [MC–EDMX]: EDM model for the data service package format.
The DataSvcUtil.exe program is installed in the .NET Framework catalogue.
This is usually the folder C:\Windows\Microsoft.NET\Framework\v4.0. For 64-bit system versions this is the folder C:\Windows\Microsoft.NET\Framework64\v4.0.
Format of calling the DataSvcutil.exe utility
datasvcutil /out:file [/in:file | /uri:serviceuri] [/dataservicecollection] [/language:devlang] [/nologo] [/version:ver] [/help]
The DataSvcutil.exe utility is covered in the corresponding section of the MSDN.
Creating proxy classes in the project of the Visual Studio client application
Proxy classes for the WCF client may be created directly from Visual Studio. For this purpose, the following sequence of actions must be implemented:
- Right-click the project where the integration with bpm'online must be implemented, select the Add Service Reference… item in the right-click menu
- Enter the full address of the OData service, namely EntityDataService.svc in the Address field in the opened window.
- Press the Go button. As a result, the service authentication window will open. The name and password of the bmp'online user must be specified in the window. If the authentication is successful, the entities supported by the service will be displayed in the Services window.
- In the Namespase field, enter the name of the names space where generated proxy classes will be located. For example, bpm'onlineServiceReference. A link to this names space must be added afterwards to the using block of the project code.
- Press the OK button. Proxy classes will be generated. A new Reference.cs code file containing the description of proxy classes will be added to the project. These classes may be used now for addressing and interacting with the data service resources as with objects.
NOTE Visual Studio may generate proxy classes of the service from the service metadata file saved on the disk. For this purpose, fulfill part. 1 of the instructions. Then, enter the full path to the metadata file with the prefix "file://" in the Address dialogue window. Example: file://C:/metadata.xml" After this, fulfill part. 3—5 of the instructions. |
Examples of working with bmp'online entities in the WCF client
When proxy classes of the service are generated, a link to the Microsoft.Data.Services.Client.dll assembly is added to the project. This assembly supports the OData v.3 protocol. If, by any reason, the earlier version of the protocol must be used in the client application, a link to the corresponding assembly must be added manually.
This client library allows making requests to the EntityDataService.svc data service using standard software templates .NET Framework, and include the use of the LINQ request language.
To ensure successful compilation of the examples below, the following must be added to the project code:
Using directives
using System; using System.Data.Services.Client; using System.Net; using Terrasoft.Sdk.Examples.BPMonlineServiceReference; using System.Linq;
Declaring the variable of the OData service address
private static Uri serverUri = new Uri("http://<server_name>/<application_name>/0/ServiceModel/EntityDataService.svc/");
Receiving the objects collection of the service
To receive the objects collection of the service, the DataServiceQuery universal class is used. This class represents a request to the service, which returns the collection of a certain type of entities.
To implement the request to the EntityDataService.svc data service, an instance of the environment context object for the bmp'online must be created.
One ought to bear in mind that all external requests to bpm'online web-services must be authenticated. Detailed methods of authentication may be found in the article Authenticating external requests to bpm'online services.
Forms authentication implemented on the basis of the example in the clause above will be in further examples.
To implement the forms authentication, the LoginClass class with authServiceUri fields (string of a request to the Login method of the AuthService.svc authenticated service) and AuthCookie (Cookie authentications of bpm'online) were created. The TryLogin(string userName, string userPassword) method implementing the user authentication and saving the server response in the AuthCookie field may also be used.
In addition, the OnSendingRequestCookie (object sender, SendingRequestEventArgse) method is created. The method will be called in response to an event of the SendingRequest context instance (creating a new HttpWebRequest instance).
The OnSendingRequestCookie method authenticates the user and Cookies received in response are added to the data receipt request.
static void OnSendingRequestCookie(object sender, SendingRequestEventArgs e) { // Calling the method of the LoginClass class, which authenticates the user method transmitted in parameters. LoginClass.TryLogin("BPMUserName", "BPMUserPassword"); var req = e.Request as HttpWebRequest; // Adding pre-received authentication cookie to the data receipt request. req.CookieContainer = LoginClass.AuthCookie; e.Request = req; }
A request to the service may be implemented by one of the following methods:
- Implementing a LINQ request to the DataServiceQuery named object received from the service context.
- Implicit listing of the DataServiceQuery object received from the service context.
- Explicit call of the Execute method of the DataServiceQuery or BeginExecute object for asynchronous execution.
Below are the examples of access to EntityDataService.svc objects by one of the above methods.
1) Example of receiving the contacts collection via a LINQ request
This example demonstrates how the LINQ request returning all contact entities of the EntityDataService.svc service must be determined and implemented.
public static void GetOdataCollectioByLinqWcfExample() { // Creating the context of the BPMonline application. var context = new BPMonline(serverUri); // Determining the method which adds authentication cookie when creating a new request. context.SendingRequest += new EventHandler<SendingRequestEventArgs>(OnSendingRequestCookie); try { // Building a LINQ request to receive the contacts collection. var allContacts = from contacts in context.ContactCollection select contacts; foreach (Contact contact in allContacts) { // Implementing actions with contacts. } } catch (Exception ex) { // Error processing. } }
2) Example of receiving the contacts collection via an implicit request to the OData service via the context object
This example demonstrates how the context must be used to implement the implicit request returning all contact entities of the EntityDataService.svc service.
public static void GetOdataCollectionByImplicitRequestExample() { // Creating a context object of the BPMonline application. var context = new BPMonline(serverUri); // Determining the method which adds authentication cookie when creating a new request. context.SendingRequest += new EventHandler<SendingRequestEventArgs>(OnSendingRequestCookie); try { // Determining an implicit request to the service to receive the contacts collection. DataServiceQuery<Contact> allContacts = context.ContactCollection; foreach (Contact contact in allContacts) { // Implementing actions with contacts. } } catch (Exception ex) { // Error processing. } }
3) Example of receiving the contacts collection via an explicit request to the OData service via the context object
This example demonstrates how the DataServiceContext context must be used to implement a request to the EntityDataService.svc service returning all contact entities.
public static void GetOdataCollectionByExplicitRequestExample() { // Determining a Uri request to the service which returns the contacts collection. Uri contactUri = new Uri(serverUri, "ContactCollection"); // Creating a context object of the BPMonline application. var context = new BPMonline(serverUri); // Determining the method which adds authentication cookie when creating a new request. context.SendingRequest += new EventHandler<SendingRequestEventArgs>(OnSendingRequestCookie); try { // Implementing an explicit request to the service by calling the Execute<>() method. foreach (Contact contact in context.Execute<Contact>(contactUri)) { // Implementing actions with contacts. } } catch (Exception ex) { // Error processing. } }
Receiving an object with set features
public static void GetOdataObjectByWcfExample() { // Creating the context of the BPMonline application. var context = new BPMonline(serverUri); // Determining the method which adds authentication cookie when creating a new request. context.SendingRequest += new EventHandler<SendingRequestEventArgs>(OnSendingRequestCookie); var contact = context.ContactCollection.Where(c => c.Name.Contains("User")).First(); // Implementing actions over the contact. }
Creating a new object
public static void CreateBpmEntityByOdataWcfExample() { // Creating a new contact, initiating properties. var contact = new Contact() { Id = Guid.NewGuid(), Name = "New Test User" }; // Creating and initiating properties of a new account, to which the created contact refers. var account = new Account() { Id = Guid.NewGuid(), Name = "Some Company" }; contact.Account = account; // Creating the context of the BPMonline application. var context = new BPMonline(serverUri); // Determining the method which adds authentication cookie when creating a new request. context.SendingRequest += new EventHandler<SendingRequestEventArgs> (OnSendingRequestCookie); // Adding the created contact to the contacts collection of the service data model. context.AddToAccountCollection(account); // Adding the created account to the accounts collection of the service data model. context.AddToContactCollection(contact); // Setting the relationship between the created contact and account in the service data model. context.SetLink(contact, "Account", account); // Saving the modification of data in BPMonline by one request. DataServiceResponse responces = context.SaveChanges(SaveChangesOptions.Batch); // Processing the server responses. }
Modifying an existing object
public static void UpdateBpmEntityByOdatetWcfExample() { // Creating the context of the BPMonline application. var context = new BPMonline(serverUri); // Determining the method which adds authentication cookie when creating a new request. context.SendingRequest += new EventHandler<SendingRequestEventArgs>(OnSendingRequestCookie); // The contact on which basis the data will be modified is selected from the contacts collection. var updateContact = context.ContactCollection.Where(c => c.Name.Contains("Test")).First(); // Modifying the selected contact properties. updateContact.Notes = "New updated description for this contact."; updateContact.Phone = "123456789"; // Saving the modifications in the service data model. context.UpdateObject(updateContact); // Saving the modification of data in BPMonline by one request. var responces = context.SaveChanges(SaveChangesOptions.Batch); }
Deleting an object
public static void DeleteBpmEntityByOdataWcfExample() { // Creating the context of the BPMonline application. var context = new BPMonline(serverUri); context.SendingRequest += new EventHandler<SendingRequestEventArgs>(OnSendingRequestCookie); // The object which will be deleted is selected from the contacts collection. var deleteContact = context.ContactCollection.Where(c => c.Name.Contains("Test")).First(); // Deleting the selected object from the service data model. context.DeleteObject(deleteContact); // Saving the modification of data in BPMonline by one request. var responces = context.SaveChanges(SaveChangesOptions.Batch); // Processing the server responses. }