如何覆盖 WebServiceHostFactory MaxReceivedMessageSize? [英] How to override WebServiceHostFactory MaxReceivedMessageSize?

查看:38
本文介绍了如何覆盖 WebServiceHostFactory MaxReceivedMessageSize?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

那里有很多类似的问题,但我已经尝试了每个解决方案中的每一个都无济于事.

There are a lot of similar questions out there, but I have tried every solution in every one of them to no avail.

我们有一个使用 WebServiceHostFactory 初始化的 Web 服务,但是如果向它抛出的数据超过 64k,我们会收到400 Bad Request".通常,这只能通过提高 MaxReceivedMessageSize、MaxBufferSize 和 MaxBufferPoolSize 来解决.问题是使用 WebServiceHostFactory,Web.Config 被完全忽略.我在 ServiceModel 部分所做的更改根本没有反映在服务中.

We have a web service that initialises with WebServiceHostFactory, but if any more than 64k is thrown at it, we get a '400 Bad Request'. Normally, this would just be resolved by bumping up the MaxReceivedMessageSize, MaxBufferSize and MaxBufferPoolSize. The problem is that using the WebServiceHostFactory, the Web.Config is completely ignored. No changes I make in the ServiceModel section reflect in the service at all.

完全放弃 WebServiceHostFactory 并从头开始设置 web.config 会很好,但是没有它我们的服务将无法运行.其中一种方法具有流参数以及其他一些字符串参数.没有工厂,我们得到

It would be nice to just completely ditch WebServiceHostFactory and set up the web.config from scratch, but our service will not run without it. One of the methods has a stream parameter as well as some other string params. Without the factory, we get

System.InvalidOperationException: For request in operation Test to be a stream the operation must have a single parameter whose type is Stream

所以移除工厂不是一个选项.我无法确切地弄清楚工厂正在做什么来修复这个错误,但我花了 4 天的时间来解决这个问题,但始终没有取得任何进展.

So it is not an option to remove the factory. I can't work out exactly what the factory is doing that fixes this error but I spent 4 days on it and never got anywhere.

我还尝试以编程方式覆盖 MaxReceivedMessageSize,并提供了一些我在现场找到的示例:

I've also tried overriding MaxReceivedMessageSize programatically, with some examples I found on around the place:

protected override void OnOpening()
        {
            base.OnOpening();
            foreach (var endpoint in Description.Endpoints)
            {

                //var binding = endpoint.Binding as WebHttpBinding;
                //if (binding != null)
                //{
                //    binding.MaxReceivedMessageSize = 20000000;
                //    binding.MaxBufferSize = 20000000;
                //    binding.MaxBufferPoolSize = 20000000;
                //    binding.ReaderQuotas.MaxArrayLength = 200000000;
                //    binding.ReaderQuotas.MaxStringContentLength = 200000000;
                //    binding.ReaderQuotas.MaxDepth = 32;
                //}


                //var transport = endpoint.Binding.CreateBindingElements().Find<HttpTransportBindingElement>();
                //if (transport != null)
                //{
                //    transport.MaxReceivedMessageSize = 20000000;
                //    transport.MaxBufferPoolSize = 20000000;
                //}


                var newTransport = new HttpTransportBindingElement();
                newTransport.MaxReceivedMessageSize = 20000000;
                newTransport.MaxBufferPoolSize = 20000000;
                endpoint.Binding.CreateBindingElements().Add(newTransport);
            }
        }

第一个不起作用,因为工厂创建了一个不能转换为 WebHttpBinding 的 CustomBinding.第二个不起作用,因为绑定元素似乎是只读的 - 无论我将元素设置为什么,都没有任何变化,我已经通过在更改"它们后读取值来验证这一点.第三次是尝试在其中抛出新绑定元素的最后一次尝试,但当然这也失败了.

The first doesn't work as the factory creates a CustomBinding which cannot be cast to a WebHttpBinding. The second doesn't work as it seems the binding elements are read only - no matter what I set the elements to, nothing changes, which I have verified by reading the values back after 'changing' them. The third was a last ditch attempt to try to throw a new binding element in there, but of course this failed as well.

