Author Archives: waelhamze

Building CRM Solutions with TFS Build

Using the xRM CI Framework and TFS Build you can easily automate the build of your CRM Solutions.

In this post  will go through the details of the Dynamics CRM TFS Build template “DynamicsCrm2011Template.11.1.xaml” that makes of all this possible. Before I proceed further, a TFS Build template is a workflow that defines the flow and steps of a TFS Build. This is normally implemented using Windows Workflow Foundation. TFS Build allows you provide custom build templates to suite your needs.

The Dynamics CRM 2011 TFS build template extends the default TFS Build template to provide the extra steps required to Build CRM Solutions and implement Continuous Integration.

Below are the high level steps the Dynamics CRM Build will go through. Note that all these steps can be configured using parameters and can be turned on or off to suite your specific scenarios.

  1. Compile your Visual Studio Solution (Plug-ins, Custom Workflows, Silverlight, Dependencies, etc…)
  2. Run Unit Tests
  3. Invoke CRM Developer Toolkit CrmPackage project deployment (deploy solution components from source control)
  4. Publish Customizations
  5. Update CRM Solution version number from TFS Build number (the part after the ‘_’)
  6. Export your CRM Solution from a CRM Instance
  7. Unpack an exported CRM Solution using Solution Packager and update your source control
  8. Update version number of your unpacked solution stored in source control (“\Other\Solution.xml”)
  9. Pack your customizations from source control and produce a CRM Solution Package
  10. Invoke a PowerShell script to further extend the Build and/or deploy your solution and dependencies
  11. Run Integration tests on your selected environment

Using various combinations of the above you can implement different types of builds to suite your needs.

Note that all components required to build your CRM Solution should be either in source control or CRM instance for the Build Template to work correctly.

As I mentioned before all of the above can be configured very easily using the TFS Build user interface inside visual studio. So you can create a new build definition in a matter of minutes.

DynamicsCRMBuildDefinition

To visualize the build workflow for Dynamics CRM, below is a Visio diagram showing the main flow.

Dynamics CRM 2011 TFS Build Template Flow

Dynamics CRM 2011 TFS Build Template Flow

In the coming posts I will go into the details of the different types of Builds you can create and how you can use this template to implement these.

In the meantime you can have a go at creating a build definition using the template after following the setup instructions in my previous post.

xRM CI Framework is now available

The xRM CI Framework is a set of tools that allows you to quickly and easily implement Continuous Integration for your Dynamics CRM solutions.

The framework provides an implementation of some of the concepts detailed in the recently published Microsoft Dynamics CRM Application Lifecycle Management (ALM) white paper. The framework is also compatible with the Dynamics CRM Developer toolkit from the SDK.

The framework allows you to improve efficiency and consistency by automating your build and deployments using Team Foundation Server (TFS) 2012 and PowerShell.

Below is the list of features provided in the first release.

  1. Dynamics CRM TFS Build Template that allows you to easily create your Check-In, Continuous Integration, Nightly and Release Builds
  2. Dynamics CRM PowerShell Cmdlets to extend your build process and automate your deployments
  3. Ability to support online & offline Dynamics CRM Builds (Build from CRM instance v.s. from source control)
  4. Ability to trigger automated deployments from your TFS Builds
  5. Ability to run Integration Tests from your TFS Builds after deployment
  6. Automatic versioning of your CRM Solutions inline with your TFS Build number
  7. Ability to automate the updating of your customisations stored in source control from CRM using the solution packager
  8. Support for Dynamics CRM on-premise & online
  9. Support for TFS 2012 on-premise & online
  10. Easy to use and extensible to meet your specific scenarios

Apart from the benefits above you will also get all the benefits of using Team Foundation Server Build to improve your ALM.

There will be a series of blog articles to show you how you can use the framework to implement your specific scenarios in your projects.

In the meantime you can download a copy of the framework from the visual studio gallery.

Don’t forget to check out the setup post on how to get started.

Installing the xRM CI Framework

In this post I will provide you with the details on how to setup  the xRM CI Framework.

The process is simple and easy. After this stage you will be ready to create your automated builds and deployments.

Framework Download & Installation:

  1. The first step is to download the setup files from the visual studio gallery.
  2. Run the setup which will copy all the required files to the installation directory “C:\Program Files (x86)\Xrm CI Framework”.

Automated Build Template Setup:

  1. The first step is to copy the contents from the installation directory “C:\Program Files (x86)\Xrm CI Framework\CRM 2011\VS 2012\TFS Build Templates” and store them under source control in TFS.
  2. Once the files are under source control, you will need configure your Build Controller to use the custom assemblies required by the template.
  3. Follow this link to perform the two steps above. This is based on TFS online but you can use the same process for TFS on premise.
  4. The final step is to register the Dynamics CRM 2011 Build templates with TFS. Follow this link to register the template by selecting the template from the location in source control from the previous step.
  5. Now you should be ready to create your first Build Definition using the Dynamics CRM 2011 template.

Dynamics CRM PowerShell Cmdlets Setup

  1. Start the PowerShell Console and run the command below.
  2. Import-Module “C:\Program Files (x86)\Xrm CI Framework\CRM 2011\PowerShell Cmdlets\Xrm.Framework.CI.PowerShell.dll”. This will give you access to all the xRM CI Framework PowerShell Cmdlets.
    If you are running this on Windows 7 or 8. You will most probably have PowerShell using .NET 2.0 and encounter some errors. To force PowerShell to use .NET follow this blog.
  3. Create your PowerShell Script using the Cmdlets

This article demonstrated how to setup the xRM CI Framework. In the next blogs i will show you how to configure different types of builds and deployment to suite your specific scenario.

Building the CRM Developer Toolkit Solution (CrmPackage) in the Cloud (TFS Online)

As most of you probably know, Microsoft released an online version of  TFS that is host in the cloud. You can find more information about this http://tfs.visualstudio.com/.

This allows you to store and manage all the artefacts related to your application life cycle management in the cloud. This includes source control, work item management and testing.

One of the cool features that TFS provides is Automated Builds. This can among other things compile your code in a consistent way and also run automated tests and produce packages such as your CRM solutions.

