Masinov
Masinov

Reputation: 233

Windows service calling WCF service (web http configuration)

I've searched all the available question here, I don't know if the problem is specific to my configuration or am I missing something.

Background:

I have a WCF service hosted on IIS 7 using a HTTPS binding. The service is used to send/receive large objects. A windows service uses this WCF service to send these large objects to the it, but I get the 400 Bad Request error. I have enabled tracing in the service and the error is "the maximum message size quota for incoming messages (65536) has been exceeded". Below are the WCF and Windows service configurations and how the wcf service is utilized.

WCF Service configuration.

<system.web>
    <compilation debug="true" targetFramework="4.0" />
    <globalization culture="mk-MK" fileEncoding="windows-1251" />
</system.web>
<system.serviceModel>
<bindings>
  <webHttpBinding>
    <binding name="basicWebHttp" allowCookies="true" closeTimeout="00:59:59" receiveTimeout="00:59:59"
             sendTimeout="00:59:59" maxReceivedMessageSize="2147483647" 
             maxBufferSize="2147483647" maxBufferPoolSize="2147483647" >
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647"
                    maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
      <security>
        <transport clientCredentialType="None" realm="" proxyCredentialType="None" />
      </security>
    </binding>
  </webHttpBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior>
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
      <serviceTimeouts transactionTimeout="00:10:00"/>
      <serviceThrottling maxConcurrentCalls="20" maxConcurrentSessions="20" maxConcurrentInstances="20" />
      <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
    </behavior>
  </serviceBehaviors>
  <endpointBehaviors>
    <behavior name="WebHttp">
      <webHttp automaticFormatSelectionEnabled="true" faultExceptionEnabled="true" />
      <dataContractSerializer maxItemsInObjectGraph="2147483647" />
    </behavior>
  </endpointBehaviors>
</behaviors>
<client>
  <endpoint address="" binding="webHttpBinding" bindingConfiguration="basicWebHttp"
    contract="Classes.IVisService" name="BasicHttpBinding_IVisService" behaviorConfiguration="WebHttp" />
</client>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<defaultDocument>
  <files>
    <remove value="default.aspx" />
    <remove value="iisstart.htm" />
    <remove value="index.html" />
    <remove value="index.htm" />
    <remove value="Default.asp" />
    <remove value="Default.htm" />
    <remove value="Default.html" />
    <add value="VisService.svc" />
  </files>
</defaultDocument>
<urlCompression doDynamicCompression="false" />
</system.webServer>
<system.diagnostics>
<sources>
  <source name="System.ServiceModel"
          switchValue="Information, ActivityTracing, Error"
          propagateActivity="true">
    <listeners>
      <add name="traceListener"
          type="System.Diagnostics.XmlWriterTraceListener"
          initializeData= "c:\log\Traces.svclog" />
    </listeners>
  </source>
</sources>
</system.diagnostics>

The service is consumed through a Windows service who has the following configuration :

<system.web>
<httpRuntime maxRequestLength="2147483647" />
</system.web>
<system.serviceModel>
<bindings>
  <webHttpBinding>
    <binding name="basicWebHttp" allowCookies="true" closeTimeout="00:59:59" receiveTimeout="00:59:59"
              sendTimeout="00:59:59"
              maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" maxBufferPoolSize="2147483647">
      <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647"
                    maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
      <security mode="Transport">
        <transport clientCredentialType="None"></transport>
      </security>
    </binding>
  </webHttpBinding>
</bindings>
<behaviors>
  <endpointBehaviors>
    <behavior name="basicWebHttpBehaviour">
      <dataContractSerializer maxItemsInObjectGraph="2147483647" />
      <webHttp />
    </behavior>
  </endpointBehaviors>
</behaviors>
<client>
  <endpoint address="" behaviorConfiguration="basicWebHttpBehaviour"
            binding="webHttpBinding" bindingConfiguration="basicWebHttp"
            contract="labis.IVisService" name="BasicHttpBinding_IVisService" />
</client>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

The service is called like this :

System.Net.ServicePointManager.ServerCertificateValidationCallback += (se, cert, chain, sslerror) => { return true; };
WebChannelFactory<IVisService> factory = new WebChannelFactory<IVisService>(
                                "BasicHttpBinding_IVisService",
                                new Uri("https://some_ip/service.svc"));
IVisService service = factory.CreateChannel();
service.PostData(large_object);

I've enabled tracing and from the log I can see that the server throws the exception : the maximum message size quota for incoming messages (65536) has been exceeded

I think I've set all the needed properties for this to work, but no luck. Also in the IIS configuration editor I've set the system.webServer/security/requestFiltering - requestLimits property to maximum

Any help ?

