SharePoint 4 Developers

Additional reference guide in .NET / SharePoint Development

Business Connectivity Services – Part V

Take advantage of the interface IContextProperty to get the BDC Connection details. Learn how to create ECTs via Assembly .NET in SharePoint 2010 through Business Connectivity Services.

Hi folks,

This is the one more article of the BCS series. Learn how to create ECTs via Assembly .NET in SharePoint 2010 through Business Connectivity Services!

This approach will take advantage of the interface IContextProperty to get the BDC Connection details set against the BDC Model.

Enjoy it!

Creating ECTs via Assembly .NET

Creating ECTs via Assembly .NET just requires VS2010. The SPD2010 will not be used.

This approach can be applied in environments that:

  • Need to create business rules, which can be developed against the BDC model;
  • Use databases other than SQL Server, which can be implemented in the data access tier;
  • Require the deployment of WSP packages to activate features, which is automatically generated by VS2010;

If you have this scenario, this implementation has a higher level of difficulty by the level of details in creating the assembly .NET, which is displayed in the next sections of this article.

Working with Visual Studio 2010

The template called Business Data Connectivity Model will be used in this article. Start by opening up VS2010 and create a new project according to the Figure 1:

Solution

Figure 1 - Creating a new project and solution

Immediately after that a Wizard helps you in setting up the project. The URL needs to be validated for debugging purposes, and the solution will be created as a Farm Solution, according to the Figure 2:

1part1

Figure 2 – Wizard

Note: Once the project is created, delete the classes called Entity1 and Entity1Service. Don’t forget to delete the entity created which is available in the BDC Designer, because new classes will be generated in a new model.

Data Access Layer

Due to the fact the feature will be created as a package WSP, I preferred to provide data access in the same project. Some objects need to be added to manipulate the database, and for demonstration purposes I am using LINQ to SQL because it is simpler to implement.
Add the LINQ to SQL object to the project and name it Dev.dbml, then create a new connection through the Server Explorer that uses Windows Authentication, open the database and drag the table Contact (Part II) according to the Figure 3:

LINQtoSQL

Figure 3 - Adding table Contact

Before manipulating data of the Contact object, a class that contains CRUD methods needs to be created. So create a class called ContactManager and add the code below, whose comments are well documented:

Code Snippet
  1. public class ContactManager
  2. {
  3.     /// <summary>
  4.     /// Gets all the Contacts
  5.     /// </summary>
  6.     /// <returns>Contacts Array</returns>
  7.     public Contact[] GetContacts()
  8.     {
  9.         var contacts = new List<Contact>();
  10.  
  11.         using (DevDataContext dev = new DevDataContext())
  12.         {
  13.             contacts = (from cont in dev.Contacts
  14.                         select cont).ToList();
  15.         }
  16.         return contacts.ToArray();
  17.     }
  18.  
  19.     /// <summary>
  20.     /// Gets a specific Contact
  21.     /// </summary>
  22.     /// <param name="contactId">Contact Id</param>
  23.     /// <returns>Returns the Contact</returns>
  24.     public Contact GetContactById(int contactId)
  25.     {
  26.         var contact = new Contact();
  27.  
  28.         using (DevDataContext dev = new DevDataContext())
  29.         {
  30.             contact = (from cont in dev.Contacts
  31.                         where cont.ContactID == contactId
  32.                         select cont).First();
  33.         }
  34.         return contact;
  35.     }
  36.  
  37.     /// <summary>
  38.     /// Updates a specific Contact
  39.     /// </summary>
  40.     /// <param name="contact">Contact to be updated</param>
  41.     public void UpdateContact(Contact contact)
  42.     {
  43.         var contactDB = new Contact();
  44.  
  45.         using (DevDataContext dev = new DevDataContext())
  46.         {
  47.             contactDB = (from cont in dev.Contacts
  48.                             where cont.ContactID == contact.ContactID
  49.                             select cont).First();
  50.  
  51.             // Alters the object
  52.             contactDB.Address = contact.Address;
  53.             contactDB.City = contact.City;
  54.             contactDB.CompanyName = contact.CompanyName;
  55.             contactDB.ContactName = contact.ContactName;
  56.             contactDB.ContactTitle = contact.ContactTitle;
  57.             contactDB.Country = contact.Country;
  58.             contactDB.Email = contact.Email;
  59.             contactDB.Fax = contact.Fax;
  60.             contactDB.Phone = contact.Phone;
  61.             contactDB.PostalCode = contact.PostalCode;
  62.             contactDB.Region = contact.Region;
  63.  
  64.             // Submitting the changes
  65.             dev.Refresh(System.Data.Linq.RefreshMode.KeepChanges, contactDB);
  66.             dev.SubmitChanges();
  67.         }
  68.     }
  69.  
  70.     /// <summary>
  71.     /// Adds a Contact
  72.     /// </summary>
  73.     /// <param name="contact">New Contact</param>
  74.     public void AddContact(Contact contact)
  75.     {
  76.         using (DevDataContext dev = new DevDataContext())
  77.         {
  78.             dev.Contacts.InsertOnSubmit(contact);
  79.             dev.SubmitChanges();
  80.         }
  81.     }
  82.  
  83.     /// <summary>
  84.     /// Deletes a Contacts
  85.     /// </summary>
  86.     /// <param name="contactId">Contact Id</param>
  87.     public void DeleteContact(int contactId)
  88.     {
  89.         using (DevDataContext dev = new DevDataContext())
  90.         {
  91.             var contact = (from cont in dev.Contacts
  92.                             where cont.ContactID == contactId
  93.                             select cont).First();
  94.             dev.Contacts.DeleteOnSubmit(contact);
  95.             dev.SubmitChanges();
  96.         }
  97.     }
  98. }

Note: This was already explained when creating ECTs via Web Services in part II, however as this is important in this demo, the same code was reused.

Create a new partial class called DevDataContext, as we already have this class automatically generated by Visual Studio. Create a new constructor, according to the code below:

Code Snippet
  1. public partial class DevDataContext
  2.     {
  3.         public DevDataContext() :
  4.             base(BdcModel1.ContactService.GetConnection(), mappingSource)
  5.         {
  6.             OnCreated();
  7.         }
  8.     }

Note: This new constructor contains a call to the method GetConnection(). It belongs to the ContactService class and returns the connection string, which is obtained directly from the BDC Metadata Model (we’ll check it soon).

BDC Model

By using the new BDC Panels in Visual Studio the Metadata Model will be created. It needs to be created based on the Data Access layer, as we will work with the Contact entity. Do this by using the BDC Designer Panel, according to the Figure 4:

1and2Figure 4 - Contact entity added

As the Contact entity was created, now it must be configured. In order to do that add an Identifier called ContactID and the following Methods: GetConnection, ReadItem, ReadList, Delete, Update and Create. The context menu makes things easier, according to the Figure 5:

2

Figure 5 - Identifier and Methods added

