7

そこには多くの類似の質問がありますが、私はすべてのソリューションを無駄にしようとしました。WebServiceHostFactory MaxReceivedMessageSizeをオーバーライドする方法?

私たちはWebServiceHostFactoryで初期化するWebサービスを持っていますが、64kを超えるものがあれば '400 Bad Request'を取得します。通常、これはMaxReceivedMessageSize、MaxBufferSize、およびMaxBufferPoolSizeをバンプすることによって解決されます。問題は、WebServiceHostFactoryを使用すると、Web.Configが完全に無視されることです。 ServiceModelセクションで行った変更は、サービスに反映されません。

WebServiceHostFactoryを完全に捨てて、最初からweb.configを設定するとよいでしょうが、サービスがなくても実行されません。メソッドの1つにストリームパラメータと他の文字列パラメータがあります。工場がなければ、

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

したがって、工場を取り外すことはできません。私は工場が何をしているのかを正確には調べることができません。このエラーを修正しましたが、私は4日間過ごしました。

また、私は場所の周りにあるいくつかの例を用いて、プログラム的MaxReceivedMessageSizeを上書きしようとしました:

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を作成します。 2つ目は、バインディング要素が読み取り専用であるように機能しません。要素を何に設定しても、何も変更されません。値を変更した後で値を読み取ることで検証しました。 3つ目は、最後に新しいバインディング要素を投げようとする試みでしたが、もちろんこれも失敗しました。

今私たちは完全に迷っています。どうやってこのことを実行させることができますか?あなたはそれがとても簡単だと思います!

みんなありがとう

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

編集、これまでのところ成功していない修正案を使用して:

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); 
     } 
    } 

答えて

3

独自のカスタムサービスホストあなたを実装している場合バインドに必要なすべてのコンフィグレーションプロパティを関連付けることができる "ApplyConfiguration"というメソッドをオーバーライドできる必要があります。以下に示すようにいくつかのサンプルコード:

EDIT:追加私のServiceHostファクトリ実装

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を設定します。

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ファイルのマークアップは、この持っている:他人の利益のために

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

感謝Rajesh。しかし、これは依然として私のためにはうまく機能していません。何らかの理由で、ApplyConfigurationが呼び出されたときにエンドポイントが存在しないため、foreachループ内に置かないことさえあります。ファクトリがすべての記述作成を行っているので、ApplyConfigurationが起動する前にエンドポイントを作成する方法はありますか? –

+0

詳細なヘルプを提供するための工場コードを掲載することは可能ですか? – Rajesh

+0

もちろん、コードで質問を更新しました。宣言は次のようになります。<%@ ServiceHost Language = "C#" Debug = "true" Service = "APINamespace.Service" CodeBehind = "Service.svc.cs" Factory = "WcfService1.MyWebServiceHostFactory"%> このコードが実行されていることを確認するために、APIUsers.TestStringが出力されます。結果はここ0(0 =エンドポイント数) –

7

、上記の答えは右の道を行くが、それには多くのエラーを持っており、変更なしに動作しません。 (したがって、OPは解決策を働かせることができませんでした)。次のものを使用すると、それはあなたのために 'すぐに使える'でしょう。

- それは非常に重要そうしないと、次のエラーメッセージが表示されます、すべて以下のコンストラクタを提供し、工場で実証され、コンストラクタのオーバーロードを使用する次のとおりです。

InitializeRuntimeは、そのDescriptionプロパティが必要です初期化される。どちらのCreateDescription方法で有効なServiceDescriptionを提供したり、代替実装に

カスタムのServiceHostの実装を提供するためにInitializeRuntimeメソッドをオーバーライド:

public class CustomServiceHost : ServiceHost 
{ 
    public CustomServiceHost() 
    { 
    } 

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

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

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

     foreach (var endpoint in this.Description.Endpoints) 
     { 
      var binding = endpoint.Binding; 
      var web = binding as WebHttpBinding; 

      if (web != null) 
      { 
       web.MaxBufferSize = 2147483647; 
       web.MaxReceivedMessageSize = 2147483647; 
      } 

      var myReaderQuotas = new XmlDictionaryReaderQuotas { MaxStringContentLength = 2147483647 }; 

      binding.GetType().GetProperty("ReaderQuotas").SetValue(binding, myReaderQuotas, null); 
     } 
    } 
} 

カスタムServiceHostFactory実装を:

public sealed class CustomServiceHostFactory : ServiceHostFactory 
{ 
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) 
    { 
     return new CustomServiceHost(serviceType, baseAddresses); 
    } 
} 

Service1.svc上記のマークアップは、タイプが正しい限り動作します。私は実際にWebServiceHostをオーバーライドしてより大きなJSON応答サイズを許可するためにこのテクニックを使用しましたが、その原則はすべてServiceHostにも適用する必要があります。

+0

私はバインディングプロパティをオーバーライドしようとしていませんが、コンストラクタに関するメモとInitializeRuntimeエラーについて+1しています。それは私が探していたものでした! – AdmSteck

+0

VB .NETでは、コンストラクタに.New()キーワードを使用しますか? – Thomas

+0

非常に役に立ちます。私は 'ApplyConfiguration()'を使ってエンドポイントの振る舞いを追加しようとしていましたが、 'WebServiceHost'は' OnOpening() 'までそのエンドポイントを作成しません。 – kenchilada

関連する問題