Experience your
30 day trial
now!
GET STARTED
This topic is about new authentication mechanism for accessing CRM Web Services that was in Dynamics CRM Live – Passport Authentication.
This new method requires you to jump a few more hoops before you can make your first web service call (after all we have now stepped out of our friendly AD neighborhood and are out in the Internet wilderness), but once you have the appropriate helper methods defined it’ll be just as easy as setting good old CredentialCache.DefaultCredentials.
There are 4 steps required in order to retrieve a proper CRM Ticket:
Easy enough?... Not yet? Alright then, read on.
But first things first – I assume you have already downloaded CRM 4.0 SDK and unpacked it in, lets say, “C:\CrmSdk” folder.
Building CrmDiscoveryService DLL
In order to call CrmDiscoveryService methods we need an assembly that defines this web service methods. And there are two ways to build it:
Since definition of CrmDiscoveryService is not changing I would recommend going with second method. Build a DLL once and reuse this same DLL in all projects calling CrmDiscoveryService by adding it as an assembly reference, simply because it is much easier to add an assembly reference than a web reference.
1. Open you Visual Studio command prompt (or your regular command prompt that knows a path to wsdl.exe) and go to:
> C:> cd CrmSdk\sdk\wsdl
2. Build a C# proxy for crmdiscoveryservice.wsdl file with following command:
> wsdl /namespace:CrmSdk.CrmDiscoveryService /out:CrmDiscoveryService.cs crmdiscoveryservice.wsdl
3. Compile CrmDiscoveryService.cs file into a DLL:
> csc /target:library CrmDiscoveryService.cs
4. Create a BIN folder under C:\CrmSdk and move your CrmDiscoveryService.dll there:
> mkdir C:\CrmSdk\bin > move CrmDiscoveryService.dll C:\CrmSdk\bin
> mkdir C:\CrmSdk\bin
> move CrmDiscoveryService.dll C:\CrmSdk\bin
Note that we specified CrmSdk.CrmDiscoveryService namespace for this DLL, this is important so there will be no conflicts with main CrmService proxy.
Building a Passport Service Helper
Now, the second component that we will need is a wrapper around IDCRL library that is required to talk to Passport Service.
Why do we need a wrapper? Well… take a look at the code that it consists of and tell me – do you want to write this stuff every time you need to get a Passport ticket?... I didn’t think so.
The wrapper project is located in “C:\CrmSdk\sdk\server\helpers\cs\idcrlwrapper” folder. In the SDK it is constructed as a sample code. But what we need is a library. So personally I would apply the following 2 modifications to the Program.cs before building it:
Now:
Getting CrmTicket
Okay, now that we have paid our dues of tedium to the programming Gods and have CrmDiscoveryService.dll and IdCrlWrapper.dll in our possession it is time to do some actual coding.
Here is a helper function that I would suggest you add somewhere in your code that will retrieve a CrmTicket and OrganizationDetail information for you.
public string GetCrmTicket(string liveusername, string livepassword, string orgname, out OrganizationDetail orgdetail) { // Create and configure the CrmDiscoveryService Web service. CrmDiscoveryService discoveryService = new CrmDiscoveryService(); discoveryService.Url = "https://dev.crm.dynamics.com/MSCRMServices/2007/Passport/CrmDiscoveryService.asmx"; // Retrieve a policy from the Web service. RetrievePolicyRequest policyRequest = new RetrievePolicyRequest(); RetrievePolicyResponse policyResponse = (RetrievePolicyResponse)discoveryService.Execute(policyRequest); string partner = "crm.dynamics.com"; // Retrieve a ticket from the Windows Live (Passport) service. LogonManager lm = new LogonManager(); string passportTicket = lm.Logon(liveusername, livepassword, partner, policyResponse.Policy, "Production"); // Dispose of the LogonManager object to avoid a FileNotOpen exception. lm.Dispose(); // Retrieve a CrmTicket from the Web service. RetrieveCrmTicketRequest crmTicketRequest = new RetrieveCrmTicketRequest(); crmTicketRequest.OrganizationName = orgname; crmTicketRequest.PassportTicket = passportTicket; RetrieveCrmTicketResponse crmTicketResponse = (RetrieveCrmTicketResponse)discoveryService.Execute(crmTicketRequest); orgdetail = crmTicketResponse.OrganizationDetail; return crmTicketResponse.CrmTicket; }
public string GetCrmTicket(string liveusername, string livepassword, string orgname, out OrganizationDetail orgdetail)
{
// Create and configure the CrmDiscoveryService Web service.
CrmDiscoveryService discoveryService = new CrmDiscoveryService();
discoveryService.Url =
"https://dev.crm.dynamics.com/MSCRMServices/2007/Passport/CrmDiscoveryService.asmx";
// Retrieve a policy from the Web service.
RetrievePolicyRequest policyRequest = new RetrievePolicyRequest();
RetrievePolicyResponse policyResponse =
(RetrievePolicyResponse)discoveryService.Execute(policyRequest);
string partner = "crm.dynamics.com";
// Retrieve a ticket from the Windows Live (Passport) service.
LogonManager lm = new LogonManager();
string passportTicket = lm.Logon(liveusername, livepassword, partner,
policyResponse.Policy, "Production");
// Dispose of the LogonManager object to avoid a FileNotOpen exception.
lm.Dispose();
// Retrieve a CrmTicket from the Web service.
RetrieveCrmTicketRequest crmTicketRequest = new RetrieveCrmTicketRequest();
crmTicketRequest.OrganizationName = orgname;
crmTicketRequest.PassportTicket = passportTicket;
RetrieveCrmTicketResponse crmTicketResponse =
(RetrieveCrmTicketResponse)discoveryService.Execute(crmTicketRequest);
orgdetail = crmTicketResponse.OrganizationDetail;
return crmTicketResponse.CrmTicket;
}
Calling CRM Live Web Service
If you have read to this point you probably thinking “Where exactly is the “easy” part that was promised in the beginning?” Not to worry. The hard part is over (forever)! From now on the call to CRM Live Web Service will look like this:
public Guid WhoAmI() { // Set up the CRM Service OrganizationDetail orgDetail; CrmAuthenticationToken token = new CrmAuthenticationToken(); token.AuthenticationType = 1; token.OrganizationName = "AdventureWorksCycle"; token.CrmTicket = GetCrmTicket("crmuser@live.com", "crmuser_password", "AdventureWorksCycle", out orgDetail); CrmService Service = new CrmService(); Service.Url = orgDetail.CrmServiceUrl; Service.CrmAuthenticationTokenValue = token; // Call WhoAmI() WhoAmIRequest req = new WhoAmIRequest(); WhoAmIResponse resp = (WhoAmIResponse) Service.Execute(req); return resp.UserId; }
public Guid WhoAmI()
// Set up the CRM Service
OrganizationDetail orgDetail;
CrmAuthenticationToken token = new CrmAuthenticationToken();
token.AuthenticationType = 1;
token.OrganizationName = "AdventureWorksCycle";
token.CrmTicket = GetCrmTicket("crmuser@live.com", "crmuser_password", "AdventureWorksCycle", out orgDetail);
CrmService Service = new CrmService();
Service.Url = orgDetail.CrmServiceUrl;
Service.CrmAuthenticationTokenValue = token;
// Call WhoAmI()
WhoAmIRequest req = new WhoAmIRequest();
WhoAmIResponse resp = (WhoAmIResponse) Service.Execute(req);
return resp.UserId;
Where of course “Set up the CRM Service” part should be done only one time somewhere in your application (could be defined as a property for example):
private CrmService _service; public CrmService Service { get { if (_service == null) { // Set up the CRM Service. OrganizationDetail orgDetail; CrmAuthenticationToken token = new CrmAuthenticationToken(); token.AuthenticationType = 1; token.OrganizationName = "AdventureWorksCycle"; token.CrmTicket = GetCrmTicket("crmuser@live.com", "crmuser_password", "AdventureWorksCycle", out orgDetail); _service = new CrmService(); _service.Url = orgDetail.CrmServiceUrl; _service.CrmAuthenticationTokenValue = token; } return _service; } }
private CrmService _service;
public CrmService Service
get
if (_service == null)
// Set up the CRM Service.
_service = new CrmService();
_service.Url = orgDetail.CrmServiceUrl;
_service.CrmAuthenticationTokenValue = token;
return _service;
Obviously user credentials and organization name will not be hard coded in your application, but you get the idea.
So, to review, what we have done was:
And for the next project all we will have to do will be – reference those DLLs in project and use CrmService helper. That’s pretty easy I would say.
Alexander Panov
PingBack from http://www.travel-hilarity.com/airline_travel/?p=1948
Hi Alexander
I got the sample CRM live access working - so far so good.
As I am not using C# and .net for my development environment, I need to build another wrapper around the idcrl library. Is there any description or header file for this library ?
Or is there a another way to use the Windows Live logon ?
Have anyone tried to use the Windows Live Client API in connection with CRM ?
Thanks for any help.
Michael
Code works well. I can query, add & change a handful of entities with no problem. If I run the code on my entire database, I receive a popup error message from Visual Studio after a couple hours of processing:
Assertion Failed: The finalizer for the LogonManager instance should not be called directly, use a “using” statement instead. At LogonManager.Finalize()
Here’s a screenshot
http://www.beringer.net/images/LogonManagerError.gif
The error message is generated from a piece of SDK code located here:
sdk\server\helpers\cs\idcrlwrapper\Program.cs
The code calling the error message:
Has anyone seen this issue? Thank you for reading.
Nice, however, I need a different solution which using javascript to access the discovery service. Currently, I get "Permission Denial" when using javasript with XmlHttp object. Please help.
Okay, so I'll give you a baker's dozen of some really good stuff from the perspective of a Microsoft
hi Alexander,
i am a new crm developer. i want to use my custom web service (having 2 parameters) that i developed and hosted in my PC. what should i do to access this service? is there any changes required to access it?
thanks n regards,
Jahedur
Hi Rob,
I believed the reason that you are getting this error is because you compiled IdCrlWrapper project in a debug mode. try to compile it using Release mode to see if you still getting this error.
Darren
I too need to do this outsideof a C#/.NET environment. Did Michael Bock (above) every get a response?