To add and configure methods, the most convenient way is the utilisation of the BDC Method Details Panel (as this tool is going to generate XML automatically) according to the Figure 6:

3

Figure 6 - BDC Method Details Panel in action

 

The Table 1 below shows a summary of the configuration started in the Figure 6. It contains all the methods and signatures:

Option Method Parameters Direction Type Descriptor
Create Creator Method Create returnContact Return ReturnContact
    newContact In NewContact
Create Deleter Method Delete contactID In ContactID
Create Finder Method ReadList contactList Return ContactList
Create Specific Finder Method ReadItem contact Return Contact
    contactID In ContactID
Create Updater Method Update contact In Contact
Create Blank Method GetConnection parameter Return connection
Table 1 - Automatic method generation of the Contact entity

Note: A Blank Method will create a method called Method, which needs to be renamed. In this example call it GetConnection.

Before configuring the methods, make sure that the ContactID identifier type is System.Int32. Take the ReadItem method as the first one to be configured and click over the parameter (aka type descriptor) Contact, so we can select its type according to the Figure 7:

bdcmethoddetails

Figure 7 - TypeDescriptor type

The next step is to include new Type Descriptors to the Type Descriptor called Contact through BDC Explorer Panel, which basically represent its attributes. The Figure 9 displays how to add Type Descriptors and the Table 2 reveals the Type Descriptors to be added.

6part1Figure 8 - Adding TypeDescriptors to Contact

 

Type Descriptor Type
Address System.String
City System.String
CompanyName System.String
ContactID System.Int32
ContactName System.String
ContactTitle System.String
Country System.String
Email System.String
Fax System.String
Phone System.String
PostalCode System.String
Region System.String
Table 2 - Types of Type Descriptors

Once created, these Type Descriptors will be automatically reused when creating other methods. The code below shows the XML automatically generated of the Contact entity after configuring of all methods. This was extracted from the file called BdcModel1.bdcm:

