13

WCF Webプログラミングモデルを使用すると、次のように操作コントラクトを指定できます。

[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml, UriTemplate = "SomeRequest?qs1={qs1}&qs2={qs2}")]
XElement SomeRequest1(string qs1, string qs2);

ここで、同じ名前(この場合はqs1)のパラメーターの配列を受け入れるコントラクトを作成する必要がある場合は、次のようにコントラクトします...

[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml, UriTemplate = "SomeRequest?qs1={qs1}&qs1={qs2}")]
 XElement SomeRequest2(string qs1, string qs2);

メソッドを呼び出すと、実行時にエラーメッセージが表示されます。

クエリ文字列には、一意の名前を持つ「name=value」のペアが必要です。名前では大文字と小文字が区別されないことに注意してください。詳細については、UriTemplateのドキュメントを参照してください。

ゆるいグージーなインターフェースに頼ることなく、パラメーターの配列でリソースを公開するHTTPサービスをどのように定義しますか?

4

3 に答える 3

27

シンプルなカスタム QueryStringConverter を実装したので、qs1 を string[] にしてから、クエリ文字列変数をカンマ区切りにすることができます (例: http://server/service/SomeRequest?qs1=val1,val2,val3,val4 ) 。

[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Xml,
        UriTemplate = "SomeRequest?qs1={qs1}")]
XElement SomeRequest2(string[] qs1);

まず、カスタム QueryStringConverter を挿入できるように、WebHttpBehavior から継承するクラスが必要です。

public class CustomHttpBehavior : System.ServiceModel.Description.WebHttpBehavior
{
    protected override System.ServiceModel.Dispatcher.QueryStringConverter GetQueryStringConverter(System.ServiceModel.Description.OperationDescription operationDescription)
    {
        return new CustomQueryStringConverter();
    }
}

次に、string[] パラメータを処理する CustomQueryStringConverter:

public class CustomQueryStringConverter : System.ServiceModel.Dispatcher.QueryStringConverter
{
    public override bool CanConvert(Type type)
    {
        if (type == typeof(string[]))
        {
            return true;
        }

        return base.CanConvert(type);
    }

    public override object ConvertStringToValue(string parameter, Type parameterType)
    {
        if (parameterType == typeof(string[]))
        {
            string[] parms = parameter.Split(',');
            return parms;
        }

        return base.ConvertStringToValue(parameter, parameterType);
    }

    public override string ConvertValueToString(object parameter, Type parameterType)
    {
        if (parameterType == typeof(string[]))
        {
            string valstring = string.Join(",", parameter as string[]);
            return valstring;
        }

        return base.ConvertValueToString(parameter, parameterType);
    }
}

最後に、動作構成拡張機能を作成して、ランタイムが CustomWebHttpBehavior のインスタンスを取得できるようにする必要があります。

public class CustomHttpBehaviorExtensionElement : System.ServiceModel.Configuration.BehaviorExtensionElement
{
    protected override object CreateBehavior()
    {
        return new CustomHttpBehavior();
    }

    public override Type BehaviorType
    {
        get { return typeof(CustomHttpBehavior); }
    }
}

CustomWebHttpBehavior が使用されるように、要素を構成拡張機能に追加し<webHttp />ます。動作ではなく、その拡張機能の Name を使用します。

 <system.serviceModel>
   <services>
     <service name="NameSpace.ServiceClass">
       <endpoint address="" behaviorConfiguration="MyServiceBehavior"
        binding="webHttpBinding" contract="NameSpace.ServiceClass" />
     </service>
   </services>
  <behaviors>
   <endpointBehaviors>
    <behavior name="MyServiceBehavior">
      <customWebHttp/>
    </behavior>
   </endpointBehaviors>
  </behaviors>
  <extensions>
    <behaviorExtensions>
      <add name="customWebHttp" type="NameSpace.CustomHttpBehaviorExtensionElement, MyAssemblyName" />
    </behaviorExtensions>
  </extensions>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
 </system.serviceModel>

また、CustomQueryStringConverter を拡張して、null 許容値の型など、既定の型では処理できない他の型を処理できるようになりました。

注: このコードに直接関連するバグが microsoft connect に記録されています。このコードは、さまざまな型をクエリ変換しようとするほとんどすべての状況で実際には機能しません。

http://connect.microsoft.com/VisualStudio/feedback/details/616486/bug-with-getquerystringconverter-not-being-called-by-webservicehost#tabs

おそらく機能しないカスタム REST クエリ文字列コンバーターを作成するために時間を無駄にする前に、必ずこれを注意深くお読みください。(Framework 4.0 以下に適用されます)。

于 2008-12-10T01:21:01.350 に答える
5

私の他の答えに対するあなたのコメントに答えるには:

次のように、クエリ文字列の最後にワイルドカード パラメーターを使用できます。

[WebGet(ResponseFormat = WebMessageFormat.Xml,
        UriTemplate = "SomeRequest?qs1={*qs1}")]
XElement SomeRequest2(string qs1);

このようにして、qs1 文字列パラメーターは qs1= の後の生のクエリ文字列全体になり、コードで手動で解析できます。

QueryStringConverter はクエリ文字列のフォーマットに依存しているため、他の回答で行った小さなオーバーライドの代わりに QueryStringConverter を書き換えない限り、希望どおりに何かを行うことはできません。

MSDN から:

ワイルドカード セグメントは、次の規則に従う必要があります。

  • テンプレート文字列ごとに指定できるワイルドカード セグメントは最大 1 つです。
  • 名前付きワイルドカード セグメントは、パスの右端のセグメントにある必要があります。
  • 名前付きワイルドカード セグメントは、同じテンプレート文字列内の匿名ワイルドカード セグメントと共存できません。
  • 名前付きワイルドカード セグメントの名前は一意である必要があります。
  • 名前付きワイルドカード セグメントにデフォルト値を設定することはできません。
  • 名前付きワイルドカード セグメントは、「/」で終わることはできません。
于 2008-12-10T23:12:24.230 に答える
2

WCF 3.5 では、完全修飾アセンブリ名を次の場所に指定する必要があることに注意してください。

   <extensions>
    <behaviorExtensions>
      <add name="customWebHttp" type="NameSpace.CustomHttpBehaviorExtensionElement, MyAssemblyName, NOT SUFFICIENT HERE" />
    </behaviorExtensions>
  </extensions>

次のように: SampleService.CustomBehavior、SampleService、Version=1.0.0.0、Culture=neutral、PublicKeyToken=null

そうしないと、例外が発生します。

構成エラー
の説明: この要求を処理するために必要な構成ファイルの処理中にエラーが発生しました。以下の特定のエラーの詳細を確認し、構成ファイルを適切に変更してください。

パーサー エラー メッセージ: 構成の要素が無効です。拡張機能名 'CustomWebHttp' は、system.serviceModel/extensions/behaviorExtensions のコレクションに登録されていません。

于 2009-12-24T10:02:57.543 に答える