George wrote this Article
Yesterday I was working on some plug-in code which was working fine earlier. I changed pipeline to synchronous and started to get consistent "404 - Not Found" error from calls to CrmService. I reduced the problem to something like this:
public class MyPlugin: IPlugin
{
public void Execute(IPluginExecutionContext context)
{
ICrmService service = context.CreateCrmService(true);
account a = new account();
a.name = "test";
service.Create(a); // this line fails with 404
}
}
And it just was not working. We all know about very "informative" SoapException which would have been fine but I was getting simple http-level 404. Something was pointing somewhere it shouldn't have...
Stepping through with the debugger I managed to find out that, if plugin is registered for synchronous execution, call to context.CreateCrmService seems to return a service wrapper that ALWAYS points to http://localhost/MSCrmServices/2007/CrmService.asmx regardless whether CRM is handling requests to http://localhost or not. In my environment CRM was installed outside of the default web site and, as such, did not handle requests sent to localhost. Hence consistent 404 error.
I managed to "reflectorise" the problem down to the class Microsoft.Crm.Extensibility.CrmServiceFactory in the assembly Microsoft.Crm.ObjectModel. In this class GetServerUrl() method contains something like this:
string deploymentSetting; // protocol, i.e http or https
int nullable? = null; // this is actually local port for crm, e.g. 5555 on the server or 2525 offline
<snip >some cassini logic and getting localsdkport setting from registry</snip>
string str2 = "localhost"; // here you have it
if (nullable.HasValue)
{
str2 = string.Format(CultureInfo.InvariantCulture, "{0}:{1}", new object[] { str2, nullable });
}
return string.Format(CultureInfo.InvariantCulture, "{0}://{1}/MSCRMServices", new object[] { deploymentSetting, str2 }); // this is always a localhost?!
So, basically it always returns something like http://localhost[:optionalport]/MSCRMServices. Which is fine if you are in offline mode or if you have your http://localhost pointing to your CRM web site which is not the case in my development environment.
Plug-ins registered for asynchronous execution are getting CrmService wrapper from a different proxy factory located in assembly CrmAsyncService.exe which seem to honour all configuration settings.
Workaround
I could not think of anything better but to add localhost to the list of headers handled by CRM web site. Simple yet effective - the problem's gone. This workaround is fine in development environment but not in a deployment where for one reason or another localhost must point elsewhere.
I am curious to hear from fellow developers if anybody has come across of this problem as well as from anyone from MSFT if this behaviour is by design or it's a bug.
No comments:
Post a Comment