Thanks :)

EDIT 1

I pasted the wrong endpoint configuration element. The original lacked the behaviorConfiguration="WebHttp" part but I've tested it with this property included.

Upvotes: 2

Views: 4872

Answers (5)

Masinov
Masinov

Reputation: 233

After trying all the possibilities, the solution was really simple. I added the following configuration to the WCF service

<protocolMapping>
  <add scheme="https" binding="webHttpBinding" bindingConfiguration="basicWebHttp" />
  <add scheme="http" binding="webHttpBinding" bindingConfiguration="basicWebHttp" />
</protocolMapping>

Read more about it here http://msdn.microsoft.com/en-us/library/ee816881.aspx

I guess this worked because the service uses HTTPS binding so it needed an explicit mapping of the binding.

At least this worked for me

Upvotes: 2

sm_
sm_

Reputation: 2602

You can try something like this :

Try providing the endpoint in the constructor of your WebChannelFactory.

But first you have to pull out your configuration and create an instance of your endpoint and provide the behaviour manually.

http://weblogs.asp.net/cibrax/archive/2010/05/11/getting-wcf-bindings-and-behaviors-from-any-config-source.aspx is a great resource on how to do that.

public Binding ResolveBinding(string name)
    {
    Configuration appConfig = System.Configuration.ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

ServiceModelSectionGroup serviceModel = ServiceModelSectionGroup.GetSectionGroup(appConfig);

      BindingsSection section = serviceModel.Bindings;

      foreach (var bindingCollection in section.BindingCollections)
      {
        if (bindingCollection.ConfiguredBindings.Count > 0 

    && bindingCollection.ConfiguredBindings[0].Name == name)
        {
          var bindingElement = bindingCollection.ConfiguredBindings[0];
          var binding = (Binding)Activator.CreateInstance(bindingCollection.BindingType);
          binding.Name = bindingElement.Name;
          bindingElement.ApplyConfiguration(binding);

          return binding;
        }
      }

      return null;
    }

public List<IEndpointBehavior> ResolveEndpointBehavior(string name)
{
     Configuration appConfig = System.Configuration.ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

ServiceModelSectionGroup serviceModel = ServiceModelSectionGroup.GetSectionGroup(appConfig);

      BindingsSection section = serviceModel.Behaviors;
  List<IEndpointBehavior> endpointBehaviors = new List<IEndpointBehavior>();

  if (section.EndpointBehaviors.Count > 0 

&& section.EndpointBehaviors[0].Name == name)
  {
    var behaviorCollectionElement = section.EndpointBehaviors[0];

    foreach (BehaviorExtensionElement behaviorExtension in behaviorCollectionElement)
    {
      object extension = behaviorExtension.GetType().InvokeMember("CreateBehavior",
            BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Instance,
            null, behaviorExtension, null);

      endpointBehaviors.Add((IEndpointBehavior)extension);
    }

   return endpointBehaviors;
 }

 return null;
}

THEN USE :

    var binding = ResolveBinding("MyBinding");
    var behaviors = ResolveEndpointBehavior("MyBehavior");
    System.ServiceModel.Description.ContractDescription contract = System.ServiceModel.Description.ContractDescription.GetContract(typeof(IVisService));
     System.ServiceModel.Description.ServiceEndpoint ep = new System.ServiceModel.Description.ServiceEndpoint(contract, binding, "https://some_ip/service.svc");
                    foreach (var behavior in behaviors)
                    {
                        ep.Behaviors.Add(behavior);
                    }

System.ServiceModel.Web.WebChannelFactory<IVisService> t = new System.ServiceModel.Web.WebChannelFactory<IVisService>(ep);

Upvotes: 1

miles
miles

Reputation: 26

<system.web>
<httpRuntime maxRequestLength="2147483647" /  >
</system.web>

put the above conf into web.config where your service is hosted.

Upvotes: 1

Praveen Verma
Praveen Verma

Reputation: 144

Last 2 weeks before i faced the same issue, even i have updated the configuration at both service and client side, same as your but code did not work we got the same exceed size message.

Then we performed the below operations

1. Updated the webconfig file of service
2. Reset IIS of service
3. Created a proxy for service
4. updated client web.config file
5. reset the iis of client(webapplication)

then it worked for me.

Upvotes: 0

sm_
sm_

Reputation: 2602

In you WCF Service configuration

you forgot to add the behaviour configuration(you named it "WebHttp") to the endpoint

try this :

<endpoint address="" binding="webHttpBinding" bindingConfiguration="basicWebHttp"
    contract="Classes.IVisService" name="BasicHttpBinding_IVisService" behaviorConfiguration="WebHttp" />

Upvotes: 1

Related Questions