Code Snippet
  1. <Entity Name="Contact" Namespace="ContactServices.BdcModel.BdcModel1" Version="1.0.0.64">
  2.   <Properties>
  3.     <Property Name="Class" Type="System.String">ContactServices.BdcModel.BdcModel1.ContactService, BdcModel1</Property>
  4.   </Properties>
  5.   <Identifiers>
  6.     <Identifier Name="ContactID" TypeName="System.Int32" />
  7.   </Identifiers>
  8.   <Methods>
  9.     <Method Name="ReadItem">
  10.       <Parameters>
  11.         <Parameter Name="contact" Direction="Return">
  12.           <TypeDescriptor Name="Contact" TypeName="ContactServices.BdcModel.Contact, BdcModel1" IsCollection="false">
  13.             <TypeDescriptors>
  14.               <TypeDescriptor Name="Address" TypeName="System.String" />
  15.               <TypeDescriptor Name="City" TypeName="System.String" />
  16.               <TypeDescriptor Name="CompanyName" TypeName="System.String" />
  17.               <TypeDescriptor Name="ContactID" TypeName="System.Int32" IsCollection="false" IdentifierEntityName="Contact" IdentifierEntityNamespace="ContactServices.BdcModel.BdcModel1" IdentifierName="ContactID" />
  18.               <TypeDescriptor Name="ContactName" TypeName="System.String" />
  19.               <TypeDescriptor Name="ContactTitle" TypeName="System.String" />
  20.               <TypeDescriptor Name="Country" TypeName="System.String" />
  21.               <TypeDescriptor Name="Email" TypeName="System.String" />
  22.               <TypeDescriptor Name="Fax" TypeName="System.String" />
  23.               <TypeDescriptor Name="Phone" TypeName="System.String" />
  24.               <TypeDescriptor Name="PostalCode" TypeName="System.String" />
  25.               <TypeDescriptor Name="Region" TypeName="System.String" />
  26.             </TypeDescriptors>
  27.           </TypeDescriptor></Parameter>
  28.         <Parameter Name="contactID" Direction="In">
  29.           <TypeDescriptor Name="ContactID" TypeName="System.Int32" IdentifierEntityName="Contact" IdentifierEntityNamespace="ContactServices.BdcModel.BdcModel1" IdentifierName="ContactID" /></Parameter>
  30.       </Parameters>
  31.       <MethodInstances>
  32.         <MethodInstance Name="ReadItem" Type="SpecificFinder" ReturnParameterName="contact" ReturnTypeDescriptorPath="Contact" />
  33.       </MethodInstances></Method>
  34.     <Method Name="ReadList">
  35.       <Parameters>
  36.         <Parameter Name="contactList" Direction="Return">
  37.           <TypeDescriptor Name="ContactList" TypeName="System.Collections.Generic.IEnumerable`1[[ContactServices.BdcModel.Contact, BdcModel1]]" IsCollection="true">
  38.             <TypeDescriptors>
  39.               <TypeDescriptor Name="Contact" IsCollection="false" TypeName="ContactServices.BdcModel.Contact, BdcModel1">
  40.                 <TypeDescriptors>
  41.                   <TypeDescriptor Name="Address" TypeName="System.String" />
  42.                   <TypeDescriptor Name="City" TypeName="System.String" />
  43.                   <TypeDescriptor Name="CompanyName" TypeName="System.String" />
  44.                   <TypeDescriptor Name="ContactID" IdentifierEntityNamespace="ContactServices.BdcModel.BdcModel1" IdentifierEntityName="Contact" IdentifierName="ContactID" IsCollection="false" TypeName="System.Int32" />
  45.                   <TypeDescriptor Name="ContactName" TypeName="System.String" />
  46.                   <TypeDescriptor Name="ContactTitle" TypeName="System.String" />
  47.                   <TypeDescriptor Name="Country" TypeName="System.String" />
  48.                   <TypeDescriptor Name="Email" TypeName="System.String" />
  49.                   <TypeDescriptor Name="Fax" TypeName="System.String" />
  50.                   <TypeDescriptor Name="Phone" TypeName="System.String" />
  51.                   <TypeDescriptor Name="PostalCode" TypeName="System.String" />
  52.                   <TypeDescriptor Name="Region" TypeName="System.String" /></TypeDescriptors></TypeDescriptor></TypeDescriptors></TypeDescriptor></Parameter>
  53.       </Parameters>
  54.       <MethodInstances>
  55.         <MethodInstance Name="ReadList" Type="Finder" ReturnParameterName="contactList" ReturnTypeDescriptorPath="ContactList" />
  56.       </MethodInstances></Method>
  57.     <Method Name="Create">
  58.       <Parameters>
  59.         <Parameter Name="returnContact" Direction="Return">
  60.           <TypeDescriptor Name="ReturnContact" IsCollection="false" TypeName="ContactServices.BdcModel.Contact, BdcModel1">
  61.             <TypeDescriptors>
  62.               <TypeDescriptor Name="Address" TypeName="System.String" />
  63.               <TypeDescriptor Name="City" TypeName="System.String" />
  64.               <TypeDescriptor Name="CompanyName" TypeName="System.String" />
  65.               <TypeDescriptor Name="ContactID" IdentifierEntityNamespace="ContactServices.BdcModel.BdcModel1" IdentifierEntityName="Contact" IdentifierName="ContactID" IsCollection="false" TypeName="System.Int32" />
  66.               <TypeDescriptor Name="ContactName" TypeName="System.String" />
  67.               <TypeDescriptor Name="ContactTitle" TypeName="System.String" />
  68.               <TypeDescriptor Name="Country" TypeName="System.String" />
  69.               <TypeDescriptor Name="Email" TypeName="System.String" />
  70.               <TypeDescriptor Name="Fax" TypeName="System.String" />
  71.               <TypeDescriptor Name="Phone" TypeName="System.String" />
  72.               <TypeDescriptor Name="PostalCode" TypeName="System.String" />
  73.               <TypeDescriptor Name="Region" TypeName="System.String" /></TypeDescriptors></TypeDescriptor></Parameter>
  74.         <Parameter Name="newContact" Direction="In">
  75.           <TypeDescriptor Name="NewContact" IsCollection="false" TypeName="ContactServices.BdcModel.Contact, BdcModel1">
  76.             <TypeDescriptors>
  77.               <TypeDescriptor Name="Address" TypeName="System.String" CreatorField="true" />
  78.               <TypeDescriptor Name="City" TypeName="System.String" CreatorField="true" />
  79.               <TypeDescriptor Name="CompanyName" TypeName="System.String" CreatorField="true" />
  80.               <TypeDescriptor Name="ContactID" IdentifierEntityNamespace="ContactServices.BdcModel.BdcModel1" IdentifierEntityName="Contact" IdentifierName="ContactID" IsCollection="false" TypeName="System.Int32" CreatorField="true" />
  81.               <TypeDescriptor Name="ContactName" TypeName="System.String" CreatorField="true" />
  82.               <TypeDescriptor Name="ContactTitle" TypeName="System.String" CreatorField="true" />
  83.               <TypeDescriptor Name="Country" TypeName="System.String" CreatorField="true" />
  84.               <TypeDescriptor Name="Email" TypeName="System.String" CreatorField="true" />
  85.               <TypeDescriptor Name="Fax" TypeName="System.String" CreatorField="true" />
  86.               <TypeDescriptor Name="Phone" TypeName="System.String" CreatorField="true" />
  87.               <TypeDescriptor Name="PostalCode" TypeName="System.String" CreatorField="true" />
  88.               <TypeDescriptor Name="Region" TypeName="System.String" CreatorField="true" /></TypeDescriptors></TypeDescriptor></Parameter>
  89.       </Parameters>
  90.       <MethodInstances>
  91.         <MethodInstance Name="Create" Type="Creator" ReturnParameterName="returnContact" ReturnTypeDescriptorPath="ReturnContact" />
  92.       </MethodInstances></Method>
  93.     <Method Name="Update">
  94.       <Parameters>
  95.         <Parameter Name="contact" Direction="In">
  96.           <TypeDescriptor Name="Contact" IsCollection="false" TypeName="ContactServices.BdcModel.Contact, BdcModel1">
  97.             <TypeDescriptors>
  98.               <TypeDescriptor Name="Address" TypeName="System.String" UpdaterField="true" />
  99.               <TypeDescriptor Name="City" TypeName="System.String" UpdaterField="true" />
  100.               <TypeDescriptor Name="CompanyName" TypeName="System.String" UpdaterField="true" />
  101.               <TypeDescriptor Name="ContactID" IdentifierEntityNamespace="ContactServices.BdcModel.BdcModel1" IdentifierEntityName="Contact" IdentifierName="ContactID" IsCollection="false" TypeName="System.Int32" UpdaterField="true" />
  102.               <TypeDescriptor Name="ContactName" TypeName="System.String" UpdaterField="true" />
  103.               <TypeDescriptor Name="ContactTitle" TypeName="System.String" UpdaterField="true" />
  104.               <TypeDescriptor Name="Country" TypeName="System.String" UpdaterField="true" />
  105.               <TypeDescriptor Name="Email" TypeName="System.String" UpdaterField="true" />
  106.               <TypeDescriptor Name="Fax" TypeName="System.String" UpdaterField="true" />
  107.               <TypeDescriptor Name="Phone" TypeName="System.String" UpdaterField="true" />
  108.               <TypeDescriptor Name="PostalCode" TypeName="System.String" UpdaterField="true" />
  109.               <TypeDescriptor Name="Region" TypeName="System.String" UpdaterField="true" /></TypeDescriptors></TypeDescriptor></Parameter>
  110.       </Parameters>
  111.       <MethodInstances>
  112.         <MethodInstance Name="Update" Type="Updater" />
  113.       </MethodInstances></Method>
  114.     <Method Name="Delete">
  115.       <Parameters>
  116.         <Parameter Name="contactID" Direction="In">
  117.           <TypeDescriptor Name="ContactID" TypeName="System.Int32" IdentifierEntityName="Contact" IdentifierEntityNamespace="ContactServices.BdcModel.BdcModel1" IdentifierName="ContactID" /></Parameter>
  118.       </Parameters>
  119.       <MethodInstances>
  120.         <MethodInstance Name="Delete" Type="Deleter" />
  121.       </MethodInstances></Method>
  122.     <Method Name="GetConnection">
  123.       <Parameters>
  124.         <Parameter Name="parameter" Direction="Return">
  125.           <TypeDescriptor Name="connection" TypeName="System.String" /></Parameter>
  126.       </Parameters></Method>
  127.   </Methods>
  128.   </Entity>

Note: The file BdcModel1.bdcm can be visualised in XML directly through Visual Studio, just using the context menu Open With... and then XML (Text) Editor.

BDC Model Connection

Connection details can be set inside of the LobSystemInstance properties if you are using a database or web service. As we have this scenario, the code below shows the connection details:

Code Snippet
  1. <LobSystemInstance Name="BdcModel1">
  2.   <Properties>
  3.     <Property Name="AuthenticationMode" Type="System.String">PassThrough</Property>
  4.     <!-- AuthenticationMode can be set to PassThrough, RevertToSelf, RdbCredentials, or WindowsCredentials. -->
  5.     <Property Name="DatabaseAccessProvider" Type="System.String">SqlServer</Property>
  6.     <!-- Options:  SQL Server, OleDB, Oracle, or ODBC. -->
  7.     <Property Name="RdbConnection Data Source" Type="System.String">W2008R2Sub1</Property>
  8.     <!-- Type the database server name or the SQL Server instance name in the format SQLServer\Instance. -->
  9.     <Property Name="RdbConnection Initial Catalog" Type="System.String">Dev</Property>
  10.     <!-- Type the database name. -->
  11.     <Property Name="RdbConnection Integrated Security" Type="System.String">SSPI</Property>
  12.     <!-- Type SSPI for Integrated Security. -->
  13.     <Property Name="RdbConnection Pooling" Type="System.String">false</Property>
  14.     <!-- Type true or false for Pooling -->
  15.   </Properties>
  16. </LobSystemInstance>

