Eric White's Blog
Open XML, SharePoint, and Office
Consuming External OData Feeds with SharePoint BCS
I wrote an MSDN Magazine article, Consuming External OData Feeds with SharePoint BCS, which was published in April, 2011. Using BCS, you can connect up to SQL databases and web services without writing any code, but if you have more exotic data sources, you can write C# code that can grab the data from anywhere you can get it. Knowing how to write an assembly connector is an important skill for pro developers who need to work with BCS. This article shows how to write a .NET Assembly Connector for BCS. It uses as its data source an OData feed. Of course, as you probably know, SharePoint 2010 out-of-the-box exposes lists as OData feeds. The MSDN article does a neat trick – you write a .NET assembly connector that consumes an OData feed for a list that is on the same site. While this, by itself, is not very useful, it means that it is super easy to walk through the process of writing a .NET assembly connector.
I write the article and the code for the 2010 Information Worker Demonstration and Evaluation Virtual Machine (RTM). Some time ago, I wrote a blog post, How to Install and Activate the IW Demo/Evaluation Hyper-V Machine.
The MSDN article contains detailed instructions on how to create a read-only external content type that consumes an OData feed. This is an interesting exercise, but advanced developers will want to create .NET assembly connectors that can create/read/update/delete records. The procedures for doing all of that were too long for the MSDN magazine article, so of necessity, the article is limited to creating a read-only ECT.
However, I have recorded a screen-cast that walks through the entire process of creating a CRUD capable ECT. It is 25 minutes long, so some day when you feel patient, you can follow along step-by-step-by-step, creating a CRUD capable ECT that consumes an OData feed. Here is the video:
The procedure requires code for two source code modules: Customer.cs, and CustomerService.cs.
Here is the code for Customer.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Contoso.Crm
{
public partial class Customer
{
public string CustomerID { get; set; }
public string CustomerName { get; set; }
public int Age { get; set; }
}
}
Here is the code for CustomerService.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
namespace Contoso.Crm
{
public class CustomerService
{
public static Customer ReadCustomer(string customerID)
{
TeamSiteDataContext dc =
new TeamSiteDataContext(
new Uri("http://intranet.contoso.com/_vti_bin/listdata.svc"));
dc.Credentials = CredentialCache.DefaultNetworkCredentials;
var customers =
from c in dc.Customers
where c.CustomerID == customerID
select new Customer()
{
CustomerID = c.CustomerID,
CustomerName = c.CustomerName,
Age = (int)c.Age,
};
return customers.FirstOrDefault();
}
public static IEnumerable<Customer> ReadCustomerList()
{
TeamSiteDataContext dc =
new TeamSiteDataContext(
new Uri("http://intranet.contoso.com/_vti_bin/listdata.svc"));
dc.Credentials = CredentialCache.DefaultNetworkCredentials;
var customers =
from c in dc.Customers
select new Customer()
{
CustomerID = c.CustomerID,
CustomerName = c.CustomerName,
Age = (int)c.Age,
};
return customers;
}
public static void UpdateCustomer(Customer customer)
{
TeamSiteDataContext dc =
new TeamSiteDataContext(
new Uri("http://intranet.contoso.com/_vti_bin/listdata.svc"));
dc.Credentials = CredentialCache.DefaultNetworkCredentials;
var query =
from c in dc.Customers
where c.CustomerID == customer.CustomerID
select new Customer()
{
CustomerID = c.CustomerID,
CustomerName = c.CustomerName,
Age = (int)c.Age,
};
var customerToUpdate = query.FirstOrDefault();
customerToUpdate.CustomerName = customer.CustomerName;
customerToUpdate.Age = customer.Age;
dc.UpdateObject(customerToUpdate);
dc.SaveChanges();
}
public static void DeleteCustomer(string customerID)
{
TeamSiteDataContext dc =
new TeamSiteDataContext(
new Uri("http://intranet.contoso.com/_vti_bin/listdata.svc"));
dc.Credentials = CredentialCache.DefaultNetworkCredentials;
var query =
from c in dc.Customers
where c.CustomerID == customerID
select new Customer()
{
CustomerID = c.CustomerID,
CustomerName = c.CustomerName,
Age = (int)c.Age,
};
var customerToDelete = query.FirstOrDefault();
dc.DeleteObject(customerToDelete);
dc.SaveChanges();
}
public static void CreateCustomer(Customer customer,
out Customer returnedCustomer)
{
// create item
TeamSiteDataContext dc =
new TeamSiteDataContext(
new Uri("http://intranet.contoso.com/_vti_bin/listdata.svc"));
dc.Credentials = CredentialCache.DefaultNetworkCredentials;
CustomersItem newCustomer = new CustomersItem();
newCustomer.CustomerID = customer.CustomerID;
newCustomer.CustomerName = customer.CustomerName;
newCustomer.Age = customer.Age;
dc.AddToCustomers(newCustomer);
dc.SaveChanges();
returnedCustomer = customer;
}
}
}
[...] http://ericwhite.com/blog/2011/05/23/consuming-external-odata-feeds-with-sharepoint-bcs/ Leave a Comment LikeBe the first to like this post. [...]
Hey Eric, I think your blog is really good. I’m developing my first Sharepoint 2010 services and I have a WCF WebService that recieves a parameter and returns a filtered list if data. I already have configured and deployed an external content type, configured it’s CRUD and created an external list.
I’m trying to create a webpart that calls my custom method and shows this data somehow(preferablly using the already existing list) And i’m using a GenericInvoker to do so, but now I find the oblstacle of casting the results from “Object” to my External Content Type… I’m already out of ideas so I’d really apreciate your help….
Thanke You
Mauricio
[...] Consuming External OData Feeds with SharePoint BCS [...]
Hi there, I found your website via Google at the same time as looking for a related topic, your website came up, it looks great. I’ve bookmarked it in my google bookmarks.