SharePoint Blogs / SharePoint University
SharePoint Blogs and SharePoint University - all in one place!
Need SharePoint Training? Attend a SharePoint Bootcamp!

Please delete cookies related to sharepointblogs.com and sharepointu.com to resolve login issues!

Free SharePoint Business Data Catalog Column

I have decided to release the custom BDC column that I created to the public domain. This custom column type provides a BDC Column type that can be created at the Site Column level and therefore used in Site Content Types. Out of the box this is not possible, and the ability to reuse BDC columns across sites and content has been identified as a common requirement. At this stage there are a number of things that are not yet implemented, including related fields, refreshing and nicer admin UI. However, I have created a Project on CodePlex so if you are interested in participating let me know! There is plenty of scope for features and function!

The new column is included in a SharePoint Solution (.wsp package) and can be deployed to SharePoint via the standard solution deployment framework.

Once installed a new column type is available to be chosen when creating columns in lists and when creating site columns:

When the BDC field type is selected the user is presented with a custom UI which displays all BDC Applications (and their Entities) registered on the current Server’s Share Services Provider. The user also has the ability to set the fields that will be displayed in the Entity picker dialog when searching.

 Enough of the UI already, where's the code I hear you ask! ... 

To get the data for the Application and Entity drop downs, we query the BDC metadata:

//Declare the relevent references
using Microsoft.Office.Server.ApplicationRegistry.Runtime;
using Microsoft.Office.Server.ApplicationRegistry.MetadataModel;

For the Applications…

//Get the Line of Business Instances.
NamedLobSystemInstanceDictionary sysInstances = ApplicationRegistry.GetLobSystemInstances();
cboApplications.Items.Clear();

//Loop through their names and add them to the drop down.
foreach (String name in sysInstances.Keys)
{
 cboApplications.Items.Add(name);
}

For the Entities, once an application is selected…

LobSystemInstance currentInstance = sysInstances[cboApplications.SelectedValue];

//Get the Entities for the given Application.
NamedEntityDictionary currentEntities = currentInstance.GetEntities();

foreach (String name in currentEntities.Keys)
{
 cboEntities.Items.Add(name);
}

Once created the column appears as a Site Column, and is available for use in Content Types.

When rendered in a list form, the field is very similar to the out of the box BDC column:

 

The picker dialog used to find and select Entity items is almost identical to the standard SharePoint BDC Picker. This dialog is AJAX enabled so that if AJAX is enabled on the server the user will experience the AJAX feel, ie. no page refreshes for search and selection. The fall back if AJAX is not enabled is a standard aspx style form with full page refresh required for operations such as searching. There is a great blog entry from the Microsoft SharePoint Team (via Mike Ammerlaan’s blog on the subject) on Integrating ASP.Net AJAX with SharePoint that you should read if you want AJAX to be available on you SharePoint server. If you install your AJAX enabled solution on a server where this process is not complete, it should still function in the standard ASP.Net (ie. without AJAX) way. In theory, now that SP1 is out this is supported too, although I'm not sure that configuring it is any easier...

The Pop Up is called via a JavaScript function on the book image above. This function build a URL based on the Application, Entity and Display Fields properties of the column. To save time and make the popup consistent with the standard UI, it is based on the pickerdialog.master Master page.

The fields displayed in the list view are set when the column is defined, but can be modified once the column is created by editing the settings of the new column.

 
We use the following code to get the list of Finders and populate the dropdown of fields to search on. Finders are defined in the XML definition of the Application and control the way data is retrieved from the external source in relation to searching.

NamedLobSystemInstanceDictionary sysInstances = ApplicationRegistry.GetLobSystemInstances();

LobSystemInstance myIns = sysInstances[Request[“BDCApplication”]];

Entity myEntity = myIns.GetEntities()[Request[“BDCEntity”]];

FilterCollection fc = myEntity.GetFinderFilters();

The GridView containing the search results is contained within an AJAX UpdatePanel so that operations that would normally cause postback (and hence full page refreshes) are handled in the background. Inside the CreateChildControls we set up the AJAX UpdatePanel, GridView and Trigger Controls.