Note: If you want to know more about the authentication types available through BCS, check the section References. Basically the XML above contains properties commonly used when creating connection strings.

BDC Model Entity Methods

Along the creation of methods through BDC Panels, Visual Studio took charge of the generation of the ContactService class and its respective methods. They are not implemented yet and are throwing an exception type of NotImplementedException.

Before coding all methods, do you remember the code that contains the method called GetConnection? It needs to return a database connection string, but how? Well, we are going to take advantage of the LobSystemInstance properties set previously.

But how to read the XML that contains those properties? Easy peasy! Just implement the interface IContextProperty in the ContactService class and the BDC does the trick for you.

Note: When an assembly contains a class that implements IContextProperty, its properties are automatically initialized at the time the assembly is executed in BDC. It helps a lot!

Do that by adding a reference to the assembly Microsoft.Business, which is available at the 14: \ISAPI\Microsoft.BusinessData.dll.

Check out the code below, which shows the ContactService class:

Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using ContactServices.BdcModel;
  6. using Microsoft.BusinessData.SystemSpecific;
  7. using Microsoft.BusinessData.MetadataModel;
  8. using Microsoft.BusinessData.Runtime;
  9. using Microsoft.BusinessData.MetadataModel.Collections;
  10.  
  11. namespace ContactServices.BdcModel.BdcModel1
  12. {
  13.     public partial class ContactService : IContextProperty
  14.     {
  15.         private static IMethodInstance methodInstance;
  16.         private static ILobSystemInstance lobSystemInstance;
  17.         private static IExecutionContext executionContext;
  18.  
  19.         #region IContextProperty implementation
  20.  
  21.         public IMethodInstance MethodInstance
  22.         {
  23.             get { return methodInstance; }
  24.             set { methodInstance = value; }
  25.         }
  26.  
  27.         public ILobSystemInstance LobSystemInstance
  28.         {
  29.             get { return lobSystemInstance; }
  30.             set { lobSystemInstance = value; }
  31.         }
  32.  
  33.         public IExecutionContext ExecutionContext
  34.         {
  35.             get { return executionContext; }
  36.             set { executionContext = value; }
  37.         }
  38.  
  39.         #endregion
  40.  
  41.         public static Contact ReadItem(int contactID)
  42.         {
  43.             // Implement your own business rules
  44.             return new ContactManager().GetContactById(contactID);
  45.         }
  46.  
  47.         public static IEnumerable<Contact> ReadList()
  48.         {
  49.             // Implement your own business rules
  50.             return new ContactManager().GetContacts();
  51.         }
  52.  
  53.         public static Contact Create(Contact newContact)
  54.         {
  55.             if (string.IsNullOrEmpty(newContact.ContactName) || string.IsNullOrEmpty(newContact.Email) || string.IsNullOrEmpty(newContact.Phone))
  56.                 throw new ObjectNotFoundException("ContactName, Email and Phone are mandatories.");
  57.  
  58.             var manager = new ContactManager();
  59.             manager.AddContact(newContact);
  60.             return manager.GetContactById(newContact.ContactID);
  61.         }
  62.  
  63.         public static void Update(Contact contact)
  64.         {
  65.             if (string.IsNullOrEmpty(contact.ContactName) || string.IsNullOrEmpty(contact.Email) || string.IsNullOrEmpty(contact.Phone))
  66.                 throw new ObjectNotFoundException("ContactName, Email and Phone are mandatories.");
  67.  
  68.             new ContactManager().UpdateContact(contact);
  69.         }
  70.  
  71.         public static void Delete(int contactID)
  72.         {
  73.             // Implement your own business rules
  74.             new ContactManager().DeleteContact(contactID);
  75.         }
  76.  
  77.         public static string GetConnection()
  78.         {
  79.             INamedPropertyDictionary properties = lobSystemInstance.GetProperties();
  80.  
  81.             string template = "Data Source={0};Initial Catalog={1};Integrated Security={2};";
  82.  
  83.             string dataSource = "RdbConnection Data Source";
  84.             string initialCatalog = "RdbConnection Initial Catalog";
  85.             string integratedSecurity = "RdbConnection Integrated Security";
  86.  
  87.             if (!properties.ContainsKey(dataSource) || !properties.ContainsKey(initialCatalog) || !properties.ContainsKey(integratedSecurity))
  88.                 throw new Exception("LobSystemInstance does not contain a connection string");
  89.  
  90.             return string.Format(template, properties[dataSource].ToString(), properties[initialCatalog].ToString(), properties[integratedSecurity].ToString());
  91.  
  92.         }
  93.     }
  94. }

With the exception of the GetConnection method, all the others call CRUD methods from the ContactManager class. Still, in the Create and Update methods there is a validation of the required fields ContactName, Email and Phone, which cannot be null or empty as they throw an exception type of ObjectNotFoundException.

As expected the GetConnection method gets the properties of LobSystemInstance, which contains the BDC connection details, by returning the connection string used in the constructor of the DevDataContext Partial Class.

Creating the Deployment Package

Deployment of WSP packages in the real world is performed either manually or using scripts, not directly with the intervention of Visual Studio. I am explaining this for purposes of demonstration and understanding of STSADM.

Before generating the WSP package, some more settings are needed. Rename the feature to BdcModelFeature and add a property SiteUrl in the XML file BdcModelFeature.Template.xml that contains the URL for deployment, according to the Figure 9:

9_680 Figure 9 – Feature Property

Finally generate the WSP package by selecting Package in the context menu of Visual Studio. Get the WSP package from the Bin directory and by using STSADM deploy it with the following commands:

stsadm -o addsolution -filename "ContactServices.BdcModel.wsp"

stsadm -o deploysolution -name "ContactServices.BdcModel.wsp" -allowGacDeployment –immediate

stsadm -o execadmsvcjobs

stsadm -o installfeature -filename "ContactServices.BdcModel_BdcModelFeature\feature.xml" –force

stsadm -o activatefeature -name "ContactServices.BdcModel_BdcModelFeature"

Note: Download the solution here.

Configuring the External List

At this stage it is already possible to create an External List that will provide a visual interface to the external data in SharePoint 2010. Both SharePoint Designer and the SharePoint UI provides a way for us to create an External List, in the Part II I have showed how to use SharePoint Designer for this and now I am going to show how to create it by SharePoint UI.

Go to the web site and access Site Actions > More Options. The Figure 10 displays the modal dialog to select the External List:

10
Figure 10 – Selecting the External List

