Wednesday, May 16, 2012

DOMDocument60 limitation : Unspecified Error while loading Xml

A customer was using DOMDocument60 to create an xml document and then use the same class to load the generated xml document. The document generation part of the program was working fine however when trying to load the document it was returning an unspecified error. The error code was –2147467259  and it made no sense as to why would DOMDocument60 fail to load an Xml document generated by it.

On investigating a bit further I found that the XML being generated had a very long attribute with lot of XML Entities (e.g. &) being used in its value. As I started deleting these XML Entities from the attribute value I saw that the exact position at which the error is happening started shifting.

On playing a bit more I found that the DOMDocument60 can process an attribute with maximum of 65527 XML entities in an attribute. If you have anything more then that then you start getting an Unspecified Error with error code –2147467259 . I believe it might be a buffer overflow exception in the parser. I couldn’t find any documentation around this problem or a fix for this problem however I do believe that this is an extreme usage of Xml.

As a best practice the Xml attributes should have small readable values. For anything as big as 65527 characters in the attribute value I think the Xml Element is the best choice. One should refactor the Xml to ensure that such values are part of element and not attributes.



Tuesday, May 8, 2012

Authenticating Third party Services to CRM as Web Resources

One of the capabilities of CRM is to build a Web Resource which can help you expose a custom UI on CRM Forms or Dashboards. We can also use the web resources to call third party services and expose some interesting functionality in the web resource. This web resource can then be hosted in the CRM UI and call your WCF service to show interesting data. The problem though is how do you enable authentication on your WCF service.

CRM supports multiple authentication methods. If its an on premise installation it could be using AD, ADFS etc. for authentication. It could be an IFD deployment using a 3rd party authentication provider. If its CRM online it could be using Live authentication or authenticating using the federation with Office 365.

It becomes quite a task if the 3rd party provider has to provide a web resource and ensuring that they authenticate against every possible authentication mechanism that CRM could be using. I tried to get help from a few discussion groups and is a potential solution

Use a shared key to authenticate the callers of the service. Store this key in a CRM entity instance and use it every time (in the WCF header) you call the WCF service hosted on your server. This key can be stored at the time one buys the license to use your web resource. If you plan to impersonate the user then let every user have a different key and map them in a database on the WCF service side. With impersonation enabled the user provisioning headaches for the administrator will increase but at least you can achieve it.

The drawback of the above solution is that the shared key is easily hackable since it will be available on the client side as part of the javascript. The potential solution to that could be to have a synchronous plug in on the server side which provisions a separate key by calling your server every time the web resource is being used. It will no doubt increase the round trips and hence performance to some extent. But if it needs to be really safe then that’s a solution.

Its not as elegant as we want it to be but it can definitely work. I would wait for CRM Online to support a single mode of authentication using Azure Active Directory to at least make it consistent in CRM online world. i.e. with every CRM online subscription you get a subscription of Azure Active Directory. And then your web resource can pass the token to WCF service hosted by you which can check with the Azure Active Directory for validity and do the job for you.

Hope this helps!!