Monday, March 2, 2009

Custom Web Part using BDC Object Model

Sharepoint ( MOSS 2007 ) provides two BDC related web parts namely Business Data List Web Part and Business Data Related List Web Part. This blog will demonstrate writing custom web parts that read data through BDC APIs.

In this example a simple web part reads data from BDC APIs and displays it in web part panel. The custom web part (XBdc) is shown in the following figure.


Figure 1 : Custom web part reading data from BDC APIs


To create a custom web part, I will be using Visual Studio 2008 without Visual Studio .NET Extensions for SharePoint 3.0. If you download Visual Studio .NET Extensions for SharePoint, it will be a bit easier. Since extensions are not available ( as of March2009 ) for x64, I will create XBdc Web Part without using extensions.

First create a Visual Studio project of "Class Library" type. Lets name the project "XBdc" for extended BDC. The name is not important and can be anything. After creating the project add references to Microsoft.SharePoint.Portal.dll ( the dll can be found in %system drive%\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI folder ).



Figure 2 : Class Library project in Visual Studio


You will also need to sign the assembly as the web part assembly will be deployed to GAC. For signing the assembly, load project properties and check the "Sign the assembly" checkbox and choose private key file.( see following figure ).



Figure 3 : Signing custom web part assembly


The goal of the web part is to display BDC entities in a DataGrid. For this we will need references to System.Data.dll and System.Web.dll in the project.

Implementation

XBdc web part class needs to inherit from
System.Web.UI.WebControls.WebParts.WebPart . There is another WebPart class in SharePoint, but it should be avoided for the reasons listed here. Also XBdc class will override
CreateChildControls and Render methods to attach DataGrid and populate it with BDC entities.


[System.Xml.Serialization.XmlRoot(Namespace = "http://jardalu/Samples")]
public class XBdc : System.Web.UI.WebControls.WebParts.WebPart
{
protected override void CreateChildControls(){ ... }
protected override void Render(System.Web.UI.HtmlTextWriter writer){ ... }
}

To use BDC APIs, we will need to use the following namespaces

using Microsoft.Office.Server.ApplicationRegistry.MetadataModel;
using Microsoft.Office.Server.ApplicationRegistry.Runtime;

For simplicity sake, only these two namespaces are used. For complete list of APIs please visit MSDN site. Also, to keep things simple the Entity Name/Lob System Instance Name/Entity columns is hardcoded in the code.


// hardcoded entity fields
private string[] headers = { "Id", "Name", "Contact", "Phone", "Address" };

Method LoadCustomersFromBdc() will read entities from BDC and create a DataTable that can be bounded to the DataGrid in the web part. In the method, LobSystemInstance and Entity is searched through ApplicationRegistry object. Once entity is found, the method instance of type Finder is loaded. MethodInstance is executed to get all the entity instances for the finder. Finally instances are added in the data table using EntityAsDataRow method. Please note BDC also provides EntityAsDataTable property to create the data table itself.

private DataTable LoadCustomersFromBdc()
{
DataTable dt = new DataTable();
foreach (string header in headers)
{
dt.Columns.Add(new DataColumn(header));
}

// hardcoded LobSystemInstance and Entity name
LobSystemInstance lsi = ApplicationRegistry.GetLobSystemInstanceByName("CustomerLobSystemInstance");
Entity entity = lsi.GetEntities()["Customer"];
MethodInstance mi = entity.GetFinderMethodInstance();
IEntityInstanceEnumerator enumerator = entity.FindFiltered(mi.GetFilters(), lsi);
while (enumerator.MoveNext())
{
IEntityInstance instance = enumerator.Current;
if (instance == null) continue;
instance.EntityAsDataRow(dt);
}

return dt;
}

Its time now to create the DataGrid control and attach the control to Web Part ( see method CreateChildControls() )

protected override void CreateChildControls()
{
this.grid = new DataGrid();
this.grid.Width = new Unit(100, UnitType.Percentage);

this.grid.HeaderStyle.Font.Size = 10;
this.grid.HeaderStyle.Font.Bold = true;
this.grid.AlternatingItemStyle.BackColor = Color.Gray;

foreach (string header in headers)
{
BoundColumn column = new BoundColumn();
column.HeaderText = header;
column.DataField = header;
this.grid.Columns.Add(column);
}
this.grid.AutoGenerateColumns = false;

this.Controls.Add(this.grid);
base.CreateChildControls();
}

Finally DataGrid is bond to the BDC entities

protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
this.grid.DataSource = this.LoadCustomersFromBdc();
this.grid.DataBind();

this.grid.RenderControl(writer);
}


Once the custom Web Part is compiled, its time to hook it up in the SharePoint. Before hooking the XBdc Web Part, we will upload the "Customer" application definition file as the custom Web Part has hardcoded entity/lob system instance names ( see accompaning source code for model file and LOB code ).

Uploading Customer Model

  1. Compile the project CustomersLob accompanying in the source code

  2. GAC the assembly using gacutil tool

  3. Upload the accompaning model (customer.xml) into BDC



Registering XBdc Web Part in SharePoint

  1. GAC the Web Part assembly using gacutil. Please note the public key token for the assembly.

  2. Locate the virtual directory for SharePoint web site ( in the IIS Manager ). Typically the virtual directory is %system drive%\INETPUB\WWROOT\WSS\80 ( assuming web site is on port 80 )

  3. In the virtual directory, edit the web.config and add XBdc custom part in SafeControls section ( choose appropriate assembly and namespace ).

    <SafeControl
    Assembly="XBdcWebPart, Version=1.0.0.0, Culture=neutral, PublicKeyToken=def61931772d3147"
    Namespace="Jardalu.Samples.XBdcWebPart"
    TypeName="*" Safe="True" AllowRemoteDesigner="True" />

  4. Then browse to the WebSite, and go to Site Actions -> Site Settings -> Modify All Site Settings. Under that, click on "Web Parts" under Galleries.

  5. Click on "New" in the toolbar, and find the XBdc custom webpart as shown below

  6. Check the checkbox, go to the top, click on "Populate Gallery".

  7. At this time XBdc custom web part is ready to be consumed.



Source Code

Sample with complete source code can be downloaded from here.

As-is
The source code/software is provided "as-is". No claim of suitability, guarantee, or any warranty whatsoever is provided. Source Code and executable files can not be used in commercial applications.