Then pick up the External Content Type ContactServices.BdcModel.BdcModel1.Contact and create the Contacts List, as displayed in the Figure 11:

11_680
Figure 11 - Creating the Contacts External List

After doing this you will get your Contacts List created. Is that all? No, you need to set permissions in the BDC Service Application for this Assembly, otherwise you will get the following screen:

BDC1
Figure 12 – Access denied by Business Data Connectivity

Settings BDC Permissions

After the deployment of the .NET Assembly you need to set proper permissions in the BDC Service Application for users to see the external data. Go to the BDC Service Application in the Central Administration and find the .NET Assembly:

BDC2_680
Figure 13 – Find the .NET Assembly

Then specify the users that are going to be allowed to see the external data, according to the Figure 14:

BDC3_680
Figure 14 – Set Object Permissions

By doing this, refresh the External List (Figure 12) and you will get the external data. Smile

This was advanced guys, from now on you are able to create your own ECTs via .NET Assemblies.

The BDC series is not yet finished, next time I will show how to interface ECTs with Client Applications. See you next time!

Reference:
http://msdn.microsoft.com/en-us/library/ee556826(v=office.14).aspx
http://msdn.microsoft.com/en-us/library/microsoft.businessdata.systemspecific.icontextproperty(office.14).aspx

Cheers,

Marcel Medina

Click here to read the same content in Portuguese.

Business Connectivity Services – Part IV

Understand the hierarchical structure of the BDC metadata model (Business Data Connectivity Model) and the new tools in Visual Studio 2010 to design BDC models (Part IV)

Hi folks,

This is the fourth part of the article about the news in integrating external data with the Business Connectivity Services (BCS) in SharePoint 2010!

Just to recap, the Part I of this article brought an introduction to the BCS by the analysis of its architecture and components, the Part II brought the creation of External Content Types (ECT) via Database and the Part III the creation of ECTs via Web Service.

Part I reading is extremely important to understand this post. In this article I will explain the hierarchical structure of the Business Data Connectivity Metadata Model and introduce the new tools available in the Visual Studio 2010 to create BDC objects.

Have a good reading!

Understanding the BDC Metadata Model

In this article's example a new template in Visual Studio 2010 called Business Data Connectivity (BDC) Model will be used. It allows the creation of entities (BDC Entities) also known as External Content Types, an old friend of us (check Part I for more details).

Entities are objects that belong to the BDC metadata model and represent one of the core BDC metadata model objects. In this approach I want to go a little deeper into this model, check out the Figure 1:

BDCModelFigure 1 - BDC Metadata Model

Now it is clear where the ECTs are within the BDC Metadata Model, but we still do not know in details the role performed by each one of the objects comprised in the Figure 1. We can only note that the objects are in a hierarchical structure.

To understand these objects let's check the details of each one:

NOTE: The same content can be found in the Reference links, however I have decided to drill down a little bit more than the content presented on MSDN. :)

  • Model - This is the BDC core main object that maps the external data. This is the aggregator of all the objects that comprise the hierarchy of this model.

  • LobSystem - Inside the model it behaves as the representation of an external service that contains the business logic, simply by defining the type of external data source to be used, that can be:
  1. Database – Sets the mapping of a database;
  2. DotNetAssembly – Defines the mapping of an assembly. NET;
  3. Wcf – Defines the mapping of a WCF service endpoint;
  4. WebService – Defines the mapping of a Web Service. It is considered "deprecated", so use a WCF service;
  5. Custom – Defines the mapping of a custom connector, implemented to manage the external data source connection and data transferring.
  • LobSystemInstance - This is the implementation of a LobSystem. It holds all the connection details to an external service.

  • Entity - This is the representation within the BDC metadata model of an ECT, which according to the Part I describes the schema and data access capabilities of an external data source and its behaviour within Office and SharePoint.

  • Identifier - An identifier acts as a primary key in entities, the same concept used in tables.

  • Method - The methods are the behaviours of an entity. Within the metadata model it works as an aggregator of settings (FilterDescriptor, Parameter, MethodInstance) of the method that represents.

  • FilterDescriptor - Basically a FilterDescriptor can be created within a method to select both the input and the return of values. Several types of filters can be used (check the Reference links).

  • Parameter - Defines the parameter to be used inside the method, as follows:
  1. In – Used to input parameters;
  2. Out – Used to output parameters, similar to the parameter "out" in C#.
  3. InOut – Represents a parameter that has two functions (input / output), similar to the parameter "ref" in C#.
  4. Return – Sets a method return type. In the BDC this is considered as a return parameter.
  • TypeDescriptor - A TypeDescriptor is nothing more, nothing less than a definition to the parameter type. i.e.: Int32, String. It is recursive because it allows that other TypeDescriptor is referred as a parameter type.

  • MethodInstance - This is the implementation of a Method. Operations Create, Update, ReadItem, ReadList and Delete are already predefined for using.

  • Action - The actions allow the addition of extra functionalities to ECTs because they work as an additional link to external data. By default the actions View Item, Edit Item and Delete Item are added to the user interface (check the Reference links) and any further action added, such as a link to open a page, follows the ECT in any part of SharePoint.

  • ActionParameter - Sets the URL of the action that refers, so the link created works. It uses Identifiers or TypeDescriptors of the entity to create the URL.

  • AssociationGroup - Associations represent relationships between entities, similar to a relationship of tables. An AssociationGroup should be used to tie association methods, which are applied in a relationship of entities. i.e.: Given two entities Customer and Order, an AssociationGroup would store methods like GetOrderByCustomer and GetCustomerByOrder.

NOTE: In the next part of this lesson you will see the majority of these objects in use. This overview will be consolidated with a hands-on demo, especially when working with XML behind these definitions.

BDC Metadata Model Design Tool

Visual Studio 2010 was powered with several new design tools and the BDC was not forgotten. Now it's easy to create BDC models, because the toughest job (creation of objects) can be done visually and other small details manually in the XML generated.

The Figure 2 displays the new windows available in VS2010 to design BDC models:

NewDesignerFigure 2 - New windows to design BDC models

With the exception of the Properties window, three (3) new windows were added to the VS2010. They are:

  • BDC Designer - Enables the creation and edition of Entities, Identifiers, Methods and Associations between Entities. This is an design area that allows the creation of objects via drag-and-drop from the Toolbox window or even using the context menu (right mouse button).

  • BDC Method Details - As the name implies, it displays the configuration details of the methods. Allows creation and edition of methods, parameters, typedescriptors and filters (according to the BDC metadata model).

  • BDC Explorer - Organizes and displays BDC metadata model objects in a tree view. Its main purpose is to display objects in a hierarchical structure, but also allows the creation of TypeDescriptors and validation of objects.

Throughout the development in the next part you will see how to manipulate the BDC Metadata Model objects by using these panels. Stick around!

References:
http://msdn.microsoft.com/en-US/library/ee556378.aspx
http://msdn.microsoft.com/en-us/library/ee557835.aspx
http://msdn.microsoft.com/en-us/library/ee559393.aspx