TFS online comes with a hosted pre-configured build controller that you can use to build your software. This comes pre-configured with a list of software packages. These don’t include the CRM Developer Toolkit. As such trying to compile any Visual Studio projects created using the CRM Developer Toolkit will not work by default.

In this post I will show you how to configure your CrmPackage project to make it compatible with the hosted build controller.

A typical project created using the CRM Developer Toolkit will look something like the below. This contains Plug-in,Workflow and  XAML Workflow projects. It also contains the CrmPackage Project that is used to deploy all the previous components.
EmptyDeveloperToolkitProject

Once you created the projects, you will notice that all references to the CRM Sdk and Developer Toolkit Libraries are pointing to the local installation folder of the Developer Toolkit which will not be available on the Hosted Build Server.

DeveloperToolkitPluginDefaultReference

To get everything to build online, you will need to store all CRM Sdk libraries in source control and change all the references in your projects (Plugins, Workflows, XAML Workflows) to point to the relative path in your workspace.

SampleLibDeveloperToolkitPluginLocalReference

The next step is to fix the CrmPackage Project. Right click on the project and select Unload.

UnloadPackageProject

Then Right click and edit.

EditPackageProject

Locate the import statement below. This imports the developer toolkit targets from the installation directory.

  1. <ImportProject=$(MSBuildExtensionsPath32)\Microsoft\CRM\Microsoft.CrmDeveloperTools.12.targets />

Before you change that, you will need to copy the files from the installation directory below and store them in source control along with the CRM Sdk binaries.

DeveloperToolkitTargetsDirectory

Now change the import statement to the relative path in your source control workspace as below.

  1. <ImportProject=..\Lib\CrmSdk\Microsoft.CrmDeveloperTools.12.targets />

Now you can save and reload the package project.

ReloadPackageProject

At this stage you should be able to rebuild the package project successfully  and all the dependencies should be in your workspace together with your source code. Check-in all your changes into source control.

The next step is to create a Build Definition. For example you can create a build definition to compile your code and run your uni tests every time somebody check-in any code. This will ensure that the latest version of your code is always working.

More information on creating build definitions can be found http://msdn.microsoft.com/en-us/library/ms181716.aspx

In my next posts I will show you how to configure and modify your Build definitions to make them more useful. This will include things such as producing CRM Solutions.

Dynamics CRM 2011 Organization Service Tracing

In Dynamics CRM 4.0 you used to be able to run Fiddler to look at the contents of the HTTP requests being made to the CRM Service. When playing with the Dynamics CRM 2011 SDK i was curious to have a look at the messages that are being send across the wire between my development PC and the Dynamics CRM Organization service. This can be useful to look sometimes at what is happening behind the scenes when you work with the early bound model/LINQ and also when debugging various scenarios. When trying to run Fiddler on an on-premise deployment i noticed that the messages were encrypted. So i figured another way to achieve this using WCF standard mechanism since the CRM Service and SDK libraries are build around the WCF stack. All you need to do is put the sample cconfiguration below to your application configuration file. This will log any messages that are send and received on the client side. All you have to do now is open the trace log file with the Service Trace Viewer (SvcTraceViewer.exe). A similar mechanism can also be adoped on the server side.

  <system.diagnostics>
    <sources>
      <source name ="System.ServiceModel.MessageLogging"
              switchValue="Verbose, ActivityTracing">
        <listeners>
          <add name="xml" />
        </listeners>
      </source>
    </sources>
    <sharedListeners>
      <add name="xml" type="System.Diagnostics.XmlWriterTraceListener"
           traceOutputOptions="LogicalOperationStack"
           initializeData="C:\log\CRMTrace.svclog" />
    </sharedListeners>
    <trace autoflush="true" />
  </system.diagnostics>
  <system.serviceModel>
    <diagnostics>
      <messageLogging
           logEntireMessage="true"
           logMalformedMessages="false"
           logMessagesAtServiceLevel="true"
           logMessagesAtTransportLevel="false"/>
    </diagnostics>
  </system.serviceModel>

I will show samples messages captured using the Fiddler and WCF traces for the code below.

            using (OrganizationServiceProxy proxy = CreateProxy())
            {
                WhoAmIRequest req = new WhoAmIRequest();
                WhoAmIResponse res = proxy.Execute(req) as WhoAmIResponse;
                Console.WriteLine("WhoAmIUserId: " + res.UserId);
                return res.UserId;
            }