dvUpdatePanel = new System.Web.UI.UpdatePanel();

ajaxScriptManager = new System.Web.UI.ScriptManager();
ajaxScriptManager.EnablePartialRendering = true;
Controls.Add(ajaxScriptManager);

//Fixup the UpdatePanel. This function is defined in the blog from SharePoint Team on AJAX and SharePoint.
EnsureUpdatePanelFixups();

//Create a conditional Update Panel and make sure the Children of the Panel cause updates.
dvUpdatePanel.UpdateMode = System.Web.UI.UpdatePanelUpdateMode.Conditional;
dvUpdatePanel.ChildrenAsTriggers = true;
dvUpdatePanel.ContentTemplateContainer.Controls.Add(gvResults);

//Create a postback trigger on the search button to handle the search.
System.Web.UI.AsyncPostBackTrigger uptTrigger=new System.Web.UI.AsyncPostBackTrigger();
uptTrigger.ControlID = btnGoSearch.UniqueID;
uptTrigger.EventName = "Click";
dvUpdatePanel.Triggers.Add(uptTrigger);

//Set up a new SharePoint Grid View and turn off Auto Generate so we can control the columns.
gvResults = new SPGridView();
gvResults.ID="gvResults";
gvResults.AutoGenerateColumns = false;

 

Searching for Entities to show in the GridView is handled using the objects and methods provided by the SharePoint object model:

NamedLobSystemInstanceDictionary sysInstances = ApplicationRegistry.GetLobSystemInstances();
LobSystemInstance myIns = sysInstances[Request[“BDCApplication”]];
Entity myEntity = myIns.GetEntities()[Request[“BDCEntity”]];

//Build up a finder collection which is the query for the BDC source.
FilterCollection fc = myEntity.GetFinderFilters();

for (int iCounter = 0; iCounter < fc.Count; iCounter++)
      {
       if (fc[iCounter].Name == sFinderName || sFinderName == "")
            {
             switch (fc[iCounter].GetType().FullName)
                  {
                   case "Microsoft.Office.Server.ApplicationRegistry.Runtime.WildcardFilter":
                         ((WildcardFilter)fc[iCounter]).SystemIndependentValue = "*" + sQueryString + "*";
    break;
   case "Microsoft.Office.Server.ApplicationRegistry.Runtime.ComparisonFilter":
                         ((ComparisonFilter)fc[iCounter]).Value = Convert.ChangeType(sQueryString, ((ComparisonFilter)fc[iCounter]).GetFilterValueType());
                               break;
   case "Microsoft.Office.Server.ApplicationRegistry.Runtime.LimitFilter":
                         ((LimitFilter)fc[iCounter]).Value = Math.Min(0xc9, ((LimitFilter)fc[iCounter]).MaximumValue);
                               break;
     }
      }
 }

IEntityInstanceEnumerator prodEntityInstanceEnumerator = myEntity.FindFiltered(fc, myIns);

//Create a data table to store the results.
DataTable Results = new DataTable("BDCData");
Resultset.Tables.Add(Results);

//Get the collection of IDs and create an array to store their names.
IdentifierCollection EntIDS = myEntity.GetIdentifiers();
string[] sIDNames = new string[EntIDS.Count];

//Get the names.
int nCounter = 0;

foreach (Identifier currentID in EntIDS)
{
 sIDNames[nCounter] = currentID.Name;
 nCounter++;
}

//Add columns to the results data table named as per the Entities fields.
//Check if there any of the fields have show in picker set so we know to display only those fields.
Boolean blnShowInPickers = false;
foreach (Field f in myEntity.GetFinderView().Fields)
 {
        if (f.TypeDescriptor.GetProperties().ContainsKey("ShowInPicker"))
              {
               if (((Boolean)f.TypeDescriptor.GetProperties()["ShowInPicker"]))
               {
                     blnShowInPickers = true;
    }
   }
 }