Cheers,

Marcel Medina

Click here to read the same content in Portuguese.

Business Connectivity Services – Part III

Learn how to integrate WCF services in SharePoint 2010 through Business Connectivity Services. This is a very interesting approach because it allows that different services (including the cloud) to be integrated into SharePoint 2010.

Hi folks,

After a mini holiday here there is one more part of the BCS series, whose main approach is to show how to connect to different external data sources.

Learn how to integrate WCF services in SharePoint 2010 through Business Connectivity Services. This is a very interesting approach because it allows that different services (including the cloud) to be integrated into SharePoint 2010.

In this article a WCF service will be created, so an External Content Type (ECT) can be created.

Creating ECTs via Web Service (WCF)

In order to create ECTs via Web Service it is needed the utilisation of SPD2010 and in this case, due to the fact the Web Service is going to be coded from the scratch, VS2010 is required as well.

Use this type of approach in environments that:

  • Integrates with an external data source (i.e.: other systems), either on your Intranet or Internet;
  • There is a need for creating business rules (i.e.: any validation) which can be implemented during the creation of the Web Service;
  • Uses different databases rather than SQL Server, which can be implemented in a data access layer during the creation of the Web Service;

If you have this scenario, this implementation has a higher level of difficulty by creating the Web Service. Both VS2010 and SPD2010 are utilised, the former for the Web Service development and the latter for the configuration.

Working with Visual Studio 2010

The creation of the ECT in this approach is only possible with the existence of a Web Service, that's why a solution in VS2010 is going to be created. As already mentioned in the Block 1 of the BCS Architecture (Part I), both extensions .asmx (ASP.NET Web Service Application) and .svc (WCF Service Application) can be used in the creation of ECTs, and in this demonstration I am going to use a WCF Service Application.

Start VS2010, create a Blank Solution and add 3 projects according to the Figure 1:

solution

Figure 1 - Creating the Solution

Note: Delete the files *.cs and App.config that are created by default in new projects.

The solution was split into projects that represent the data access and business logic layers. Some references between the projects need to be added, according to the Table 1:

Project Reference
ContactServices.Business ContactServices.Data
ContactServices.Host ContactServices.Business
Table 1 - References

Note: In all code examples, my goal is just to show the functionality in creating an ECT in SharePoint 2010. Don’t forget to implement the best practices and patterns such as the Application Blocks (i.e.: Logging, Exception Handling, Security, etc...). I strongly recommend the use of Enterprise Library.

Data Access Layer

In order to create the project ContactServices.Data some objects that manipulate the database need to be added, and for demonstration purposes I use the LINQ to SQL because it is simpler to implement. Add this object to the project and name it Dev.dbml, then create a new connection that uses Windows Authentication using the Server Explorer, open the database and drag the table Contact (Part II) as displayed in Figure 2:

LINQtoSQL

Figure 2 - Adding table Contact

Create a class that contains CRUD methods, so the object Contact can be handled. To do that, create a class called ContactManager and add the code below, which comments tell by themselves:

Code Snippet
  1. public class ContactManager
  2. {
  3.     /// <summary>
  4.     /// Gets all the Contacts
  5.     /// </summary>
  6.     /// <returns>Contacts Array</returns>
  7.     public Contact[] GetContacts()
  8.     {
  9.         var contacts = new List<Contact>();
  10.  
  11.         using (DevDataContext dev = new DevDataContext())
  12.         {
  13.             contacts = (from cont in dev.Contacts
  14.                         select cont).ToList();
  15.         }
  16.         return contacts.ToArray();
  17.     }
  18.  
  19.     /// <summary>
  20.     /// Gets a specific Contact
  21.     /// </summary>
  22.     /// <param name="contactId">Contact Id</param>
  23.     /// <returns>Returns the Contact</returns>
  24.     public Contact GetContactById(int contactId)
  25.     {
  26.         var contact = new Contact();
  27.  
  28.         using (DevDataContext dev = new DevDataContext())
  29.         {
  30.             contact = (from cont in dev.Contacts
  31.                         where cont.ContactID == contactId
  32.                         select cont).First();
  33.         }
  34.         return contact;
  35.     }
  36.  
  37.     /// <summary>
  38.     /// Updates a specific Contact
  39.     /// </summary>
  40.     /// <param name="contact">Contact to be updated</param>
  41.     public void UpdateContact(Contact contact)
  42.     {
  43.         var contactDB = new Contact();
  44.  
  45.         using (DevDataContext dev = new DevDataContext())
  46.         {
  47.             contactDB = (from cont in dev.Contacts
  48.                             where cont.ContactID == contact.ContactID
  49.                             select cont).First();
  50.  
  51.             // Alters the object
  52.             contactDB.Address = contact.Address;
  53.             contactDB.City = contact.City;
  54.             contactDB.CompanyName = contact.CompanyName;
  55.             contactDB.ContactName = contact.ContactName;
  56.             contactDB.ContactTitle = contact.ContactTitle;
  57.             contactDB.Country = contact.Country;
  58.             contactDB.Email = contact.Email;
  59.             contactDB.Fax = contact.Fax;
  60.             contactDB.Phone = contact.Phone;
  61.             contactDB.PostalCode = contact.PostalCode;
  62.             contactDB.Region = contact.Region;
  63.  
  64.             dev.Refresh(System.Data.Linq.RefreshMode.KeepChanges, contactDB);
  65.             dev.SubmitChanges();
  66.         }
  67.     }
  68.  
  69.     /// <summary>
  70.     /// Adds a Contact
  71.     /// </summary>
  72.     /// <param name="contact">New Contact</param>
  73.     public void AddContact(Contact contact)
  74.     {
  75.         using (DevDataContext dev = new DevDataContext())
  76.         {
  77.             dev.Contacts.InsertOnSubmit(contact);
  78.             dev.SubmitChanges();
  79.         }
  80.     }
  81.  
  82.     /// <summary>
  83.     /// Deletes a Contacts
  84.     /// </summary>
  85.     /// <param name="contactId">Contact Id</param>
  86.     public void DeleteContact(int contactId)
  87.     {
  88.         using (DevDataContext dev = new DevDataContext())
  89.         {
  90.             var contact = (from cont in dev.Contacts
  91.                             where cont.ContactID == contactId
  92.                             select cont).First();
  93.             dev.Contacts.DeleteOnSubmit(contact);
  94.             dev.SubmitChanges();
  95.         }
  96.     }
  97. }

Business Logic Layer

The project ContactServices.Business should contain Interfaces and Classes that call methods of the ContactServices.Data project. Creating Interfaces are important because of 3 main reasons in this Solution:

  • Establishes a contract for methods;
  • Sets a behaviour in classes that implement them;
  • Utilisation by WCF Service Application (project ContactServices.Host);