Below is the Fiddler trace the request. As you can see nothing very useful.
 
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <s:Header>
    <a:Action s:mustUnderstand="1" u:Id="_4">http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute</a:Action>
    <a:MessageID u:Id="_5">urn:uuid:e5c9ff4c-0752-4c24-9dbb-8ac49e6f4c46</a:MessageID>
    <a:ReplyTo u:Id="_6">
      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
    <VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink">uIDPoxO2jGq+wmJNtFyl0vt7JzoAAAAA4Whc+xgnSU6m/mUlFbvDxSBygozH25xJqktDA+Roo0AACQAA</VsDebuggerCausalityData>
    <a:To s:mustUnderstand="1" u:Id="_7">http://[Server]/[Org]/XRMServices/2011/Organization.svc</a:To>
    <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <u:Timestamp u:Id="uuid-4e6e29af-ab82-458e-9dbc-e8a0aac0342a-4">
        <u:Created>2011-04-09T22:02:06.117Z</u:Created>
        <u:Expires>2011-04-09T22:07:06.117Z</u:Expires>
      </u:Timestamp>
      <c:SecurityContextToken u:Id="uuid-8fcc72f9-4325-4918-84d2-20233d35381a-4477" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc">
        <c:Identifier>urn:uuid:247def00-8dd1-47ee-b396-538ae9bcbc44</c:Identifier>
      </c:SecurityContextToken>
      <c:DerivedKeyToken u:Id="_0" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc">
        <o:SecurityTokenReference>
          <o:Reference ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct" URI="#uuid-8fcc72f9-4325-4918-84d2-20233d35381a-4477"/>
        </o:SecurityTokenReference>
        <c:Offset>0</c:Offset>
        <c:Length>24</c:Length>
        <c:Nonce>X/8UYVFOuWcc6UTL/OqAvQ==</c:Nonce>
      </c:DerivedKeyToken>
      <c:DerivedKeyToken u:Id="_1" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc">
        <o:SecurityTokenReference>
          <o:Reference ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct" URI="#uuid-8fcc72f9-4325-4918-84d2-20233d35381a-4477"/>
        </o:SecurityTokenReference>
        <c:Nonce>sdrDI626w2V+kUT5XKE3Mg==</c:Nonce>
      </c:DerivedKeyToken>
      <e:ReferenceList xmlns:e="http://www.w3.org/2001/04/xmlenc#">
        <e:DataReference URI="#_3"/>
        <e:DataReference URI="#_8"/>
      </e:ReferenceList>
      <e:EncryptedData Id="_8" Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:e="http://www.w3.org/2001/04/xmlenc#">
        <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
        <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
          <o:SecurityTokenReference>
            <o:Reference ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/dk" URI="#_1"/>
          </o:SecurityTokenReference>
        </KeyInfo>
        <e:CipherData>
          <e:CipherValue>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</e:CipherValue>
        </e:CipherData>
      </e:EncryptedData>
    </o:Security>
  </s:Header>
  <s:Body u:Id="_2">
    <e:EncryptedData Id="_3" Type="http://www.w3.org/2001/04/xmlenc#Content" xmlns:e="http://www.w3.org/2001/04/xmlenc#">
      <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <o:SecurityTokenReference xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
          <o:Reference ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/dk" URI="#_1"/>
        </o:SecurityTokenReference>
      </KeyInfo>
      <e:CipherData>
        <e:CipherValue>naQiwhfpoT8xWJ72S9E62+dkbV/RKc9idba5I5UyeMvchrE8DWpsPFeiNlSvvR8SpgVgE7S1f7HuqhRgqOiB4QBPbiWUZRycMVo7f2Suj+uJ3/hTxB51MpZ9jEYGf3Vbi2qjrgUN1BEWg/R5yYbWUB1hsXzaL6ccqIqgI4hHWhX55te6lvg0bs7CwfKZorLYY7+1UeMkaDEu83Dsy6O4oYKfKSyRDRpFRRzG0kk/H50bDut4Jl8NlO/L6HRROVOZLShuttymxlkEdAsojZm7g1MKiff1imUcfxJoSUYETYl6hXd8EKADiS22vhc+3F4ZXCux/exy2STxgBei8OYsLH3mV6SS2yKyLUG1yyMSScXjKPYRFtd9Ku1rzl7YYBabm+5l59vIwAgN8pK+NRuVuNwpgU9ARNDWOYb5dllS6OBNc3S7U7ANNEL+FOsWSv71PtyttWFn8anecWaTnnm85qe4VA97rEmArJw3cSZ0YFt7cHfuR1miCjek2sU3DY5zuCrAi5ObBjvy40/1iB3vv6rLkm2KJzksyhFO2OXd8rilMpnE6Yp+aWn5Zjujjz+YH8oQGfEkxOAE+wKOOXGpUzhnAIoAmYxyL0hTaBe6eokOUKONvxiZtpR5T86mjNry</e:CipherValue>
      </e:CipherData>
    </e:EncryptedData>
  </s:Body>
</s:Envelope>

