eimagine provides leading custom development for Microsoft Dynamics CRM 4.0 and 2011. If you’re doing advanced CRM development you may need to use Microsoft’s code generation tool (CrmSvcUtil.exe) to generate a strongly-typed code file. This executable, available in the Advanced Developer Extensions for Microsoft Dynamics CRM in the CRM SDK is able to generate:

  1. Statically typed entities, including N:N classes
  2. Enumerated types
  3. WCF Data Services for managing entities

Despite the documentation on MSDN, I had some trouble generating the file partially due to complications derrived from an IFD-enabled CRM deployment for CRM 2011. When following Microsoft’s instructions, I received the following error, despite solid credentials:

Exiting program with exception: The user authentication failed!
Enable tracing and view the trace files for more information.
CrmSvcUtil.exe Error: 0 : Exiting program with exit code 2 due to exception : System.InvalidOperationException: The user authentication failed!

In order to resolve this, I had to build a custom metadata provider component. This utilizes claims-based authentication to override the standard provider, allowing authentication and generation of the code file. Here are instructions on how to do it…

  1. Create a new Visual Studio project called MetadataProvider, type of class library.
  2. Add a new class and paste in the code reference below [IfdMetadataProviderService.cs].
  3. Add any necessary references, and build the project. Save the output file MetadataProvider.dll.
  4. Copy the DLL to the MS CRM SDK directory, in /sdk/bin/.
  5. Create a BAT file in the same directory from the reference below [GenerateCode.bat]. Modify the URL endpoint appropriately for your organization.
  6. Important: Create the directory /sdk/bin/output and create a blank file in that directory named organizationXrm.cs. I got errors generating the file without creating an empty placeholder.
  7. Run the BAT file (as Administrator) and enter the login details to generate the code file.
  8. Voila! You can now add the organizationXrm.cs code file to your projects and reap the benefits of a strongly typed code file!  If you ever need to regenerate it due to changes in CRM configuration, simply run the BAT file again and you’ll get a fresh file.

[IfdMetadataProviderService.cs]

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using System.ServiceModel.Description;
using Microsoft.Crm.Services.Utility;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Metadata;

namespace MetadataProvider
{
public sealed class IfdMetadataProviderService : IMetadataProviderService
{
private class OrganizationMetadata : IOrganizationMetadata
{
public EntityMetadata[] Entities { get; set; }
public OptionSetMetadataBase[] OptionSets { get; set; }
public SdkMessages Messages { get; set; }
}

private readonly Dictionary<string, string> _parameters;
private OrganizationMetadata _metadata;

public IfdMetadataProviderService(IDictionary<string, string> parameters)
{
_parameters = new Dictionary<string, string>(parameters, StringComparer.InvariantCultureIgnoreCase);
}

IOrganizationMetadata IMetadataProviderService.LoadMetadata()
{
if (_metadata == null)
{
var credentials = new ClientCredentials();
credentials.UserName.UserName = _parameters[“username”];
credentials.UserName.Password = _parameters[“password”];

using (var service = new OrganizationServiceProxy(new Uri(_parameters[“url”]), null, credentials, null))
{
service.Timeout = new TimeSpan(0, 5, 0);

_metadata = new OrganizationMetadata
{
Entities = RetrieveEntities(service),
OptionSets = RetrieveOptionSets(service),
Messages = RetrieveMessages(service),
};
}
}

return _metadata;
}

private static EntityMetadata[] RetrieveEntities(IOrganizationService service)
{
var request = new OrganizationRequest(“RetrieveAllEntities”);
request.Parameters[“EntityFilters”] = EntityFilters.Entity | EntityFilters.Attributes | EntityFilters.Relationships;
request.Parameters[“RetrieveAsIfPublished”] = false;
var response = service.Execute(request);
return response.Results[“EntityMetadata”] as EntityMetadata[];
}

private static OptionSetMetadataBase[] RetrieveOptionSets(IOrganizationService service)
{
var request = new OrganizationRequest(“RetrieveAllOptionSets”);
request.Parameters[“RetrieveAsIfPublished”] = false;
var response = service.Execute(request);
return response.Results[“OptionSetMetadata”] as OptionSetMetadataBase[];
}

private static SdkMessages RetrieveMessages(IOrganizationService service)
{
var type = Assembly.LoadFrom(“crmsvcutil.exe”).GetType(“Microsoft.Crm.Services.Utility.SdkMetadataProviderService”);
var getMessages = type.GetMethod(“RetrieveSdkRequests”, BindingFlags.Instance | BindingFlags.NonPublic);
var provider = FormatterServices.GetUninitializedObject(type);
return getMessages.Invoke(provider, new object[] { service }) as SdkMessages;
}
}
}

[GenerateCode.bat]

@echo off

set url=https://<YOUR_SERVER_NAME_HERE>/XRMServices/2011/Organization.svc

echo Domain:
set /p domain=
echo Username:
set /p username=
echo Password:
set /p password=

echo.
echo Endpoint URL: %url%
echo.

CrmSvcUtil.exe /metadataproviderservice:”MetadataProvider.IfdMetadataProviderService, MetadataProvider” /codecustomization:”Microsoft.Xrm.Client.CodeGeneration.CodeCustomization, Microsoft.Xrm.Client.CodeGeneration” /url:”%url%” /out:”outputOrganizationXrm.cs” /namespace:OrganizationXrm /serviceContextName:XrmServiceContext /serviceContextPrefix:Xrm /u:”%domain%%username%” /p:%password%

echo.
pause

Like this post? Share it!