To perform that, create the interface IContactServices and the class called ContactServices that implements it, according to the code below:

Code Snippet
  1. [ServiceContract]
  2. public interface IContactServices
  3. {
  4.     [OperationContract]
  5.     Contact[] GetContacts();
  6.  
  7.     [OperationContract]
  8.     Contact GetContactById(int contactId);
  9.  
  10.     [OperationContract]
  11.     void UpdateContact(Contact contact);
  12.  
  13.     [OperationContract]
  14.     void AddContact(Contact contact);
  15.  
  16.     [OperationContract]
  17.     void DeleteContact(int contactId);
  18. }

 

Code Snippet
  1. public class ContactServices : IContactServices
  2. {
  3.     #region IContactServices Members
  4.  
  5.     public Contact[] GetContacts()
  6.     {
  7.         // Create your own business rules
  8.         return new ContactManager().GetContacts();
  9.     }
  10.  
  11.     public Contact GetContactById(int contactId)
  12.     {
  13.         // Create your own business rules
  14.         return new ContactManager().GetContactById(contactId);
  15.     }
  16.  
  17.     public void UpdateContact(Contact contact)
  18.     {
  19.         // Create your own business rules
  20.         new ContactManager().UpdateContact(contact);
  21.     }
  22.  
  23.     public void AddContact(Contact contact)
  24.     {
  25.         // Create your own business rules
  26.         new ContactManager().AddContact(contact);
  27.     }
  28.  
  29.     public void DeleteContact(int contactId)
  30.     {
  31.         // Create your own business rules
  32.         new ContactManager().DeleteContact(contactId);
  33.     }
  34.  
  35.     #endregion
  36. }

 

The class ContactServices contains CRUD methods that are going to be used by the BCS and tell by themselves. They work as a "thin layer" for handling data, because directly call the ContactManager methods in the project ContactServices.Data.

In this example no business rules were implemented, but you can if you need them. Just code against the methods above.

Service Host

The project ContactServices.Host was created to work as the WCF Service host, which let methods to be available for BCS consuming. Start renaming the file Service1.svc to ContactServices.svc and update the service reference at the page directive:

Code Snippet
  1. <%@ ServiceHost Language="C#" Debug="true" Service="ContactServices.Business.ContactServices" %>

 

This change is necessary because the ContactServices class needs to be mapped, which was implemented in the project ContactServices.Business. An update in the Web.config is also necessary, by editing it in the WCF Service Configuration Editor (available in the VS2010) or directly in the section system.serviceModel according to the code below:

Code Snippet
  1. <system.serviceModel>
  2.     <services>
  3.       <service behaviorConfiguration="ContactServicesBehavior" name="ContactServices.Business.ContactServices">
  4.         <endpoint binding="wsHttpBinding" bindingConfiguration="" contract="ContactServices.Business.IContactServices" />
  5.         <endpoint address="mex" binding="mexHttpBinding" bindingConfiguration="" contract="ContactServices.Business.IContactServices" />
  6.       </service>
  7.     </services>
  8.     <behaviors>
  9.       <serviceBehaviors>
  10.         <behavior name="ContactServicesBehavior">
  11.           <serviceMetadata httpGetEnabled="true" />
  12.           <serviceDebug includeExceptionDetailInFaults="true" />
  13.         </behavior>
  14.       </serviceBehaviors>
  15.     </behaviors>
  16.   </system.serviceModel>

Note: The behavior serviceDebug contains the attribute includeExceptionDetailInFaults to list in details any Web Service problem in the SharePoint Log, which is very useful during the WCF integration tests.

In the end, your solution should be similar to the Figure 3:

vstudio

Figure 3 – Final Solution

Deploy the solution in the IIS, so you can get the Url for creating the ECT, as demonstrated in the next sections.

Working with SharePoint Designer 2010

At this stage the solution was already created, and now the ECT needs to be created, by mapping the Web Service methods and parameters. The Figure 1 (Part II) displays the first step in creating the ECT, afterwards add a new connection (1) to the Web Service by choosing the External Data Source Type (2), according to the Figure 4:

conexao

Figure 4 - Creating a new connection

Set the connection parameters according to the Figure 5:

WCF

Figure 5 – WCF Connection details

Note: Some important considerations:

  • The WCF metadata can be obtained through WSDL or endpoint Mex. Both of them can be informed in the fields Service Metadata URL / Metadata Connection Mode, and are available in this solution.
  • The User’s Identity can be used to connect to the WCF service and hence to the database, that’s why the Windows Authentication is required.

After creating the WCF connection the CRUD operations need to be mapped. This is the stage in which the Web Service methods and parameters should be mapped for the creation of the ECT. For each figure below there is an operation whose parameters are displayed in tables:

addcontact

Figure 6 - AddContact Operation Properties

The operation AddContact as shown in Figure 6 has the following Input parameters according to the Tables 2 and 3:

Element .NET Type Map to Identifier Identifier Field Display Name Foreign Identifier
ContactID System.Int32 TRUE ContactID ContactID ID  
Address System.String FALSE   Address Address  
City System.String FALSE   City City  
CompanyName System.String FALSE   CompanyName Company Name  
ContactName System.String FALSE   ContactName Contact Name  
ContactTitle System.String FALSE   ContactTitle Contact Title  
Country System.String FALSE   Country Country  
Email System.String FALSE   Email E-mail  
Fax System.String FALSE   Fax Fax  
Phone System.String FALSE   Phone Phone  
PostalCode System.String FALSE   PostalCode Postal Code  
Region System.String FALSE   Region Region  
Table 2 - AddContact Operation Input Parameters

Element Default Value Filter Element Path
ContactID <<None>>   contact.ContactID
Address <<None>>   contact.Address
City <<None>>   contact.City
CompanyName <<None>>   contact.CompanyName
ContactName <<None>>   contact.ContactName
ContactTitle <<None>>   contact.ContactTitle
Country <<None>>   contact.Country
Email <<None>>   contact.Email
Fax <<None>>   contact.Fax
Phone <<None>>   contact.Phone
PostalCode <<None>>   contact.PostalCode
Region <<None>>   contact.Region
Table 3 - AddContact Operation Input Parameters (Continuation)

There are no Return parameters to be configured for the operation AddContact, so simply ignore the configuration screen and finish this mapping.

deletecontact

Figure 7 - DeleteContact Operation Properties

The operation DeleteContact as shown in Figure 7 has the following Input parameter according to the Table 4:

Element .NET Type Map to Identifier Identifier Display Name Default Value Filter Element Path
contactId System.Int32 TRUE ContactID ID <<None>>   contactId
Table 4 - DeleteContact Operation Input Parameters

getcontactbyid

Figure 8 - GetContactById Operation Properties

The operation GetContactById as shown in Figure 8 has the following Input and Return parameters according to the Tables 5, 6 and 7:

