WCF响应太长—验证错误

时间:2021-04-20 20:28:32

In the project that I currently work for, there is exposed a WCF service which returns an array of a business entity, let's call it Invoice :

在我目前工作的项目中,公开了一个WCF服务,它返回一个业务实体的数组,我们称它为Invoice:

Invoice[] GetInvoicesByTypeAndTime(InvoiceType invoiceType, byte startHour, byte? endHour);

The authentication mechanism used is Windows Authentication, the WCF service is hosted in a Web Application hosted on IIS 6.

使用的身份验证机制是Windows身份验证,WCF服务托管在IIS 6上托管的Web应用程序中。

At first when I used to get data more than 64kB a CommunicationException was thrown stating that "The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element."

起初,当我获取的数据超过64kB时,会抛出一个通信异常,指出“已经超过了传入消息的最大消息大小配额(65536)”。要增加限额,请在适当的绑定元素上使用MaxReceivedMessageSize属性。

Fine, I just increased in App.config the values to 65536000 (I blatantly added three zeros at the end) for both maxReceivedMessageSize and maxBufferSize (the latter because it complained in an ArgumentException that "For TransferMode.Buffered, MaxReceivedMessageSize and MaxBufferSize must be the same value. Parameter name: bindingElement").

好的,我只是在App.config中为maxReceivedMessageSize和maxBufferSize(后者是因为它在ArgumentException中抱怨说“for TransferMode”)将值增加到65536000(我在末尾加了三个0)。缓冲、maxreceivedmessagze和MaxBufferSize必须是相同的值。参数名称:bindingElement”)。

Now I could receive larger responses...

现在我可以收到更多的回复……

Until I hit another limit (I THINK) in that after 624 elements (approx. 2.2 MB) a strange exception is thrown :

直到我在624个元素之后达到另一个极限。2.2 MB)抛出一个奇怪的异常:

System.ServiceModel.Security.MessageSecurityException: The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate,NTLM'. ---> System.Net.WebException: The remote server returned an error: (401) Unauthorized.
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   --- End of inner exception stack trace ---

Server stack trace:

服务器堆栈跟踪:

   at System.ServiceModel.Channels.HttpChannelUtilities.ValidateAuthentication(HttpWebRequest request, HttpWebResponse response, WebException responseException, HttpChannelFactory factory)
   at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory factory, WebException responseException)
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]:

异常rethrown[0]:

   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at Test2.DBS.IDbService.GetInvoicesByTypeAndTime(InvoiceType invoiceType, Byte startHour, Nullable`1 endHour)
   at Test2.DBS.DbServiceClient.GetInvoicesByTypeAndTime(InvoiceType invoiceType, Byte startHour, Nullable`1 endHour) in D:\TEMP\Test2\Test2\Service References\DBS\Reference.cs:line 1445
   at Test2.Program.Main(String[] args) in D:\TEMP\Test2\Test2\Program.cs:line 19

Is there a limit on authenticated responses? Is there a limit from the ASP.NET settings?

经过验证的响应是否有限制?ASP有限制吗?网络设置?

2 个解决方案

#1


3  

I'm guessing that you're using Windows Authentication hence the 401 rather than a message explaining how you've blown your message limits. When you send through a Windows Authenticated request, WCF sends the SOAP request twice, once for it to fail and return an accepts header, and the second time to send it with the Windows Authentication headers.

我猜您是在使用Windows身份验证,因此使用的是401,而不是一条解释您如何突破消息限制的消息。当您通过Windows认证的请求发送时,WCF会发送两次SOAP请求,一次失败并返回一个接收头,另一次使用Windows认证头发送。

However, from my testing, it looks like you still get the 401 if the message would have actually failed if it did get through.

然而,从我的测试来看,如果消息真的通过了,你仍然可以获得401退休金。

To troubleshoot this, I had to put server trace logging in:

为了解决这个问题,我必须将服务器跟踪日志记录到:

<system.diagnostics>
    <trace autoflush="true" />
    <sources>
      <source name="System.ServiceModel" switchValue="Critical, Error, Warning">
        <listeners>
          <add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="C:\Logs\ServiceTrace.svclog"/>
        </listeners>
      </source>
    </sources>
  </system.diagnostics>