DataColumn currentColumn = null;
foreach (Field f in myEntity.GetFinderView().Fields)
      {
 //Add the default display name to the caption if there is one so we can pull it out when we create the list.
       if (f.DefaultDisplayName == "")
            {
             currentColumn = Results.Columns.Add(f.Name);
     }
            else
            {
             currentColumn = Results.Columns.Add(f.Name);
                currentColumn.Caption = f.DefaultDisplayName;
     }

            if (blnShowInPickers)
            {
  //Only show fields that have show in picker set (if any do).
             if (f.Name != sTitle)
                  {
                   if (f.TypeDescriptor.GetProperties().ContainsKey("ShowInPicker"))
                        {
                         if (((Boolean)f.TypeDescriptor.GetProperties()["ShowInPicker"]))
                              {
                               currentColumn.ExtendedProperties.Add("ShowInPicker", "TRUE");
         }
         else
                              {
                               currentColumn.ExtendedProperties.Add("ShowInPicker", "FALSE");
         }
   }
    }
                  else
                  {
                   currentColumn.ExtendedProperties.Add("ShowInPicker", "TRUE");
    }
     }
            else
            {
  //Else if the field is an identifier or it’s the title field then show it.
             if (f.TypeDescriptor.ContainsIdentifier || f.Name == sTitle)
                  {
                   currentColumn.ExtendedProperties.Add("ShowInPicker", "TRUE");
    }
                  else
                  {
                   currentColumn.ExtendedProperties.Add("ShowInPicker", "FALSE");
      }
      }
 }

//Loop through the found Entity instances and add them to the results.
while (prodEntityInstanceEnumerator.MoveNext())
{
 try
 {
  IEntityInstance IE = prodEntityInstanceEnumerator.Current;
  DataRow newResultRow = Results.NewRow();
  System.Collections.IList MyList = (System.Collections.IList)IE.GetIdentifierValues();

  //Create an array to hold the identifiers.
  object[] oIdentitiers = new object[sIDNames.Length];

  for (int iCounter = 0; iCounter < MyList.Count; iCounter++)
  {
   oIdentitiers[iCounter] = MyList[iCounter].ToString();
  }

  foreach (Field f in myEntity.GetFinderView().Fields)
  {
   if (IE[f] != null)
   {
    newResultRow[f.Name] = IE[f];
   }
  }

  Results.Rows.Add(newResultRow);
 }

 catch (Exception rowex)
 {
 }
}

//Grab the Display Fields and add columns for them in the Grid View.
gvResults.DataSource = Resultset;
string[] keys = Request["DisplayFields"].ToUpper().Split(',');
gvResults.DataKeyNames = keys;
gvResults.Columns.Clear();

foreach (DataColumn currentCol in ((DataTable)gvResults.DataSource).Columns)
{
        string[] displayFields = Request["DisplayFields"].ToUpper().Split(',');
        if (Array.BinarySearch(displayFields,currentCol.ColumnName.ToString().ToUpper())>=0)
  
 {
                BoundField newfield=new BoundField();
                newfield.HeaderText=currentCol.ColumnName.ToString();
                newfield.DataField=currentCol.ColumnName.ToString();
         gvResults.Columns.Add(newfield);
 }
}

//Bind the results to the grid.
gvResults.DataBind();

Feel free to wander over to CodePlex and grab a copy if this is a requirement for you or your clients and feel free to offer any suggestions you think of!

I'm off for a month with the Kids and the Family, so I wish you all a great Xmas, Holiday, or work time!

 

 


 


Posted 12-21-2007 10:02 AM by adrh

Comments

SharePoint, SharePoint and stuff wrote BDC Site Column
on 12-21-2007 4:35 AM

Ín der Beta2 Version vom MOSS war es noch möglich, Websitespalten an Daten aus dem BDC (Business Data

JoeD wrote re: Free SharePoint Business Data Catalog Column
on 12-21-2007 8:06 AM

I will check this out over the weekend.... sounds awesome!  Not being able to have a BDC column in a content type is a big hole in Sharepoint.  This will be a big help.

useful sharepoint links « SharePoint, Wiki, Create, Column, Data, Business, Free, Catalog « konfabulieren wrote useful sharepoint links &laquo; SharePoint, Wiki, Create, Column, Data, Business, Free, Catalog &laquo; konfabulieren
on 12-22-2007 12:43 AM

Pingback from  useful sharepoint links &laquo; SharePoint, Wiki, Create, Column, Data, Business, Free, Catalog &laquo; konfabulieren

Blog del CIIN wrote WSS 3.0 & MOSS: Recopilación de enlaces interesantes (XII)
on 12-23-2007 4:07 PM

Una vez más, en esta nueva entrega recogemos el recopilatorio de enlaces, recursos y diferentes elementos

Joe wrote re: Free SharePoint Business Data Catalog Column
on 12-26-2007 7:56 PM

I tried installing this on my development MOSS 2007 server.  I can add the field to my content type and use it in a list.  However when I try to click the search button (the little book), it takes me to a standard MOSS error screen with the error "File not found".

(Of course in true MOSS fashion, it does not clue you in on what file it cannot find...)

Any ideas?  I've looked in the _layouts folder and the MVBDCLookUp.aspx file and mvpickerdialog.master are both there.  I do not have AJAX installed, but it sounded like it was not required.

adrh wrote re: Free SharePoint Business Data Catalog Column
on 12-26-2007 8:22 PM

Joe, my apologies, but while it does not require AJAX to run, it does reference the AJAX Assembly. I could have added that to the WSP, but then it would get removed when the solution is retracted and break AJAX!! So, the best solution for you is to install AJAX, but not go through all the configuration for it to run on MOSS and things should work better!

Joe wrote re: Free SharePoint Business Data Catalog Column
on 12-27-2007 8:22 PM

Installing AJAX worked - that allowed me to add a list item to a list with the BDC column.

However, when I edit the item, I get "An unexpected error has occurred." and it will let me get to the Web Parts Maintenance Page (which shows only the ListFormWebPart is on it).

Dirk wrote re: Free SharePoint Business Data Catalog Column
on 01-04-2008 10:21 AM

I installed the wsp-File via stsadm, but can't see any changes in MOSS. Did I forget something?

Mirrored Blogs wrote BDC Site Column
on 01-09-2008 7:10 PM

Ín der Beta2 Version vom MOSS war es noch möglich, Websitespalten an Daten aus dem BDC (Business Data

SharePoint link love: 12-28-2007 at Virtual Generations wrote SharePoint link love: 12-28-2007 at Virtual Generations
on 01-24-2008 1:50 AM

Pingback from  SharePoint link love: 12-28-2007 at  Virtual Generations

Steve wrote re: Free SharePoint Business Data Catalog Column
on 02-10-2008 6:09 PM

Where is the .wsp file? There doesn't appear to be a current release on the Codeplex site.  Am I just being thick?

Warren wrote re: Free SharePoint Business Data Catalog Column
on 04-16-2008 5:08 AM

Hi again. I've found a possible solution to my own question to you earlier ... basically, I've added a Web property to your BDCField class and changed the ContextId propert to check whether SPContext.Current is null, and if so to use the Web property to generate a ContextId. This is needed because using the BDCField in a feature receiver, SPContext.Current is null.

Then I add the following code in the feature receiver of my app, to set the custom properties.

           SPField f = web.Fields[@"Brand"];

           BDCField ff = (BDCField)f;

           ff.Web = web;

           ff.Application = @"MyCustomCorpWebInstance";

           ff.Entity = @"Brand";

           ff.DisplayFields = @"PreferredName";

           ff.ReturnField = @"PreferredName";

           ff.PushChangesToLists = true;

           ff.Update();

So the site column definition does not include the <Customization> element ...

Seems like a real kludge to me, but I am under severe pressure to "get it working" ... so this will do for now.

Warren wrote re: Free SharePoint Business Data Catalog Column
on 04-17-2008 6:32 AM

And finally ... the answer to my question ...

1. Add a safecontrol entry in your web config

     <SafeControl Assembly="MacroView.SharePointFields.BDCColumn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6f7d66a3bb7de652" Namespace="MacroView.SharePointFields" TypeName="*" Safe="True" AllowRemoteDesigner="True" />

2. Register the MacroView control in your page layout:

<%@ Register TagPrefix="MacroView" Namespace="MacroView.SharePointFields" Assembly="MacroView.SharePointFields.BDCColumn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=6f7d66a3bb7de652" %>

3. Add a BDC Field edit control inside a PublishingWebControls:EditModePanel runat="server"

    <MacroView:BDCFieldControl FieldName="Brand" BDCApplication="CadburyCorpWebInstance" BDCEntity="Brand" BDCDisplayFields="PreferredName" BDCReturnField="PreferredName" runat="server" />

!!

Adrian Fiechter wrote re: Free SharePoint Business Data Catalog Column
on 05-20-2008 8:50 AM

Customization can't be deploied with a feature by default (SP1).

To do it, include the following wss.xsd patch:

www.codeplex.com/.../View.aspx

Adrian Fiechter wrote re: Free SharePoint Business Data Catalog Column
on 05-20-2008 11:16 AM

BDCField.cs Line 129:

When i am activating the list instance over a feature, i have no context. That means SPContext.Current == null.

What is with the following way to solve the problem:

public int ContextId

       {

           get

           {

               if (SPContext.Current != null)

               {

                   return SPContext.Current.GetHashCode();

               }

               else

               {

                   return -1;

               }

           }

       }

nbhatt wrote re: Free SharePoint Business Data Catalog Column
on 10-12-2008 9:33 PM

Adrian,

Firstly, thank you for this awesome post and sharing the code with all.

I am facing one challenge if someone can help me fix it. After I add the BDC column to any list, I am able to edit any item i.e. the EditForm.aspx page for the list opens up without any problem. But when I click on view item in a list that has this BDC column, i.e. DispForm.aspx, it always throws an error.

Following is the error from SharePoint log file -

w3wp.exe (0x0580) 0x174C  CMS     Publishing  7fz4  High      WARNING: Cannot change FormContext.FormMode to [Invalid] because it is already set to [Display]  

w3wp.exe (0x0580) 0x174C  CMS     Publishing  7fz4  High      WARNING: Cannot change FormContext.FormMode to [Invalid] because it is already set to [Display]  

w3wp.exe (0x0580) 0x174C  CMS     Publishing  8ztg  Medium    Got List Item Version, but item was null.  

w3wp.exe (0x0580) 0x174C  CMS     Publishing  8ztg  Medium    Got List Item Version, but item was null.  

w3wp.exe (0x0580) 0x174C  CMS     Publishing  8ztg  Medium    Got List Item Version, but item was null.  

Your help is highly appreciated.

Thank you.

Higo wrote re: Free SharePoint Business Data Catalog Column
on 11-21-2008 4:40 AM

I want to get the source from codeplex but, there is no source there.

Sander wrote re: Free SharePoint Business Data Catalog Column
on 01-06-2009 7:51 AM

Hi Aaron,

Very helpfull this project. I hope you can help me one more step. I have a key in my database which is defined as a macroview BDC column in a contenttype. Now I also need to display any related columns (i need just display). Equivalent to the 'Add a column to display each of these additional fields' option when using a normal business data column. Is there a way to achief this?

Mail me at (removeunderscores)_till_ebuo_rren@zo_nnet.nl

adrh wrote re: Free SharePoint Business Data Catalog Column
on 01-11-2009 6:04 PM

Sander, No, there is no way to do this using the current version of the Field Type. I have thought about looking at this, but there are some technical issues to resolve, such as how you link the fields, and the fact that as far as I can tell (from the limited MSDN documentation) you can only have one releated field for each actual field. I'm not sure how Microsoft manages to get multiple if they truly built the BDC Field Type from standard WSS Field Types...

Jaz wrote re: Free SharePoint Business Data Catalog Column
on 02-02-2009 4:47 PM

Great tool.  Site Column makes BDC more compelling.  

We need to support multi-selection.  Is this done and the method level?  Does your code need to be modified to support multi-select?  What is blnMultipleSelect used for, anything?

Need SharePoint Training? Attend a SharePoint Bootcamp!
Posts (c) their respective authors. Everything else (c) 2009 SharePoint Experts, Inc.