Element .NET Type Map to Identifier Identifier Display Name Default Value Filter Element Path
contactId System.Int32 TRUE ContactID ID <<None>>   contactId
Table 5 - GetContactById Operation Input Parameters

Data Source Element .NET Type Map to Identifier Identifier Field Display Name Foreign Identifier
ContactID System.Int32 TRUE ContactID ContactID ID  
Address System.String FALSE   Address Address  
City System.String FALSE   City City  
CompanyName System.String FALSE   CompanyName Company Name  
ContactName System.String FALSE   ContactName Contact Name  
ContactTitle System.String FALSE   ContactTitle Contact Title  
Country System.String FALSE   Country Country  
Email System.String FALSE   Email E-mail  
Fax System.String FALSE   Fax Fax  
Phone System.String FALSE   Phone Phone  
PostalCode System.String FALSE   PostalCode Postal Code  
Region System.String FALSE   Region Region  
Table 6 - GetContactById Operation Return Parameters

Data Source Element Element Path Required Read-Only Office Property
ContactID GetContactById.ContactID FALSE TRUE Custom Property
Address GetContactById.Address FALSE FALSE Business Address (BusinessAddress)
City GetContactById.City FALSE FALSE Business Address City (BusinessAddressCity)
CompanyName GetContactById.CompanyName FALSE FALSE Company Name (CompanyName)
ContactName GetContactById.ContactName TRUE FALSE Full Name (FullName)
ContactTitle GetContactById.ContactTitle FALSE FALSE Title (Title)
Country GetContactById.Country FALSE FALSE Business Address Country/Region (BusinessAddressCountry)
Email GetContactById.Email TRUE FALSE Email 1 Address (Email1Address)
Fax GetContactById.Fax FALSE FALSE Business Fax Number (BusinessFaxNumber)
Phone GetContactById.Phone TRUE FALSE Business Telephone Number (BusinessTelephoneNumber)
PostalCode GetContactById.PostalCode FALSE FALSE Business Address Postal Code (BusinessAddressPostalCode)
Region GetContactById.Region FALSE FALSE Business Address State (BusinessAddressState)
Table 7 - GetContactById Operation Return Parameters (Continuation)

getcontacts

Figure 9 - GetContacts Operation Properties

The operation GetContacts as shown in Figure 9 does not have Input parameters to be configured, but has the following Return parameters according to the Tables 8 and 9:

Element .NET Type Map to Identifier Identifier Field Display Name Foreign Identifier
ContactID System.Int32 TRUE ContactID ContactID ID  
Address System.String FALSE   Address Address  
City System.String FALSE   City City  
CompanyName System.String FALSE   CompanyName Company Name  
ContactName System.String FALSE   ContactName Contact Name  
ContactTitle System.String FALSE   ContactTitle Contact Title  
Country System.String FALSE   Country Country  
Email System.String FALSE   Email E-mail  
Fax System.String FALSE   Fax Fax  
Phone System.String FALSE   Phone Phone  
PostalCode System.String FALSE   PostalCode Postal Code  
Region System.String FALSE   Region Region  
Table 8 - GetContacts Operation Return Parameters

Element Element Path Required Read-Only Show in Picker Timestamp Field
ContactID GetContacts.GetContactsElement.ContactID FALSE TRUE FALSE FALSE
Address GetContacts.GetContactsElement.Address FALSE FALSE FALSE FALSE
City GetContacts.GetContactsElement.City FALSE FALSE FALSE FALSE
CompanyName GetContacts.GetContactsElement.CompanyName FALSE FALSE FALSE FALSE
ContactName GetContacts.GetContactsElement.ContactName TRUE FALSE FALSE FALSE
ContactTitle GetContacts.GetContactsElement.ContactTitle FALSE FALSE FALSE FALSE
Country GetContacts.GetContactsElement.Country FALSE FALSE FALSE FALSE
Email GetContacts.GetContactsElement.Email TRUE FALSE FALSE FALSE
Fax GetContacts.GetContactsElement.Fax FALSE FALSE FALSE FALSE
Phone GetContacts.GetContactsElement.Phone TRUE FALSE FALSE FALSE
PostalCode GetContacts.GetContactsElement.PostalCode FALSE FALSE FALSE FALSE
Region GetContacts.GetContactsElement.Region FALSE FALSE FALSE FALSE
Table 9 - GetContacts Operation Return Parameters (Continuation)

updatecontact

Figure 10 - UpdateContact Operation Properties

The operation UpdateContact as shown in Figure 10 has the following Input parameters according to the Tables 10 and 11:

Element .NET Type Map to Identifier Identifier Field Display Name Foreign Identifier
ContactID System.Int32 TRUE ContactID ContactID ID  
Address System.String FALSE   Address Address  
City System.String FALSE   City City  
CompanyName System.String FALSE   CompanyName Company Name  
ContactName System.String FALSE   ContactName Contact Name  
ContactTitle System.String FALSE   ContactTitle Contact Title  
Country System.String FALSE   Country Country  
Email System.String FALSE   Email E-mail  
Fax System.String FALSE   Fax Fax  
Phone System.String FALSE   Phone Phone  
PostalCode System.String FALSE   PostalCode Postal Code  
Region System.String FALSE   Region Region  
Table 10 - UpdateContact Operation Input Parameters

Element Default Value Filter Element Path
ContactID <<None>>   contact.ContactID
Address <<None>>   contact.Address
City <<None>>   contact.City
CompanyName <<None>>   contact.CompanyName
ContactName <<None>>   contact.ContactName
ContactTitle <<None>>   contact.ContactTitle
Country <<None>>   contact.Country
Email <<None>>   contact.Email
Fax <<None>>   contact.Fax
Phone <<None>>   contact.Phone
PostalCode <<None>>   contact.PostalCode
Region <<None>>   contact.Region
Table 11 - UpdateContact Operation Input Parameters (Continuation)

Note: Notice that in most cases just the configuration parameters (columns) nomenclature changes, but data is the same. I have decided to create configuration tables for each operation in order to facilitate the mapping with separate operations.

Once all the columns were set properly, save the ECT (1) and check the operations created (2), which can be edited at any time, according to the Figure 11:

savingECT

Figure 11 - Saving the ECT

Now it is possible to create an External List that will provide a visual interface for the external data in SharePoint 2010. In the same screen of External Content Types, choose the option External List on the context menu. Name it to “Contacts”, according to the Figure 12:

createECT

Figure 12 - Creating an External List

When the External List is created, the purpose of this article is accomplished. Now it is up to you to test the External List, which was already explained in the Part II. Reuse the same test and apply it here, since it was created for this purpose.

The fact of using a Web Service for integration in SharePoint 2010 shows us that it is possible to transmit data from and to any system that provides this interface. Unify data from different systems in SharePoint 2010! Now you know how to do it!

Reference:
http://msdn.microsoft.com/en-us/library/ee556826(v=office.14).aspx

Cheers

Marcel Medina

Click here to read the same content in Portuguese.