Again below this is the Fiddler trace for the response message.

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <s:Header>
    <a:Action s:mustUnderstand="1" u:Id="_4">http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/ExecuteResponse</a:Action>
    <a:RelatesTo u:Id="_5">urn:uuid:e5c9ff4c-0752-4c24-9dbb-8ac49e6f4c46</a:RelatesTo>
    <ActivityId CorrelationId="cf45b67e-ea16-4a0b-b9fa-cafc8b70ac8e" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">00000000-0000-0000-0000-000000000000</ActivityId>
    <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <u:Timestamp u:Id="uuid-8fcc72f9-4325-4918-84d2-20233d35381a-4480">
        <u:Created>2011-04-09T22:02:14.688Z</u:Created>
        <u:Expires>2011-04-09T22:07:14.688Z</u:Expires>
      </u:Timestamp>
      <c:DerivedKeyToken u:Id="_0" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc">
        <o:SecurityTokenReference>
          <o:Reference URI="urn:uuid:247def00-8dd1-47ee-b396-538ae9bcbc44" ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct"/>
        </o:SecurityTokenReference>
        <c:Offset>0</c:Offset>
        <c:Length>24</c:Length>
        <c:Nonce>deNjAhrA3jpalpOD2mfjSg==</c:Nonce>
      </c:DerivedKeyToken>
      <c:DerivedKeyToken u:Id="_1" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc">
        <o:SecurityTokenReference>
          <o:Reference URI="urn:uuid:247def00-8dd1-47ee-b396-538ae9bcbc44" ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct"/>
        </o:SecurityTokenReference>
        <c:Nonce>dCRq0bmNk5BYAs++nDBFrQ==</c:Nonce>
      </c:DerivedKeyToken>
      <e:ReferenceList xmlns:e="http://www.w3.org/2001/04/xmlenc#">
        <e:DataReference URI="#_3"/>
        <e:DataReference URI="#_6"/>
      </e:ReferenceList>
      <e:EncryptedData Id="_6" Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:e="http://www.w3.org/2001/04/xmlenc#">
        <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
        <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
          <o:SecurityTokenReference>
            <o:Reference ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/dk" URI="#_1"/>
          </o:SecurityTokenReference>
        </KeyInfo>
        <e:CipherData>
          <e:CipherValue>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</e:CipherValue>
        </e:CipherData>
      </e:EncryptedData>
    </o:Security>
  </s:Header>
  <s:Body u:Id="_2">
    <e:EncryptedData Id="_3" Type="http://www.w3.org/2001/04/xmlenc#Content" xmlns:e="http://www.w3.org/2001/04/xmlenc#">
      <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc"/>
      <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
        <o:SecurityTokenReference xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
          <o:Reference ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/dk" URI="#_1"/>
        </o:SecurityTokenReference>
      </KeyInfo>
      <e:CipherData>
        <e:CipherValue>5HSblwEyHFKE78RidjYtxVfsh8oOfFBH6afHqreaRmfeD0Tokt8g1bhZheACIOX6T/lTcI7wuMJL57A0Yi/qZSsZ9NpecnkbRiN3hUs+e+9JxyG3rf7q3by58yb6/4fR3Hl+xVz6yzcjU2gTcBoZoB3seXu3UQZoIsI9YZ9ci0eeOY3wqOoNxvusUpURnOX00IKrubmK6wAKe4sLcDfmDasU/Qf425Ts4PMh3xwlv+n/yivUVKwhZWu1XVbPWrW0xzbHRkjpVt1UT3wU6MnnaPEXYHRhNp2F466SZf7/DhV10AJwjBCt44VPowcQ3DL1UEgu89ypIgMm/3Dqp1VGeIerQS+qkEkHIVPxNaV5nhbwAGnYUUZtUZfSH6FDV/Ubw8BEEZO1+mgwqzUid4X0AfvnWmDzdzayIInXROSdSaq3B4Imn4d+cYXobUBwIoJwD3ySt3W74jHQuKB8FCHvMoTb3yHuWG/bxUuvgWTOLM/VnprmTC9/dDNd+kD1rZkV0oIynuNLc4wipPXyHLCt2tKwQw+QDGxzm82N5nVIrFpI8lftAmmCfwCeyBPA3WmJkMUnZqfPet94Jpuo3WrLXc+f9ojghBpVPs66GDwmstgrJ3BicIQcZNh0hesfb4pCE732b1xIN3OOTm0kfyhBVQYOPOYP6h6P2nWebSCaoon6+HEOkcc5BwJZkk93/LgdoTJVOmsyvQ5TKtGG9tHgnVMrj6VVHEg/6/PqDpLgsvQ/MWH4OcvIvHkHMB09yO6yvxB7XpW2XVOaYvd2M9ZX4EzJbmiiwJKXS529VC9XPe9aLvdpnte5hyKDpQxQyuiGaRCELV0KKZyLA8MhO6EGk2z3xnCw2euFueMHj2+ffJp760nfbV/3VFhWED0kMlPL4ULCeitGR5+dBseF5prTvg18MTnUTrjq7+skiyfyQqAH8Bq0Ra7gqtuoXatCzyzESS8nhRYv8SGyXzSuIWeokf5VsJCmfHz4uxA0ioBZ6OOOXLt8ApMRLYw/vUDwP6thArjDVO7nDG8tvyngSlrIs0ePzBJzA1pO5IC7tZrLP4H0gOzmYLsMCMC29VmoxPe5VKa43O420jXi/syioqnDk7TPuzPUU0mstkUN5jkARn8+spT0atDNjrqdkfEMmMlxVqLVnf8oMpGcqQKBH//mF2RmGXG+2aKSc1npZcgdiiA6ajohONaU1SPXtW+UN07WEWjif/zQWlmC1FtareLJxhOyM7EcI1YJIS3Y+ODNZgH/Co4sLm5eM/64/m5ymwbNhFZZXNlaMNHctAk7inwULBIzC2KH9wPKgFLDjTNh1s+Pd4BiVgvzMP1wwH4EW1EstwhqZefmJpQDXWQPLSkl3CqySMMe1E/EsGLxn/n/8n2iYc2mnxZY6yjbzWCa8vlt8aWZAX5h7KCHvJpM+7gqAmLBqWpuNwdjDVAfynqNaWH6gRjUOHqbfLcIfCkAvtWAivY9kWlU48zqScwTdUb9KiMVGP01X7rw3tpKpYp+H1lR6u3jQSSnU8sr1XEVIs3Z</e:CipherValue>
      </e:CipherData>
    </e:EncryptedData>
  </s:Body>
</s:Envelope>

Now below is the WCF trace at the service level that shows the actual contents of the SOAP request.

<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
  <s:Header>
    <a:Action s:mustUnderstand="1">http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/Execute</a:Action>
    <a:MessageID>urn:uuid:e5c9ff4c-0752-4c24-9dbb-8ac49e6f4c46</a:MessageID>
    <a:ReplyTo>
      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
    <VsDebuggerCausalityData xmlns="http://schemas.microsoft.com/vstudio/diagnostics/servicemodelsink"></VsDebuggerCausalityData>
  </s:Header>
  <s:Body>
    <Execute xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services">
      <request xmlns:d4p1="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:d4p3="http://schemas.microsoft.com/crm/2011/Contracts" i:type="d4p3:WhoAmIRequest">
        <d4p1:Parameters xmlns:d5p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic"></d4p1:Parameters>
        <d4p1:RequestId i:nil="true"></d4p1:RequestId>
        <d4p1:RequestName>WhoAmI</d4p1:RequestName>
      </request>
    </Execute>
  </s:Body>
</s:Envelope>

