none
Establishing a CRM connection per HTTP request

    Question

  • I am building a .NET based REST service which intended to be used by a bunch of enterprise applications for interacting with
    an on premise MS CRM instance .
    The service uses the ServerConnection class from the CRM SDK samples(crmservicehelpers.cs) using AD authentication
    for connecting to MS-CRM services.

    A connection is established per HTTP request.

    I've read that the authentication process adds the most overhead in establishing a connection to CRM.
    Unfortunately, we do not have ADFS with STS and hence there is no token based authentication available for AD authentication.

    My question is whether establishing a connection per HTTP request could cause performance issues under load.
    If so, are there any other prescribed solutions for this scenario?


    -Abhijeet


    • Edited by Abhijeet P Tuesday, August 27, 2013 4:36 AM update
    Tuesday, August 27, 2013 4:35 AM

All replies

  • I would suggest creating a connection per session and adding the created ServerConnection to the session variables.
    Thursday, August 29, 2013 10:54 AM
  • I would suggest creating a connection per session and adding the created ServerConnection to the session variables.

    This is an ASP.NET WebAPI based REST (HTTP) service. HTTP services are inherently intended to be stateless.

    Although one "can" access and use the Session object it is not recommended to do so.

    Check this SO post


    -Abhijeet

    Friday, August 30, 2013 3:47 AM
  • Hi,

    Rather than use the ServerConnection use the Microsoft.Xrm.Client assembly to use web.config connection strings - this will allow you to declare your OrganizationService or OrganizationServiceContext in the Web.config using a connection string, and the authentication is handled for you. It doesn't use a challenge/response with every call - but rather preauthenticates the webrequest.

    If you are interested, you can also easily create a REST ADO.NET dataservice by simply inheriting from your OrganizationServiceContext:

    DataService<Xrm.XrmServiceContext>

    See - http://msdn.microsoft.com/en-us/library/gg695790.aspx for more information - it's a walk through that show you how to configure your web.config to contain connection info and also how to create a DataSevice that inherits from your Xrm types generated using CrmSvcUtil. It's great stuff!

    It's important that you understand how you are going to protect your data as well - you will provide a 'proxy' user that connects to CRM so anyone accessing your REST WebAPI will have the same access as this user (unless you restrict in code) - this means you need to secure the service equally as well.

    Exciting stuff! 

    Cheers,

    Scott



    Scott Durow
    Blog www.develop1.net    Follow Me
    Rockstar365
    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    Friday, August 30, 2013 8:09 AM
    Answerer
  • Hi Scott,

    Thanks for the response.

    I decided on using WEBApi over WCF Data services primarily because I did not want to be directly coupled to MS-CRM data
    types. Using the DataService<XrmServiceContext> binds the clients to using MSCRM specific data types and the thought is to have a domain specific model exposed to client with OData support
    such that if and when the CRM system changes the upstream clients don't need to change drastically.
    The WebAPI service uses query expressions to implement the OData support against the domain specific model for
    interacting with MSCRM.

    I also decided to use the ServerConnection class because it has all the infrastructure for connection management for
    IFD/On Premise using AD auth (with and without STS) and I won't need to change any upstream code if and when STS is available.

    Hope this above information provides better context for my question on establishing CRM connections on a per HTTP request basis


    -Abhijeet

    Sunday, September 01, 2013 6:22 PM
  • Hi Abhijeet,

    Understand about the Webapi but the ServerConnection is quite unsophisticated compared to the CrmConnection client - the CrmConnection has automatic support (more infact) for Online and IFD. It also has built in thread safety that the ServerConnection class does not. I would highly recommend you using it for your ASP.NET project since that is what is was designed for.

    hth,

    Scott


    Scott Durow
    Blog www.develop1.net    Follow Me
    Rockstar365
    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    Sunday, September 01, 2013 7:08 PM
    Answerer
  • Hi,

    You might find a blog post I did on connection management - http://develop1.net/public/post/MicrosoftXrmClient-Part-2.aspx

    hth,

    Scott


    Scott Durow
    Blog www.develop1.net    Follow Me
    Rockstar365
    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    Sunday, September 01, 2013 7:34 PM
    Answerer
  • Hi,

    You might find a blog post I did on connection management - http://develop1.net/public/post/MicrosoftXrmClient-Part-2.aspx

    hth,

    Scott


    Scott Durow
    Blog www.develop1.net    Follow Me
    Rockstar365
    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    Thank you Scott! That article is very useful. One question though. "The good news is that all the token expiry and thread safety is handled for you automatically provided you reuse an instance of the CrmConnection each time you create an OrganizationService:"

    Can you clarify how to reuse the instance of CrmConnection and how is the thread safety part handled automatically?

    Are you suggesting creation of an application wide singleton instance of CrmConnection and on every HTTP request create a new OrganizationServiceProxy instance passing in the singleton instance of CrmConnection?

    Thank you for your time and insights and by the way I've been using your Ribbon Workbench  quite heavily lately and it rocks!


    -Abhijeet

    Sunday, September 01, 2013 8:40 PM
  • Hi Abhijeet,

    Yes, the CrmConnection is thead safe to use application wide, however it is easier to add a connection to the app.config and instantiate using the connection string name. This is the subject of the next post in my series on Microsoft.Xrm.Client!

    You would add the following to your app.config and use the name in the constructor.

    <connectionStrings>
      <add name="Crm" connectionString="Url=http://crm.contoso.com/xrmContoso;"/>
    </connectionStrings>

    You can define you service and service context as well in this way - http://msdn.microsoft.com/en-us/library/gg695805.aspx

    Glad you are finding the Ribbon Workbench useful!

    Cheers,

    Scott


    Scott Durow
    Blog www.develop1.net    Follow Me
    Rockstar365
    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    Sunday, September 01, 2013 9:30 PM
    Answerer
  • Hi Abhijeet,

    Yes, the CrmConnection is thead safe to use application wide, however it is easier to add a connection to the app.config and instantiate using the connection string name. This is the subject of the next post in my series on Microsoft.Xrm.Client!

    You would add the following to your app.config and use the name in the constructor.

    <connectionStrings>
      <add name="Crm" connectionString="Url=http://crm.contoso.com/xrmContoso;"/>
    </connectionStrings>

    You can define you service and service context as well in this way - http://msdn.microsoft.com/en-us/library/gg695805.aspx

    Glad you are finding the Ribbon Workbench useful!

    Cheers,

    Scott


    Scott Durow
    Blog www.develop1.net    Follow Me
    Rockstar365
    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    Thanks Scott. One other question. The one benefit or OrganizationServiceProxy is that one can set the CallerId property so that the actual call into CRM executes as the incoming user instead of a "proxy user" (I defer the "security" aspect to CRM since it is already well implemented and much more thoroughly tested than any custom security mechanism that I would implement myself)

    I did not see this property on OrganizationService. Is there a way to achieve the same using

    Microsoft.Xrm.Client.Services.OrganizationService ?

    I noticed that the CallerId property is available on CrmConnection. This would prevent me from having a singleton instance of CrmConnection  since I would need to create a new CrmConnection on each web request based on the incoming user wouldn't I? Do you anticipate this being an issue or a potential performance bottleneck?


    -Abhijeet




    • Edited by Abhijeet P Sunday, September 01, 2013 9:52 PM update
    Sunday, September 01, 2013 9:38 PM
  • Hi,

    Actually, I don't think your scenario was planned for when writing the Simplified Connection Microsoft.Xrm.Client API - You would have to have a separate CrmConnection per UserId since having a single CrmConnection and changing the UserId is not thread safe. You might be better suing the Microsoft.Sdk.Xrm.Client API to get full control at a lower leve.

    The import thing is to cache an instance of IServiceConfiguration<IOrganizationService> and the AuthenticationCredentials (both of which are threadsafe) so that you can use it to get the instances of the OrganziationServiceContext and reuse the authenticated WCF channel. This will avoid the constant re-auth that you are seeing. The Helper ServerConnection class in the SDK uses this approach with the GetProxy function where you need to pass the ServerConnection.Configuration instance - although this class is really designed for Console applications and is more of an example. 

    For more information see "Improve Service Channel Allocation Performance" in http://msdn.microsoft.com/en-us/library/gg509027.aspx and also - http://blogs.msdn.com/b/crminthefield/archive/2013/06/12/10347451.aspx 

    hth,

    Scott


    Scott Durow
    Blog www.develop1.net    Follow Me
    Rockstar365
    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    Monday, September 02, 2013 9:14 AM
    Answerer
  • Hi,

    Actually, I don't think your scenario was planned for when writing the Simplified Connection Microsoft.Xrm.Client API - You would have to have a separate CrmConnection per UserId since having a single CrmConnection and changing the UserId is not thread safe. You might be better suing the Microsoft.Sdk.Xrm.Client API to get full control at a lower leve.

    The import thing is to cache an instance of IServiceConfiguration<IOrganizationService> and the AuthenticationCredentials (both of which are threadsafe) so that you can use it to get the instances of the OrganziationServiceContext and reuse the authenticated WCF channel. This will avoid the constant re-auth that you are seeing. The Helper ServerConnection class in the SDK uses this approach with the GetProxy function where you need to pass the ServerConnection.Configuration instance - although this class is really designed for Console applications and is more of an example. 

    For more information see "Improve Service Channel Allocation Performance" in http://msdn.microsoft.com/en-us/library/gg509027.aspx and also - http://blogs.msdn.com/b/crminthefield/archive/2013/06/12/10347451.aspx 

    hth,

    Scott


    Scott Durow
    Blog www.develop1.net    Follow Me
    Rockstar365
    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    Thanks Scott. I am currently using ServerConnection and GetProxy to get an instance of the OrgService  per HTTP request and setting the CallerId based on the id of the incoming user. Do you anticipate this causing any performance issues/bottlenecks? I'll mark your above reply as the answer since it confirms that the only way to achieve my scenario is to create a connection per request per user. Any insights you can provide on performance implication would be very much appreciated.

    On a side note, I would request any insights you might have on another question I've posted on the forums

    http://social.microsoft.com/Forums/en-US/583db66b-1684-4f6e-b233-f9497072a796/guidance-on-setting-the-aggregatequerylimit-deployment-property-on-the-config-db

    Thanks again!


    -Abhijeet

    Wednesday, September 11, 2013 3:46 AM
  • Hi Abhijeet,

    Performance will be optimal provided you are using a cached ServiceConfiguration so that WCF channel allocation re-uses existing authenticated credentials - this will prevent a re-auth with every request (which will reduce performance significantly - can be as much as 10 times!)

    P.S. I've replied to your other post as well!

    Cheers,

    Scott


    Scott Durow
    Blog www.develop1.net    Follow Me
    Rockstar365
    If this post answers your question, please click "Mark As Answer" on the post and "Mark as Helpful"

    Thursday, September 12, 2013 7:47 AM
    Answerer