WCF web services and the Business Data Catalog (BDC)

The general message from Microsoft has been that the Business Data Catalog does not support WCF web services, however while at the MVP summit recently I found out that basicHttp web services would work. I’d suspected this for a while, but due to the message from MS never really looked into WCF further.

So first of all we had to ensure the BDC did work ok with WCF basicHttp web services – check!

Then we had to get BDC Meta Man to generate the application definition files for these web services – check!

Now what we need to do for you is give you a guide on how to create WCF web services for the Business Data Catalog and then integrate them in to MOSS using BDC Meta Man!

Building the web services

We’re using Visual Studio 2008 to build our WCF web service. You can get a 90 day trial of VS 2008 here. Because we’re working on a SharePoint server we need to manually create an IIS web site to host our WCF service first. You can do this by completing the following steps

1, Open IIS admin screen (administration tools -> IIS)

2, Right click on the Web Sites folder and choose New WebSite

3, Create your web site in IIS as you would do any normal one. Give it a host name, or a unique port – either way remember it.

4, Once the IIS web site has been created open up VS 2008, and choose to create a new Web Site.

5, From the project templates choose the WCF Service template, select HTTP as the location, and enter in the url of the web site we just created above in IIS.

6, Click OK and it’ll go and create our project for us in the specified web site. You’ll see the below project structure in your Solution Explorer

image

The example we are going to do is to return some product information, so lets rename IService.cs and Service to IProductService.cs and ProductService.cs. I’m not going to go into details about WCF, interfaces and other bits, if you want to learn more I suggest you get hold of this particular book:

Programming WCF Services (recommended by Dmitry!). I have this particular book.

In IProduct.cs we can clean out the existing OperationContract’s and the DataContract. Firstly we are going to define our own DataContract, this is going to be a class that we use to describe the data that we are going to return. Here’s my DataContract:

[DataContract]
public class Product
{
    private int _ProductId;
    [DataMember]
    public int ProductId
    {
        get { return _ProductId; }
        set
        {
            _ProductId = value;
        }
    }

    private string _ProductName;
    [DataMember]
    public string ProductName
    {
        get { return _ProductName; }
        set
        {
            _ProductName = value;
        }
    }

    private int _StockAmount;
    [DataMember]
    public int StockAmount
    {
        get { return _StockAmount; }
        set
        {
            _StockAmount = value;
        }
    }

    private int _SalePrice;
    [DataMember]
    public int SalePrice
    {
        get { return _SalePrice; }
        set
        {
            _SalePrice = value;
        }
    }
}

Now we need to change our interface class to setup the methods we want our endpoints to provide functionality of. If the interface hasn’t been renamed from IService, simply rename it to IProductService, then we want to define our OperationContracts as so:

[ServiceContract]
public interface IProductService
{

    [OperationContract]
    List<Product> GetProducts();

    [OperationContract]
    Product GetProductById(int Id);

    [OperationContract]
    List<int> GetProductIds();
}

For anybody who has developed a web service before to use with the BDC this will look pretty familiar. What we need to do is have a web method for each of the BDC method types. Therefore:

GetProducts – this will be our Finder method. Any filters we would want to use would need to be defined as input parameters for the method.

GetProductById – this is our SpecificFinder method. Pass in the id of a product, and we get the full product information back.

GetProductIds – this is our IdEnumerator method. It simply returns a list of the product ids available. This method is only ever used by search so if you do not want to crawl this entity you do not need to worry about creating this method.

Now we have created our Interface, we actually need to build the methods that are going implement them. Open up ProductService.cs. You may need to change the name of this class to ProductService if VS 2008 hasn’t automatically done it for you, and also change the Interface it is going to implement to IProductService. You can also clear out the code that was automatically put in the class for you. We need to implement our three methods in this class, that is GetProducts, GetProductById, and GetProductIds. You would usually do some data access to SQL or something along those lines and return the data, but to save space we are going to hard code some objects. Here is what our ProductService class should look like:

public class ProductService : IProductService
{
    public List<Product> GetProducts()
    {
        List<Product> products = new List<Product>();

        // this is where we would do our data access…
        Product product = new Product();
        product.ProductId = 1;
        product.ProductName = “Red Car”;
        product.SalePrice = 6000;
        product.StockAmount = 2;

        // add the product to our collection…
        products.Add(product);

        return products;
    }

    public Product GetProductById(int productId)
    {
        Product product = new Product();

        // this is where we would do our data access…
        product.ProductId = 1;
        product.ProductName = “Red Car”;
        product.SalePrice = 6000;
        product.StockAmount = 2;

        return product;
    }

    public List<int> GetProductIds()
    {
        List<int> productids = new List<int>();

        // this is where we would run a query to get all
the ids we want to index…
        productids.Add(1);

        return productids;
    }

}

That is our c# code written. Now we need to make an edit to web.config. Here we are defining all our WCF endpoints and the interfaces they must implement. You’ll find the line

<service name=”Service” behaviorConfiguration=”ServiceBehavior”>
                <!– Service Endpoints –>
                <endpoint address=”” binding=”wsHttpBinding” contract=”IService”>

We need to change this to

<service name=”ProductService” behaviorConfiguration=”ServiceBehavior”>
                <!– Service Endpoints –>
                <endpoint address=”” binding=”basicHttpBinding” contract=”IProductService”>

There are 3 things we need to change, the service name, the binding type and the contract. The service name and contract represent the changes we made in our class names, the binding -> BDC will only support basicHttpBinding, which generally is equivalent to .NET 2.0 asmx web services.

One final change, double click on service.svc. This is your actual web service page that you can browse to. Here again we need to go from

<%@ ServiceHost Language=”C#” Debug=”true” Service=”Service” CodeBehind=”~/App_Code/Service.cs” %>

to

<%@ ServiceHost Language=”C#” Debug=”true” Service=”ProductService” CodeBehind=”~/App_Code/ProductService.cs” %>

Which again just reflects the changes we made to our class names.

Press F5 to build your WCF project and navigate to your service.svc page. Hopefully you should see something like below:

image

We can take the url for the wsdl file from this page, select and copy it to the clip board.

Now we need to generate our application definition file for our WCF web service, open BDC Meta Man (make sure you are using 3.0.0.4 or above) and connect to a web service

image

In the Data Source screen paste in the url to your WSDL location, and ensure you have the WCF Web Service checkbox ticked.

Now what we need to do is exactly the same as a normal web service, drag and drop your web methods on to the design surface to configure your entities. I’m not going to repeat those steps here, but you can read how to do it and watch a screencast from here:

http://support.lighteningtools.com/default.asp?W4

The only step that is different is when you go to add your SpecificFinder method. You will see that although you have created an input parameter of ID, the WCF web service adds another parameter automatically called IDSpecified. According to this blog post here adding the extra boolean parameter, per parameter you manually create, increases interoperability – but to me it just seems to confuse everything!

Either way you do not need to worry about IDSpecified, just configure the ID column as an BDC identifier parameter as you would with any ASP.NET 2.0 web service, we take care of the rest for you! 🙂

And that’s it….once you have configured your entity you can generate your application definition file, import it to MOSS 2007 and get using it as you would do any other BDC data source – magic eh?!

 

The one thing we are working on now is association methods for WCF web services, currently you can only create basic standalone entites. We’ll have this sorted for the next version though so keep watching.

If you have any comments on this blog post or the information contained in it please use the comments. We will eventually turn it into a Knowledge Base article so now if you change to let us know if you do not understand anything!!!

<Nick />