Wednesday, July 11, 2012

CRM 2011 - Accessing and filtering custom/crm WCF Data Service (oData) from sandboxed Plugin

As described in some MSDN-Forums and by Eric Pool, Quering data against the context directly via Linq in sandboxed plugins is not possible. You can retrieve the whole DataSet, but filtering is not possible.

If you need to access and filtering your results from an oData endpoint (also custom ones), you can use the following syntax.

Example OrganizationDataService (with FirstOrDefault):
//Define the Request URI
Guid accountId = new Guid("66BD3ABE-D2CA-E111-9E1F-000C29BDAB09");
string serviceAddress = @"http://crm:5555/DEV/XRMServices/2011/OrganizationData.svc/";
string accountQueryByPrimaryKey = string.Format("AccountSet(guid'{0}')", accountId.ToString());
Uri svcUri = new Uri(serviceAddress);
Uri accountUri = new Uri(string.Format("{0}{1}", serviceAddress, accountQueryByPrimaryKey));
 
//Create context and credentials ('My' is the name of the CRM organization, these classes are created when you add a service reference to CRM DataService endpoint)
CrmService.MyContext context = new CrmService.MyContext(svcUri);
context.Credentials = new System.Net.NetworkCredential("username""password""domain");
 
//Retrieve data
Account retrievedAccount = context.Execute<Account>(accountUri).FirstOrDefault();


Example Custom Service (with Enumeration):
// Define the Request URI
Uri svcUri = new Uri(@"http://crm:8888/MyDataService/CustomDataService.svc/");
Uri uriAccounts = new Uri(string.Format("{0}{1}", svcUri, "ACCOUNT(3)"));
 
// Create the context
DataServiceContext context = new DataServiceContext(svcUri)

// Enumerate over the query result.
StringBuilder sb = new StringBuilder();
foreach (ACCOUNT account in context.Execute<ACCOUNT>(uriAccounts)) { sb.AppendLine("Name: " + account.name); }

The trick is to use the oData (URI) for Filtering and to interprete just the results.

You can find the MSDN description here.

4 comments:

  1. Hi Markus! Great post, btw! Just wanted to ask you.. in the first piece of code you posted, where did you get the class "MyContext" (and its namespace) from? is it an ordinary Service Reference to CRM OrganizationData.svc?
    Cheers!

    ReplyDelete
    Replies
    1. Hi Josefo,

      you receive this class when you add your servicereference to your plugin project (or your data layer project of your plugin structure).
      - Rightclick "Service Reference"
      - Add Service Reference
      - Enter the address of your custom DataService (this is NOT the CRM-Service)

      Delete
    2. Thanks for you reply, Markus!
      So why are you passing "http://crm:5555/DEV/XRMServices/2011/OrganizationData.svc/" as a parameter to the constructor of "MyContext"? (that uri looks a lot like the CRM REST endpoint!)

      Delete
  2. Hi Josefo,

    i checked the code again (it was a long time ago ;) )
    You are right. The first example is the CRM call. So my description (first anwser) is correct but you have to add the CRM DataService URL instead of the custom one. Rest works fine (i tested it again).

    The Contextname is defined when you create the service reference.

    [NameSpace].[OrgName][Context]

    You can define the namespace on the "Add Service Reference" wizard. OrgName is predefined by your company/organization and Context is a defined word, defined by CRM endpoint.

    Hope this helps.

    Cheers

    ReplyDelete