WCF WebServiceHostFactory MaxReceivedMessageSize конфигурация - PullRequest
1 голос
/ 03 ноября 2010

У меня есть RESTful веб-сервис WCF под названием "Palladium" в качестве проекта в моем решении VS2008.Он размещается в веб-приложении ASP.Net 3.5 с использованием реализации WebServiceHostFactory на странице под названием «Palladium.svc».

Мой сервис работает аналогично тому, как объяснено здесь , посредством чего сервисы могут получать POST вместе с другими параметрами, определенными в URITemplate.

служба работает хорошо, и я могу получать опубликованную информацию и работать с ней.
Моя проблема возникает, когда данные записей превышают 65 КБ, и я получаю следующую ошибку (полученную с помощью system.diagnostics в web.config и Microsoft Service Trace Viewer),

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

Поскольку служба размещается через реализацию WebServiceHostFactory, для службы установлены привязки по умолчанию, установленные для нее фабрикой.Я попытался переопределить эти привязки, указав параметры привязки и конечные точки в файле web.config.Однако, когда я сделал это, я получил сообщение об ошибке:

System.InvalidOperationException, mscorlib, Версия = 2.0.0.0, Culture = нейтральный, PublicKeyToken = b77a5c561934e089

Для запроса вОперация LogStartingDetails должна быть потоком. У операции должен быть один параметр, тип которого - Stream.

LogStartingDetails - это метод, который я вызываю в моей службе RESTful.

Очевидно, что метод LogStartingDetails не должен иметь ни одного параметра, тип которого равен Stream, как, например, когда фабрика создавала привязки для меня, сервис хорошо реагировал (или, более точно,для не нужно было иметь один параметр, когда завод выполнял эту работу за меня).

После долгих исследований и столкновения с несколькими кирпичными стенами я решил создать свой собственный класс, который наследуется от WebServiceHostFactory и переопределяет некоторые реализации, чтобы указать свойство MaxReceivedMessageSize для привязки..
Когда я выполняю создание сервиса в своем классе фабрики с помощью отладки, я вижу транспорт, получающий новые значения MaxReceivedMessageSize и MaxBufferSize , но они не отображаются всделать что-нибудь, и я все равно получаю то же самое исключение The maximum message size quota for incoming messages (65536) has been exceeded..

Ниже приведены примеры моего сервисного кода.Если бы кто-то мог помочь мне понять, что я делаю здесь неправильно, это было бы очень ценно.

Palladium.svc (размещено в веб-приложении ASP.Net)

<%@ ServiceHost Language="C#" Debug="true" Service="CDS.PalladiumService.Palladium" Factory="CDS.PalladiumService.MyWebServiceHostFactory" %>

MyWebServiceHostFactory.cs (в проекте CDS.PalladiumService)

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Channels;
using System.ServiceModel.Web;

namespace CDS.PalladiumService
{
    public class MyServiceHost : WebServiceHost
    {
        public MyServiceHost()
        {
        }

        public MyServiceHost(object singletonInstance, params Uri[] baseAddresses)
            : base(singletonInstance, baseAddresses)
        {
        }

        public MyServiceHost(Type serviceType, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
        }


        protected override void OnOpening()
        {
            base.OnOpening();

            if (base.Description != null)
            {
                foreach (var endpoint in base.Description.Endpoints)
                {
                    var transport = endpoint.Binding.CreateBindingElements().Find<TransportBindingElement>();
                    if (transport != null)
                    {
                        transport.MaxReceivedMessageSize = 5242880;
                        transport.MaxBufferPoolSize = 5242880;
                    }
                }
            }
        }
    }

    class MyWebServiceHostFactory : WebServiceHostFactory
    {
        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            return new MyServiceHost(serviceType, baseAddresses);
        }
    }
}

IPalladium.cs (в проекте CDS.PalladiumService)

using System.IO;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace CDS.PalladiumService
{
    // NOTE: If you change the interface name "IPalladium" here, you must also update the reference to "IPalladium" in Web.config.
    [ServiceContract]
    public interface IPalladium
    {
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = UriTemplate.LogStartingDetails)]
        void LogStartingDetails(string truckId, string palladiumId, Stream postData);
    }
}

Palladium.cs (в проекте CDS.PalladiumService)

using System.IO;
using System.ServiceModel.Activation;

namespace CDS.PalladiumService
{
    // NOTE: If you change the class name "Palladium" here, you must also update the reference to "Palladium" in Web.config.
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class Palladium : IPalladium
    {
        public void LogStartingDetails(string truckId, string palladiumId, Stream postData)
        {
            string contents = string.Empty;
            using (var reader = new StreamReader(postData))
            {
                contents = reader.ReadToEnd();
            }

            StreamWriter sw1 =
                File.AppendText(@"C:\log.txt");
            sw1.WriteLine(contents);
            sw1.WriteLine("");
            sw1.Close();

            return;
        }
    }
}

URITemplate.cs (в проекте CDS.PalladiumService)

namespace CDS.PalladiumService
{
    public static class UriTemplate
    {
        public const string LogStartingDetails = "/log-starting/{truckId}/{palladiumId}";
    }
}

Ответы [ 2 ]

3 голосов
/ 17 декабря 2010

Мне удалось добиться этого, установив 3 параметра ниже для привязки конечной точки в методе OnOpening моего WebServiceHost:

protected override void OnOpening()
{
  base.OnOpening();

  foreach (var endpoint in Description.Endpoints)
  {
    var binding = endpoint.Binding as WebHttpBinding;
    if (binding != null)
    {
      const int fiveMegaBytes = 5242880;
      binding.MaxReceivedMessageSize = fiveMegaBytes;
      binding.MaxBufferSize = fiveMegaBytes;
      binding.MaxBufferPoolSize = fiveMegaBytes;
    }
  }
}

Мне нужен большой размер буфера, потому что я не могу включить потоковую передачу.

2 голосов
/ 01 июля 2011

Хорошо, для тех из вас, кто ищет решение вышеуказанной проблемы - я просто внес некоторые изменения в мой файл web.config и разместил службу на своем веб-сайте asp.net.

Я изменилсяраздел <system.serviceModel> моей веб-конфигурации соответствует следующему - это позволяет использовать «Большое связывание сообщений», где максимальная длина сообщения указана в соответствующем разделе файла конфигурации.

<system.serviceModel>
<bindings>
  <webHttpBinding>
    <binding name="largeMessageBinding" maxBufferPoolSize="5242880" maxReceivedMessageSize="5242880" transferMode="Buffered">
      <readerQuotas maxStringContentLength="5242880" maxArrayLength="5242880" maxBytesPerRead="5242880" />
    </binding>
  </webHttpBinding>
</bindings>

<behaviors>
  <endpointBehaviors>
    <behavior name="largePostEndpointBehavior">
      <webHttp />
    </behavior>
  </endpointBehaviors>
  <serviceBehaviors>
    <behavior name="CDS.UI.Resources.Services.PalladiumBehavior">
      <serviceMetadata httpGetEnabled="false" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>

<services>
  <service behaviorConfiguration="CDS.UI.Resources.Services.PalladiumBehavior"
   name="CDS.PalladiumService.Palladium">
    <endpoint address="" binding="webHttpBinding" behaviorConfiguration="largePostEndpointBehavior"
              bindingConfiguration="largeMessageBinding" contract="CDS.PalladiumService.IPalladium" />
  </service>
</services>

</system.serviceModel>
...