Created
September 22, 2012 05:50
-
-
Save johnnyreilly/3765280 to your computer and use it in GitHub Desktop.
A class which when added to a web application exposes the provides an OData service on top of CRM / xRM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Data.Services; | |
using System.Data.Services.Common; | |
using System.Linq; | |
using System.Web; | |
using System.ServiceModel.Web; | |
using Microsoft.Xrm.Client; | |
using log4net; | |
namespace CrmOData | |
{ | |
/// <summary> | |
/// Exposes an OData service providing access to CRM | |
/// | |
/// Examples of how to use service. | |
/// | |
/// URI : http://myWebServer/CrmOData/Crm.svc | |
/// Purpose : Demonstrates exposed endpoints | |
/// | |
/// URI : http://myWebServer/CrmOData/Crm.svc/myCustomer | |
/// Purpose : Demonstrates how to retrieve all customers | |
/// | |
/// URI : http://myWebServer/CrmOData/Crm.svc/myCustomer?$filter=lastName eq 'Reilly' | |
/// Purpose : Demonstrates how to retrieve all customers with the Surname "Reilly" | |
/// | |
/// URI : http://myWebServer/CrmOData/Crm.svc/myCustomer?$select=firstName,lastName | |
/// Output : Does not work. | |
/// | |
/// "$select statements are not supported. This problem is being discussed | |
/// here http://social.msdn.microsoft.com/Forums/en/adodotnetdataservices/thread/366086ee-dcef-496a-ad15-f461788ae678 | |
/// and is caused by the fact that CrmDataContext implements the IExpandProvider interface which in turn causes | |
/// the DataService to lose support for $select projections" | |
/// | |
/// See http://social.microsoft.com/Forums/en/crmdevelopment/thread/31daedb4-3d75-483a-8d7f-269af3375d74 for original post discussing this | |
/// | |
/// URI : http://myWebServer/CrmOData/Crm.svc/myCustomer(guid'783323a1-b1f1-4910-b5be-a2f37e62d0ba')/currentBalance | |
/// Purpose : Retrieves the current balance of the customers account | |
/// | |
/// URI : http://myWebServer/CrmOData/Crm.svc/myCustomer(guid'783323a1-b1f1-4910-b5be-a2f37e62d0ba')/currentBalance/$value | |
/// Output : 321186905.8600 | |
/// Purpose : The raw value | |
/// | |
/// URI : http://myWebServer/CrmOData/Crm.svc/myCustomer(guid'783323a1-b1f1-4910-b5be-a2f37e62d0ba')?$expand=transactions | |
/// Purpose : Retrieves a customer by their guid'783323a1-b1f1-4910-b5be-a2f37e62d0ba', with the transactions property expanded (the equivalent of Include in Entity Framework I guess) | |
/// </summary> | |
public class Crm : DataService< Xrm.DataContext > | |
{ | |
private static ILog _log; | |
/// <summary> | |
/// Initialise the service (this method is called only once to initialize service-wide policies.) | |
/// </summary> | |
/// <param name="config"></param> | |
public static void InitializeService(DataServiceConfiguration config) | |
{ | |
//Allows access to everything | |
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead); | |
config.SetEntitySetPageSize("*", 10); //Only allow access to 10 items at a time - don't want to bring down CRM | |
config.SetServiceOperationAccessRule("*", ServiceOperationRights.AllRead); | |
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2; | |
// set cache policy to this page | |
HttpContext context = HttpContext.Current; | |
HttpCachePolicy cachePolicy = HttpContext.Current.Response.Cache; | |
// server&private: server and client side cache only - not at proxy servers | |
cachePolicy.SetCacheability(HttpCacheability.ServerAndPrivate); | |
// default cache expire: 60 seconds | |
cachePolicy.SetExpires(HttpContext.Current.Timestamp.AddSeconds(60)); | |
// cached output depends on: accept, charset, encoding, and all parameters (like $filter, etc) | |
cachePolicy.VaryByHeaders["Accept"] = true; | |
cachePolicy.VaryByHeaders["Accept-Charset"] = true; | |
cachePolicy.VaryByHeaders["Accept-Encoding"] = true; | |
cachePolicy.VaryByParams["*"] = true; | |
//allow client to send Cache-Control: nocache headers to invalidate cache | |
cachePolicy.SetValidUntilExpires(false); | |
//Log service startup initialisation | |
_log = log4net.LogManager.GetLogger("Crm.svc"); | |
_log.Info("Crm.svc initialising..."); | |
} | |
/// <summary> | |
/// Allows the user to get the id of a specific CrmEntity given a supplied entity name | |
/// and a supplied predicate which consists of a propertyName and a string propertyValue (eg "112001-S"). | |
/// | |
/// If there is a need for a predicate with different type of value (eg int / datetime / decimal) | |
/// then it could be introduced | |
/// | |
/// Example URI : http://myWebServer/CrmOData/Crm.svc/GetId?entityName='myCustomer'&propertyName='customerNumber'&propertyValue='23456KL-P' | |
/// </summary> | |
/// <param name="entityName">eg "myCustomer"</param> | |
/// <param name="propertyName">eg "customerNumber"</param> | |
/// <param name="propertyValue">eg "23456KL-P"</param> | |
/// <returns></returns> | |
[WebGet] | |
public Guid? GetEntityId(string entityName, string propertyName, string propertyValue) | |
{ | |
var entities = CurrentDataSource.GetEntities(entityName); | |
var entitiesWhere = entities.Where(x => (x.GetPropertyValue(propertyName) as string) == propertyValue); | |
var guid = entitiesWhere.Select(x => x.Id) | |
.SingleOrDefault(); | |
return guid; | |
} | |
/// <summary> | |
/// Handle exceptions | |
/// </summary> | |
/// <param name="args"></param> | |
protected override void HandleException(HandleExceptionArgs args) | |
{ | |
base.HandleException(args); | |
//Log all exceptions | |
_log.Error(string.Format("\r\nResponseContentType: {0}\r\nResponseStatusCode: {1}\r\nResponseWritten: {2}\r\nUser: {3}{4}", | |
args.ResponseContentType, args.ResponseStatusCode, args.ResponseWritten, HttpContext.Current.User.Identity.Name, args.Exception.GetExceptionDetails()), | |
args.Exception); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment