Слишком длинный ответ WCF - ошибка аутентификации - PullRequest
3 голосов
/ 13 января 2010

В проекте, над которым я сейчас работаю, есть служба WCF, которая возвращает массив бизнес-объекта, назовем его Invoice:

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

Используемый механизм аутентификации - аутентификация Windows, служба WCF размещается в веб-приложении, размещенном на IIS 6.

Сначала, когда я использовал для получения данных размером более 64 КБ, возникло исключение CommunicationException, в котором говорилось, что «Превышена квота максимального размера сообщения для входящих сообщений (65536). Чтобы увеличить квоту, используйте свойство MaxReceivedMessageSize в соответствующем элементе привязки. . "

Хорошо, я только что увеличил в App.config значения до 65536000 (я явно добавил три ноля в конце) как для maxReceivedMessageSize, так и для maxBufferSize (последний, потому что он жаловался в ArgumentException, что «для TransferMode.Buffered, MaxReceivedMessageSize и MaxBufferize должно быть одинаковым значением. Имя параметра: bindingElement ").

Теперь я могу получать ответы большего размера ...

Пока я не достигну другого предела (я ДУМАЮ), в котором после 624 элементов (около 2,2 МБ) выдается странное исключение:

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 ---

Трассировка стека серверов:

   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)

Исключение переброшено в [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

Есть ли ограничение для аутентифицированных ответов? Есть ли ограничение в настройках ASP.NET?

Ответы [ 2 ]

3 голосов
/ 19 декабря 2011

Я предполагаю, что вы используете проверку подлинности Windows, следовательно, 401, а не сообщение, объясняющее, как вы нарушили ограничения на количество сообщений. Когда вы отправляете запрос с проверкой подлинности Windows, WCF отправляет запрос SOAP дважды, один раз для его сбоя и возврата заголовка accept, а второй раз для отправки его с заголовками проверки подлинности Windows.

Однако, из моего тестирования, похоже, что вы все равно получите 401, если сообщение действительно не получилось бы, если бы оно прошло.

Чтобы устранить эту проблему, я должен был поставить запись трассировки сервера в:

<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>

Затем мне пришлось ввести более крупные квоты для считывателей, как указано выше (но я использовал меньшие значения):

Тогда вам обычно приходится настраивать поведение, чтобы увеличить максимальное количество элементов в графе объектов:

<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>

Вам потребуется добавить атрибут «PractiourConfiguration» в ваш элемент «<system.serviceModel><services><service>» со значением «MaximumItemsBehaviour».

Другой совет, который я прочитал, но сам не нуждался в том, чтобы добавить:

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

И

  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="209715200"/>
      </requestFiltering>
    </security>
  </system.webServer>
0 голосов
/ 13 января 2010

Посмотрите на readerQuotas на стороне клиента, если вы хотите версию TLDR - чтобы увидеть, действительно ли это ваша проблема, вы можете установить максимальные значения (Int32.MaxValue), как показано ниже.

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