Finally below is the WCF trace at the service level that shows the actual contents of the SOAP response. You can see the details about the executing user.

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
  <s:Header>
    <a:Action s:mustUnderstand="1" u:Id="_4" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:a="http://www.w3.org/2005/08/addressing">http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/ExecuteResponse</a:Action>
    <a:RelatesTo u:Id="_5" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:a="http://www.w3.org/2005/08/addressing">urn:uuid:e5c9ff4c-0752-4c24-9dbb-8ac49e6f4c46</a:RelatesTo>
    <ActivityId CorrelationId="cf45b67e-ea16-4a0b-b9fa-cafc8b70ac8e" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">00000000-0000-0000-0000-000000000000</ActivityId>
    <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <u:Timestamp u:Id="uuid-8fcc72f9-4325-4918-84d2-20233d35381a-4480" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
        <u:Created>2011-04-09T22:02:14.688Z</u:Created>
        <u:Expires>2011-04-09T22:07:14.688Z</u:Expires>
      </u:Timestamp>
      <c:DerivedKeyToken u:Id="_0" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
        <o:SecurityTokenReference>
          <o:Reference URI="urn:uuid:247def00-8dd1-47ee-b396-538ae9bcbc44" ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct"></o:Reference>
        </o:SecurityTokenReference>
        <c:Offset>0</c:Offset>
        <c:Length>24</c:Length>
        <c:Nonce>
          <!-- Removed-->
        </c:Nonce>
      </c:DerivedKeyToken>
      <c:DerivedKeyToken u:Id="_1" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
        <o:SecurityTokenReference>
          <o:Reference URI="urn:uuid:247def00-8dd1-47ee-b396-538ae9bcbc44" ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct"></o:Reference>
        </o:SecurityTokenReference>
        <c:Nonce>
          <!-- Removed-->
        </c:Nonce>
      </c:DerivedKeyToken>
      <e:ReferenceList xmlns:e="http://www.w3.org/2001/04/xmlenc#">
        <e:DataReference URI="#_3"></e:DataReference>
        <e:DataReference URI="#_6"></e:DataReference>
      </e:ReferenceList>
      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
          <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod>
          <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1"></SignatureMethod>
          <Reference URI="#_2">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
            <DigestValue>CM5e0byUp3ccAE2dGzBmaEoULOQ=</DigestValue>
          </Reference>
          <Reference URI="#_4">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
            <DigestValue>T5XEnhEHcT3kntcAeWTHEDElkHg=</DigestValue>
          </Reference>
          <Reference URI="#_5">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
            <DigestValue>qUejK6uFN8IMPRBGOgD0T+IRpYk=</DigestValue>
          </Reference>
          <Reference URI="#uuid-8fcc72f9-4325-4918-84d2-20233d35381a-4480">
            <Transforms>
              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform>
            </Transforms>
            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
            <DigestValue>TY+iuqtq/ZKovc0vC9ZKFPMEttQ=</DigestValue>
          </Reference>
        </SignedInfo>
        <SignatureValue>Z6DV7dz+0wTs9aeynb/6KC04Pcs=</SignatureValue>
        <KeyInfo>
          <o:SecurityTokenReference xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <o:Reference ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/dk" URI="#_0"></o:Reference>
          </o:SecurityTokenReference>
        </KeyInfo>
      </Signature>
    </o:Security>
  </s:Header>
  <s:Body u:Id="_2" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
    <ExecuteResponse xmlns="http://schemas.microsoft.com/xrm/2011/Contracts/Services">
      <ExecuteResult i:type="b:WhoAmIResponse" xmlns:a="http://schemas.microsoft.com/xrm/2011/Contracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:b="http://schemas.microsoft.com/crm/2011/Contracts">
        <a:ResponseName>WhoAmI</a:ResponseName>
        <a:Results xmlns:c="http://schemas.datacontract.org/2004/07/System.Collections.Generic">
          <a:KeyValuePairOfstringanyType>
            <c:key>UserId</c:key>
            <c:value i:type="d:guid" xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/">8179fcb3-fb55-e011-ab42-005056b863d7</c:value>
          </a:KeyValuePairOfstringanyType>
          <a:KeyValuePairOfstringanyType>
            <c:key>BusinessUnitId</c:key>
            <c:value i:type="d:guid" xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/">a6fa9e52-564a-e011-ab42-005056b863d7</c:value>
          </a:KeyValuePairOfstringanyType>
          <a:KeyValuePairOfstringanyType>
            <c:key>OrganizationId</c:key>
            <c:value i:type="d:guid" xmlns:d="http://schemas.microsoft.com/2003/10/Serialization/">dec6a83f-564a-e011-ab42-005056b863d7</c:value>
          </a:KeyValuePairOfstringanyType>
        </a:Results>
      </ExecuteResult>
    </ExecuteResponse>
  </s:Body>
</s:Envelope>

Hope you find this useful.

CRM Developer Toolkit for Visual Studio 2012: Package Project not loading

If you have installed the new Dynamics CRM 2011 Developer Toolkit for Visual Studio 2012, you might notice that package projects created using the old developer toolkit fail to load. This is manifested in an error similar to the below.

TargetFilesNotFound

To fix the problem follow the steps below:

  1. Right click on the package project and click Unload
  2. Right click on package project and click on Edit
  3. Replace “<Import Project=”$(MSBuildExtensionsPath32)Microsoft\CRM\Microsoft.CrmDeveloperTools.CrmClient.targets” />” with “<Import Project=”$(MSBuildExtensionsPath32)Microsoft\CRM\Microsoft.CrmDeveloperTools.12.targets” />”
  4. Right click on the package project and click on Reload

This will fix the problem. The problem is because the target files location is different between the developer tools for visual studio 2010 and visual studio 2012.

Hope this helps

I’m presenting at extremeCRM 2013 Rome

eXtremeCRM 2013 Rome is the Can’t-Miss Conference

for Microsoft Dynamics® CRM Partners

There is no place like eXtremeCRM 2013 RomeeXtremeCRM is the hub where Microsoft DynamicsCRM partners come together to forge business relationships, gain knowledge from real-world experiences and dive deep into current and future technologies.  For Microsoft Dynamics CRM partner organizations, it is the annual conference to attend to nurture best practices, facilitate business growth, and educate each organization member.  The highly anticipated conference will be held in Rome, Italy, 3 – 6 February, 2013.

eXtremeCRM offers role-specific tracks for every member of the partner business.  Over 50 sessions are available to those in positions of sales, implementation and development. eXtremeCRM continues its deep focus on technical depth and app development this year and continues its commitment to helping partners grow. To this end, business leaders are invited to attend the eXecutive Summit being held at eXtremeCRM, a workshop-style event that will address key CRM business leadership issues.

Here is the session I will be presenting…

Dynamics under Control: Testing Microsoft Dynamics CRM from a 360 View

This session will show you how to easily test your Microsoft Dynamics CRM deployment at the different stages of the development lifecycle. It will cover all angles from designing your code for testability, unit, integration, performance, end-to-end and manual testing. It will introduce you to all the required tools, frameworks and processes you need to create and automate your tests through real life scenarios and practical demos. Demos will showcase the latest technologies such as Visual Studio 2012, TFS 2012, Microsoft Fakes & Test Manager 2012. This session will help you to increase productivity and quality while reducing risk and cost, thus resulting in happy developers and customers through successful deployments.