Then, I had to put in larger reader quotas, as above (but I used smaller values):

然后,我必须像上面那样,设置更大的阅读器配额(但我使用的是更小的值):

Then you generally have to put in a custom behaviour to increase the maximum number of items in an object graph:

然后,您通常需要放入一个自定义行为来增加对象图中的最大条目数:

<behaviors>
  <serviceBehaviors>
    <behavior name="MaximumItemsBehaviour">
      <dataContractSerializer maxItemsInObjectGraph="2147483647" />
      <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
      <serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
      <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>

You'll need to add a "behaviourConfiguration" attribute to your "<system.serviceModel><services><service>" element with the value "MaximumItemsBehaviour".

您需要将“行为配置”属性添加到“ <系统”中。servicemodel> <服务> <服务> "元素,其值为"最大值"。

Other advice I read, but didn't need myself was to add:

其他我读过但不需要我自己的建议是:

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <httpRuntime maxRequestLength="2097151" />
  </system.web>

And:

和:

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="209715200"/>
      </requestFiltering>
    </security>
  </system.webServer>

#2


0  

Take a look at readerQuotas on the client side, if you want the TLDR version - to see if this is indeed your issue, you can set the max's (Int32.MaxValue) as shown below.

查看客户端上的readerquota,如果您想要TLDR版本—要查看这是否确实是您的问题,您可以设置max (Int32.MaxValue),如下所示。

<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />

#1


3  

I'm guessing that you're using Windows Authentication hence the 401 rather than a message explaining how you've blown your message limits. When you send through a Windows Authenticated request, WCF sends the SOAP request twice, once for it to fail and return an accepts header, and the second time to send it with the Windows Authentication headers.

我猜您是在使用Windows身份验证,因此使用的是401,而不是一条解释您如何突破消息限制的消息。当您通过Windows认证的请求发送时,WCF会发送两次SOAP请求,一次失败并返回一个接收头,另一次使用Windows认证头发送。

However, from my testing, it looks like you still get the 401 if the message would have actually failed if it did get through.

然而,从我的测试来看,如果消息真的通过了,你仍然可以获得401退休金。

To troubleshoot this, I had to put server trace logging in:

为了解决这个问题,我必须将服务器跟踪日志记录到:

<system.diagnostics>
    <trace autoflush="true" />
    <sources>
      <source name="System.ServiceModel" switchValue="Critical, Error, Warning">
        <listeners>
          <add name="traceListener" type="System.Diagnostics.XmlWriterTraceListener" initializeData="C:\Logs\ServiceTrace.svclog"/>
        </listeners>
      </source>
    </sources>
  </system.diagnostics>

Then, I had to put in larger reader quotas, as above (but I used smaller values):

然后,我必须像上面那样,设置更大的阅读器配额(但我使用的是更小的值):

Then you generally have to put in a custom behaviour to increase the maximum number of items in an object graph:

然后,您通常需要放入一个自定义行为来增加对象图中的最大条目数:

<behaviors>
  <serviceBehaviors>
    <behavior name="MaximumItemsBehaviour">
      <dataContractSerializer maxItemsInObjectGraph="2147483647" />
      <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
      <serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
      <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>

You'll need to add a "behaviourConfiguration" attribute to your "<system.serviceModel><services><service>" element with the value "MaximumItemsBehaviour".

您需要将“行为配置”属性添加到“ <系统”中。servicemodel> <服务> <服务> "元素,其值为"最大值"。

Other advice I read, but didn't need myself was to add:

其他我读过但不需要我自己的建议是:

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <httpRuntime maxRequestLength="2097151" />
  </system.web>

And:

和:

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="209715200"/>
      </requestFiltering>
    </security>
  </system.webServer>

#2


0  

Take a look at readerQuotas on the client side, if you want the TLDR version - to see if this is indeed your issue, you can set the max's (Int32.MaxValue) as shown below.

查看客户端上的readerquota,如果您想要TLDR版本—要查看这是否确实是您的问题,您可以设置max (Int32.MaxValue),如下所示。

<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />