Equalsk Equalsk - 4 months ago 25
ASP.NET (C#) Question

How do I configure an ASP.NET web page to use wsHttpBinding when querying CRM Online?

How do I configure an ASP.NET web form to send requests via

wsHttpBinding
rather than
basicHttpBinding
when querying CRM Online?

As a bit of background this is a pretty basic ASPX page hosted locally in IIS 8.5.

The page is meant to connect to CRM Online and pull some data.

Edit: This app is authenticated via Azure AD which is why it uses a client ID and key. I want to shy away from using connection strings and domain credentials unless this is unavoidable.

I think I've got the authentication to CRM correct but when I run a query I receive the error below:


System.Net.WebException: The remote server returned an error: (415) Cannot process the message because the content type 'text/xml; charset=utf-8' was not the expected type 'application/soap+xml; charset=utf-8'..


I think this is because I haven't specified a binding in
web.config
so my page is sending everything via
basicHttpBinding
and the CRM Online interface is expecting
wsHttpBinding
.

I've tried using the example at the bottom of this MSDN article (and variations thereof) but it makes no difference.

Here's the code for connecting to CRM in case it makes a difference. Obviously I've obscured the real configuration details.

// CONFIGURE OAUTH
var tenantName = "mycompany.onmicrosoft.com";
var authString = string.Format(@"https://login.microsoftonline.com/{0}",tenantName);
var authContext = new AuthenticationContext(authString, false);
var clientId = "123ab123-123a-1a23-abcd-1a2345612345";
var key = "nStgfrdk0oyaC1P5+/FQ4wGn4fRgUTr8HTKejytf0bv=";
var clientCred = new ClientCredential(clientId, key);
var resource = "https://myinstance.crm4.dynamics.com";

// ACQUIRE THE AUTH TOKEN
var authResult = await authContext.AcquireTokenAsync(resource, clientCred);

// CREATE THE CONNECTION TO CRM
var orgService = new OrganizationWebProxyClient(
new Uri("https://dev.crm4.dynamics.com/XRMServices/2011/Discovery.svc"), true)
{
HeaderToken = authResult.AccessToken,
SdkClientVersion = "8.1.0"
};

// RUNNING THIS QUERY CAUSES THE ERROR
var contacts = orgService.RetrieveMultiple(new QueryExpression
{
EntityName = "contact",
ColumnSet = new ColumnSet("firstname", "lastname")
})
.Entities
.Select(item => item.ToEntity<Contact>());


Here's the stack trace in case it's of use:


[WebException: The remote server returned an error: (415) Cannot process the message because the content type 'text/xml; charset=utf-8' was not the expected type 'application/soap+xml; charset=utf-8'..]
System.Net.HttpWebRequest.GetResponse() +1740
System.ServiceModel.Channels.HttpChannelRequest.WaitForReply(TimeSpan timeout) +75

[ProtocolException: Content Type text/xml; charset=utf-8 was not supported by service https://dev.crm4.dynamics.com/XRMServices/2011/Discovery.svc. The client and service bindings may be mismatched.]
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) +14350190
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) +388
Microsoft.Xrm.Sdk.IOrganizationService.RetrieveMultiple(QueryBase query) +0
Microsoft.Xrm.Sdk.WebServiceClient.WebProxyClient
1.ExecuteAction(Func
1 action) +51
Quote_Robot_Demo.d__4.MoveNext() +887
System.Runtime.CompilerServices.<>c.b__6_0(Object state) +56
System.Web.Util.SynchronizationHelper.SafeWrapCallback(Action action) +110
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) +13847892
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) +61
System.Web.Util.WithinCancellableCallbackTaskAwaiter.GetResult() +32
System.Web.UI.d__523.MoveNext() +7970


Edit: Once I added the service reference I got this in my web.config:

<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_IDiscoveryService">
<textMessageEncoding />
<httpsTransport />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="https://dev.crm4.dynamics.com/XRMServices/2011/Discovery.svc"
binding="customBinding" bindingConfiguration="CustomBinding_IDiscoveryService"
contract="CRMService.IDiscoveryService" name="CustomBinding_IDiscoveryService" />
</client>
</system.serviceModel>

Answer

Although I now have some other issues I did discover how to alter the binding.
You can add the organization service as a service reference to your project as I did and then assign the binding like this:

orgService.Endpoint.Binding = new CustomBinding("CustomBinding_IOrganizationService");

The string passed to the custom binding is just the name taken from the config:

<system.serviceModel>
  <bindings>
    <customBinding>
      <binding name="CustomBinding_IOrganizationService">
        ....

Edit: I discovered later on that changing the binding was not necessary. The error seemed to be being caused by an invalid security token. I changed the way I generated security tokens to use the grant_type of password and the error went away on its own.