With its specialized content and enhanced technical focus (which includes the eXtreme App Challenge), all presented by industry leaders, experts, and innovators, eXtremeCRM 2013 Rome is the investment every partner organization should make.

And, like never before, Microsoft Dynamics will make a BIG splash at eXtremeCRM 2013 Rome. As a corporate sponsor, they have communicated that eXtremeCRM will be their #1 platform to share the latest Microsoft Dynamics CRM strategies and investments with partners.

There are a number of other session offerings I am looking forward to attending. For more information about eXtremeCRM 2013 Rome’s agenda and to register, visit eXtremeCRM 2013 Rome.

Get eXtreme in Rome!

CRM 4 Silverlight Integration

In this post I will talk about integrating the Microsoft Dynamics CRM UI with Silverlight and I will show how to inject a Silverlight control onto a CRM entity form.

Normally one would extend CRM by using javascript or custom dialogs but Silverlight is a new technology that allows the building of a nice UI that can interagate well with the underlying html page and backend systems.

The solution consists of a custom web application that hosts the silverlight required files and some customisations for the “OnLoad” event. On this occasion I will show you how to show a modal Silverlight popup on the opening of a new CRM form, however the concepts in this post can be easily extended to cater for other requirements. Below is a screen shot of the final result. You can then click anywhere on the popup to dismiss it.

CRM_Silverlight_Popup

We start with creating some methods that will inject a silverlight control onto a CRM form. To be able to create a modal popup I will create an overlay div that will cover the whole window preventing the user from interacting with anything on the form until the popup is dismissed. To display the Silverlight control I will place another silvelright container div on top of the overlay div that will contain the Silverlight control. The Silverlight container div will be the exact size of the Silverlight popup control and will be centered in the middle of the window. Both divs will be appened to the end of the document and use absolute layout to prevent any intervention with the CRM elements on the form.

The next step is to inject the Silverlight control into the Silverlight container div using the standard method that comes as part of the Silverlight.js file. Finally the overlay div and container div are shown on the form. Below is the code that illustrates this.

   13 if (!window.SilverlightInjector)

   14 {

   15     window.SilverlightInjector = {};

   16 }

   17

   18 SilverlightInjector.CreateModalSilverlightControl = function(controlSource, id, params, width, height, onLoadHandler) {

   19

   20     var screenOverlay = document.getElementById(‘screenOverlay’);

   21     var silverlightContainer = document.getElementById(id + ‘_silverlightContainer’);

   22

   23     if (“undefined” == typeof (screenOverlay)

   24         || “unknown” == typeof (screenOverlay)

   25         || null == screenOverlay) {

   26         screenOverlay = document.createElement(‘div’);

   27         screenOverlay.style.width = ‘0px’;

   28         screenOverlay.style.height = ‘0px’;

   29         screenOverlay.style.top = ‘0’;

   30         screenOverlay.style.left = ‘0’;

   31         screenOverlay.style.position = ‘absolute’;

   32         screenOverlay.style.zIndex = ‘100’;

   33         screenOverlay.id = ‘screenOverlay’;

   34         screenOverlay.style.display = ‘none’;

   35         screenOverlay.style.background = ‘#000000’;

   36         screenOverlay.style.filter = ‘alpha(opacity=25)’;

   37

   38         document.body.appendChild(screenOverlay);

   39     }

   40

   41     if (“undefined” == typeof (silverlightContainer)

   42         || “unknown” == typeof (silverlightContainer)

   43         || null == silverlightContainer) {

   44         silverlightContainer = document.createElement(‘div’);

   45         silverlightContainer.id = id + ‘_silverlightContainer’;

   46         silverlightContainer.style.position = ‘absolute’;

   47         silverlightContainer.style.zIndex = ‘101’;

   48         silverlightContainer.style.width = width;

   49         silverlightContainer.style.height = height;

   50         silverlightContainer.style.display = ‘none’;

   51

   52         document.body.appendChild(silverlightContainer);

   53     }

   54

   55     //set overlay size to window full size

   56     screenOverlay.style.width = document.body.clientWidth;

   57     screenOverlay.style.height = document.body.clientHeight;

   58

   59     //place container in the center of the window

   60     silverlightContainer.style.top = (document.body.clientHeight – height) / 2;

   61     silverlightContainer.style.left = (document.body.clientWidth – width) / 2;

   62

   63     Silverlight.createObject(

   64         controlSource,                  // Source property value.

   65         silverlightContainer,                  // DOM reference to hosting DIV tag.

   66         silverlightContainer.id + “_silverlightPlugin”,         // Unique plug-in ID value.

   67         {                               // Per-instance properties.

   68         width: ‘100%’,                // Width of rectangular region of

   69         // plug-in area in pixels.

   70         height: ‘100%’,               // Height of rectangular region of

   71         // plug-in area in pixels.

   72         inplaceInstallPrompt: false, // Determines whether to display

   73         // in-place install prompt if

   74         // invalid version detected.

   75         background: ‘transparent’,       // Background color of plug-in.

   76         isWindowless: ‘true’,       // Determines whether to display plug-in

   77         // in Windowless mode.

   78         framerate: ’24’,             // MaxFrameRate property value.

   79         version: ‘2.0’               // Silverlight version to use.

   80     },

   81         {

   82             onError: SilverlightInjector.OnErrorSilverlightEventHandler,               // OnError property value —

   83             // event handler function name.

   84             onLoad: onLoadHandler                // OnLoad property value —

   85             // event handler function name.

   86         },

   87         params                      // initParams

   88         );

   89

   90     //show the Silverlight container lock the screen

   91     silverlightContainer.style.display = ‘block’;

   92     screenOverlay.style.display = ‘block’;

   93 }

The next step is to create some code that will be injected into the CRM entity “OnLoad” event. I prefer placing any code that is used on the “OnLoad” event in a separate file on the server as it can be easily maintained, especially during development. However be aware that in this case these extra customisations are not stored in the database and will have to be deployed separately.

The first thing to do is to inject the standard Silverlight.js into the head of the page as a script element. I found that loading the file normally will not auto activate the silverlight control and the user will have to click on it to activate it. The next thing is to load SilverlightInjector.js file created in the first step into the form in a smilar fashion and call the method to create the Silverlight popup. The code below illustrates this step.

   13 if (!window.EntityOnLoad)

   14 {

   15     window.EntityOnLoad = {};

   16 }

   17

   18 EntityOnLoad.Load = function() {

   19     //Load Silverlight.js into the head to prevent having to activate the control

   20

   21     var oXML = new XMLHttpRequest();

   22     oXML.open(‘GET’, ‘/ISV/CRMSilverlightWeb/Silverlight.js’, false);

   23     oXML.send();

   24

   25     var e = document.createElement(“script”);

   26     e.type = “text/javascript”;

   27     e.text = oXML.responseText;

   28     document.getElementsByTagName(“head”)[0].appendChild(e);

   29

   30

   31     //Load SilverlightInjector.js

   32

   33     oXML = new XMLHttpRequest();

   34     oXML.open(‘GET’, ‘/ISV/CRMSilverlightWeb/SilverlightInjector.js’, false);

   35     oXML.send();

   36     eval(oXML.responseText);

   37

   38     EntityOnLoad.ShowPopupMessage(‘This is a ‘ + crmForm.ObjectTypeName + ‘ form displayed using Microsoft Silverlight.’, 300, 300);

   39 }

   40

   41 EntityOnLoad.ShowPopupMessage = function(message, width, height) {

   42     var params = ‘message=’ + message;

   43     params += ‘,width=’ + width;

   44     params += ‘,height=’ + height;

   45     SilverlightInjector.CreateModalSilverlightControl(‘/ISV/CRMSilverlightWeb/ClientBin/CRMSilverlightLibrary.xap’, ‘CRMPopupID’, params, width, height, null);

   46 }

We now need to use this code from the CRM form on the “OnLoad” event. To do this we the load the code using the standard XmlHttpRequest and invoke the load function we created previously. The code below needs to be placed into the customisations on the “OnLoad” event for the entity you want to use the popup on.

    1 try {

    2     oXML = new XMLHttpRequest();

    3     oXML.open(‘GET’, ‘/ISV/CRMSilverlightWeb/EntityOnLoad.js’, false);

    4     oXML.send();

    5     eval(oXML.responseText);

    6

    7     EntityOnLoad.Load();

    8 }

    9 catch (ex) {

   10     alert(‘Failed to load :’ + ex.description);

   11     window.close();

   12 }

The last call we made will download and launch the Silverlight application. On Application start event we create a new CRMPopup control and pass the initialisation parameters to the constructor. The CRMPopup is a Silverlight user control that implements the Popup behaviour. The control is initialised by passing a message and dimensions through the initialisation paramters. In the constructor we register for two events: The Loaded event that will start the animation to show the control and the MouseLeftButtonUp event that will be used to start an animation to hide the control.  We will not go too much into the details of the Silverlight animations as it is outside the scope of this post.

I have included some sample code that you can download using the link below. The download contains a solution with a web application project and a Silverlight control library. You will need to create a virutal directory called “CRMSilverlightWeb” under the ISV directory in CRM and copy the content of the web application into there. Make sure to add the “.xap” extension to the MIME types on the “ClientBin” directory otherwise IIS will not allow access to the Silverlight package.  You can set the extension to “.xap” and MIME type to “application/x-silverlight-2”.  You will also need to add the contents of “EntityOnLoadCustomisation.js” file to “OnLoad” event of the selected entity you want to test the popup on.

You might notice a small delay the first time you load the page and this is due to the form having to download the Silverlight package. On subsequent requests and (depending on your setup) the Siverlight package can be cached to increase performance.

In this post we have seen how to show a model popup on a crm form using Silverlight. I would just like to mention that this concept can be used to implement other types of functionality (including things like address checking where you could have a control that reads your search criteria and provides a list of matches and then save back the details onto the CRM form).  Essentially it could be used for any process that requires some user interaction as an alternative to javascript and dialogs. By using Silvelright you get the extra benefit of having a nice user interface that is easy to implement and has the advatange of using a proper programming language such as C#.

You can download the sample code from here.

CRM 4 WCF Integration

In this post i will talk about integrating the Microsoft CRM UI with backend WCF services. In the CRM SDK there is a lot of examples about creating sample SOAP requests to access the CRM SDK web services. However this involves a lot of manual work which includes generating the SOAP request message and then parsing the SOAP response message. If you are trying to retrieve and manipulate a lot of data in many forms this can be quite time consuming and difficult to maintain. One alternative is write your own custom JavaScript helpers that can simplify the process for you. However this also requires investing the time to implement the helper code. What if you want to call third party web services? This can be difficult to access using JavaScript depending on the complexity of the service definition and can have various security implicaitons.

Luckily WCF in .NET 3.5 provides the capability to expose WCF services that can be easily consumed using AJAX enabled web pages. The WCF Web Extensions architecture is based around custom bindings and behaviors that make it easy and efficient to consume backend services using Javascript. However most of this functionality is implemented using ASP.NET using the ScriptManager class. The ScriptManager on the ASP.NET page is responsible for rendering all the scripts required for the AJAX libraries to function including any proxy to WCF services. This makes the ScriptManager useless for CRM as the only supported way of customising a CRM form is by injecting Javascript on the CRM exposed events. The good news however is that with a few tweaks we can make all that functionality available on the CRM form.

This approach of being able to invoke WCF services from within the CRM UI we give us many useful features that can be used to extend CRM.

  • Implement custom WCF services that are designed to be used by the CRM UI. Thus making the least number of calls as possible and only retrieving the required data.
  • Access the return/input parameters of the CRM operations as proper JavaScript objects with no extra effort.
  • The ability to implement very complex logic in the helper service that could include talking to CRM SDK services, Third party services or databases.
  • Easy to maintain as operations can be altered/added/removed with minimal effort. There is no need to update any proxy scripts as they get generated at runtime.