现在我们完全不知所措.我们怎样才能让这个东西运行起来?你以为会这么简单!

Now we are completely at a loss. How can we get this thing to run? You think it would be so simple!

谢谢各位

Web.Config

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.web>
    <compilation targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <bindings>
      <webHttpBinding>
        <binding name="rest" maxReceivedMessageSize="500000000" />
      </webHttpBinding>
    </bindings>
    <services>
      <service name="SCAPIService" behaviorConfiguration="ServiceBehaviour">
        <endpoint address="" binding="webHttpBinding" bindingConfiguration="rest" contract="ISCAPIService" behaviorConfiguration="web">
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehaviour">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
      <endpointBehaviors>
        <behavior name="web">
          <webHttp />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
  </system.webServer>
</configuration>

使用迄今为止未成功的建议修复进行

Edit, using a suggested fix that has been unsuccessful so far:

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 ApplyConfiguration()
        {
            base.ApplyConfiguration();
            APIUsers.TestString += "here" + Description.Endpoints.Count.ToString();
            foreach (var endpoint in this.Description.Endpoints)
            {
                var binding = endpoint.Binding;
                APIUsers.TestString += binding.GetType().ToString();
                if (binding is WebHttpBinding)
                {
                    var web = binding as WebHttpBinding;
                    web.MaxBufferSize = 2000000;
                    web.MaxBufferPoolSize = 2000000;
                    web.MaxReceivedMessageSize = 2000000;
                }
                var myReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas();
                myReaderQuotas.MaxStringContentLength = 2000000;
                myReaderQuotas.MaxArrayLength = 2000000;
                myReaderQuotas.MaxDepth = 32;
                binding.GetType().GetProperty("ReaderQuotas").SetValue(binding, myReaderQuotas, null);
            }
        }
    }

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

推荐答案

如果您要实现自己的自定义服务主机,您应该能够覆盖一个名为ApplyConfiguration"的方法,您可以在其中关联您需要的所有配置属性捆绑.一些示例代码如下所示:

If you are implementing your own custom service host you should be able to override a method called "ApplyConfiguration" where you can associate all the configuration properties you need for your binding. Some sample code as shown below:

添加我的 servicehost 工厂实现

Adding my servicehost factory implementation

public class MyServiceHost : System.ServiceModel.ServiceHost
{
    public MyServiceHost () { }

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

    }

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

    }

protected override void ApplyConfiguration()
            {
                Console.WriteLine("ApplyConfiguration (thread {0})", System.Threading.Thread.CurrentThread.ManagedThreadId);
                base.ApplyConfiguration();
                foreach (ServiceEndpoint endpoint in this.Description.Endpoints)
                {
                    Binding binding = endpoint.Binding;
                    var binding = endpoint.Binding;
                    if(binding is WebHttpBinding)
                    {
                        var web = binding as WebHttpBinding;
                        web.MaxBufferSize = 2000000;
                        web.MaxReceivedMessageSize = 2000000;
                    }
                    var myReaderQuotas = new XmlDictionaryReaderQuotas();
                    myReaderQuotas.MaxStringContentLength = 5242880;
                    binding.GetType().GetProperty("ReaderQuotas").SetValue(binding, myReaderQuotas, null); 
                }
            }

}

以上确实覆盖了您对每个绑定的配置并设置了 MaxStringContentLength.

The above does override your configuration of each binding and sets the MaxStringContentLength.

public sealed class MyServiceHostFactory : System.ServiceModel.Activation.ServiceHostFactory
    {
        public override System.ServiceModel.ServiceHostBase CreateServiceHost(string constructorString, Uri[] baseAddresses)
        {
            return base.CreateServiceHost(constructorString, baseAddresses);
        }

        protected override System.ServiceModel.ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            return new MyServiceHost(serviceType, baseAddresses);
        }
    }

现在我的 Service.svc 文件标记是这样的:

Now my Service.svc file markup has this:

<%@ ServiceHost Language="C#" Debug="true" Factory="Sample.MyServiceHostFactory" Service="Sample.ReaderQuotasService" CodeBehind="ReaderQuotasService.svc.cs" %>

这篇关于如何覆盖 WebServiceHostFactory MaxReceivedMessageSize?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