The implementation consists of a custom web application deployed under the ISV directory on the CRM website. The web application will host the custom helper WCF service and provide all the scripts and customisations required to invoke the WCF service from a CRM form. The first step is to implement the WCF service. This will be implemented as a standard .NET library. I will not go into the details of the implementation of the WCF service as it is outside the scope of this post. Below is the code for the sample WCF service.

    7 namespace CRMWCFService

    8 {

    9     public class CRMService : ICRMService

   10     {

   11         public CRMEntity GetCRMData(string message)

   12         {

   13             return new CRMEntity()

   14             {

   15                 Name = “Demo “ + message,

   16                 Active = true,

   17                 Date = DateTime.Now,

   18                 User = OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name

   19             };

   20         }

   21     }

   22 }

The next step is to host the service in our custom web application. To do that add the reference to the previously created library and then create a new “Services” directory in the web application. Then add two files. The first file is “JSService.svc” which is the base endpoint address for the service. Below are the contents of the file.

    1 <%@ ServiceHost

    2     language=”C#”

    3     Debug=”true”

    4     Service=”CRMWCFService.CRMService”

    5 %>

To finish the service setup also add a web.config file to the same directory that includes the configuration for the WCF Service. The service will use windows authentication. However when you host the web application in IIS make sure you enable anonymous access on the “Services” directory to allow access to the metadata endpoint. You can also enable anonymous access on the script files to speed up loading time performance. Note the endpoint behavior that enables the endpoint to be accessible using AJAX.

   10 <configuration>

   11   <system.serviceModel>

   12     <bindings>

   13       <webHttpBinding>

   14         <bindingname=Secure>

   15           <securitymode=TransportCredentialOnly>

   16             <transportclientCredentialType=Windows />

   17           </security>

   18         </binding>

   19       </webHttpBinding>

   20     </bindings>

   21     <services>

   22       <servicebehaviorConfiguration=CRMServiceBehaviorname=CRMWCFService.CRMService>

   23         <endpointaddress=“”binding=webHttpBindingbindingConfiguration=SecurebehaviorConfiguration=AjaxBehavior

   24           name=Servicecontract=CRMWCFService.ICRMService />

   25         <endpointaddress=mexbinding=mexHttpBindingname=Meta

   26           contract=IMetadataExchange />

   27       </service>

   28     </services>

   29     <behaviors>

   30       <endpointBehaviors>

   31         <behaviorname=AjaxBehavior>

   32           <enableWebScript/>

   33         </behavior>

   34       </endpointBehaviors>

   35       <serviceBehaviors>

   36         <behaviorname=CRMServiceBehavior>

   37           <serviceMetadatahttpGetEnabled=true />

   38           <serviceDebugincludeExceptionDetailInFaults=true />

   39         </behavior>

   40       </serviceBehaviors>

   41     </behaviors>

   42   </system.serviceModel>

   43 </configuration>

The next step is to create a script called “EntityOnLoad.js” that will loaded into the CRM form. The script will first load the Microsoft AJAX library that would otherwise have been available on the client using the ASP.NET ScriptManager. To create this file you can create a test ASP.NET page as demonstrated in the sample download at the end of this post. In the test page add reference to the WCF service in the ScriptManager. Fire up the page and view the source. In there you will see references to various script files and one of them is the Microsoft AJAX library that you can save and reuse. This file should only be updated if you install a new version of .NET framework or apply a service pack. The next step is to load the JavaScript proxy for the service. WCF provide these files as part of the metadata for a web enabled WCF service. So all we need to do is link to the WCF JS metadata URL. The last step is to invoke the WCF Service asynchronously by passing a return delegate. The code below demonstrates these step.

   13 if (!window.EntityOnLoad)

   14 {

   15     window.EntityOnLoad = {};

   16 }

   17

   18 EntityOnLoad.Load = function() {

   19

   20     //Load Microsoft Ajax Library

   21

   22     var oXML = new XMLHttpRequest();

   23     oXML.open(‘GET’, ‘/ISV/CRMWCFWeb/MicrosoftAjax.js’, false);

   24     oXML.send();

   25     eval(oXML.responseText);

   26

   27     //Load Service Proxy

   28

   29     oXML = new XMLHttpRequest();

   30     oXML.open(‘GET’, ‘/ISV/CRMWCFWeb/Services/JSService.svc/js’, false);

   31     oXML.send();

   32     eval(oXML.responseText);

   33

   34     CRMWCFService.CRMService.GetCRMData(“CRM “ + crmForm.ObjectTypeName, onComplete, onError);

   35 }

   36

   37 function onComplete(result) {

   38     var message = “Name: “ + result.Name + “n”;

   39     message += “Active: “ + result.Active + “n”;

   40     message += “Date: “ + result.Date + “n”;

   41     message += “User: “ + result.User + “n”;

   42     alert(message);

   43 }

   44

   45 function onError(error) {

   46     alert(error.get_message());

   47 }

Finally the last and easiest step is to load the script and execute it from the CRM UI. For demonstration purposes i will just call the service on the load event. However you can call this code from anywhere you like. The code below needs to be added to “OnLoad” event for the CRM form. If everything is step up properly you should see a popup when you open the CRM form.

    1 try {

    2     oXML = new XMLHttpRequest();

    3     oXML.open(‘GET’, ‘/ISV/CRMWCFWeb/EntityOnLoad.js’, false);

    4     oXML.send();

    5     eval(oXML.responseText);

    6

    7     EntityOnLoad.Load();

    8 }

    9 catch (ex) {

   10     alert(‘Failed to load :’ + ex.description);

   11     window.close();

   12 }

As you can see once everything is setup, making calls to the WCF service is just a matter of calling a method and processing the response. I have created a sample that includes all the required files and test pages. The sample demonstrates the concepts in this post and provides you with a working example. However note that if you decide to run the sample locally in visual studio you will have to configure the web application to run under IIS instead of the visual studio built-in web server. Otherwise you will get an error indicating that Windows Authentication is not supported. Hope you find this post useful.

You can download the sample code from here.