WebInvoke属性をバインディング構成で置き換えることができますか
-
19-08-2019 - |
質問
JQueryで動作するWCFサービスを取得するために、操作コントラクトにWebInvoke属性を追加して、次のようにJSONシリアル化を制御します。
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
このサービスは異なるシリアル化を異なるエンドポイントに提供することを制限するため、代わりにconfigのサービスバインディングを介してこのシリアル化を制御する方法があります。
解決
@Marc Gravellの反対側で機能する別のソリューションがあります。契約を複製する代わりに、サービスから2つの異なるクラスを派生させます実装。これらは単なる型エイリアスです。 WCFアクティベーションシステム(少なくともIIS上)では異なるURLで同じサービスタイプをアクティベートできないため、これらが必要です(Gravellのソリューションがこの問題に遭遇しなかった理由はわかりません-私は取得は<!> quot; URIの登録は既に存在しています... <!> quot;同じサイトの異なるURLで同じサービスクラスをアクティブにしようとすると)。これは、poxとjsonで同じサービスを同時に実行したい場合にのみ問題であることに注意してください。応答形式を制御するだけであれば、この回避策は不要です。
私のソリューションの背後にある重要な概念は、同じサービスに対して2つの異なるURIを使用し、エンドポイントの動作を使用してデフォルトのアウトバウンドレスポンス形式を設定することです。詳細については、この質問をご覧ください。質問の概念的な純度についても触れています。ネットワークプロトコルの一部であるプロパティを指定するためにコントラクト属性を使用する必要がありますか?この問題に対するMarc Gravellの見解はそれ自体有効であると思いますが、プロトコルスタックから抽象化されるコントラクトが想定されているWCFの元のコンセプトとは一致していません。ただし、エンドポイントの動作ではすべてのREST関連の属性を指定することはできません。URIテンプレートおよびインバウンド形式の属性を使用する必要があります。
RESTは別の方法で実装できましたか? WCFの設計者は汎用フレームワークの設計で優れた仕事をしましたが、RESTが登場するとは思わないでしょう。 URIテンプレートのように、実際には契約に属しているようです。
十分な話です!コードは次のとおりです。まずweb.configファイル。これは魔法が起こるところです。この例では、WCF 4構成ベースのアクティベーションを使用していますが、2つのURIを表す2つのsvcファイルを使用して同じことを実現することもできます。
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="StackOverflow.QuoteOfTheDayAsJson">
<endpoint binding="webHttpBinding" contract="StackOverflow.IQuoteOfTheDay"
behaviorConfiguration="jsonBehavior" />
</service>
<service name="StackOverflow.QuoteOfTheDayAsPox">
<endpoint binding="webHttpBinding" contract="StackOverflow.IQuoteOfTheDay"
behaviorConfiguration="poxBehavior" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp defaultOutgoingResponseFormat="Json" />
</behavior>
<behavior name="poxBehavior">
<webHttp defaultOutgoingResponseFormat="Xml"/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="false">
<serviceActivations>
<add relativeAddress="QuoteOfTheDayJson.svc"
service="StackOverflow.QuoteOfTheDayAsJson"/>
<add relativeAddress="QuoteOfTheDayPox.svc"
service="StackOverflow.QuoteOfTheDayAsPox"/>
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
</configuration>
そして、これはサービス契約、サービス実装、およびこの作業を行うために必要な型エイリアスを含むコードです:
namespace StackOverflow
{
[DataContract]
public class Quotation
{
[DataMember]
public string Text { get; set; }
[DataMember]
public string Author { get; set; }
}
[ServiceContract]
public interface IQuoteOfTheDay
{
[OperationContract]
[WebInvoke(Method="GET", UriTemplate="GetTodaysQuote")]
Quotation GetTodaysQuote();
}
public class QuoteOfTheDayImp : IQuoteOfTheDay
{
public Quotation GetTodaysQuote()
{
return new Quotation()
{
Text = "Sometimes it's better to appologize for not asking permission",
Author = "Admiral Grace Murray Hopper"
};
}
}
/// <summary>
/// A type alias used for json activation
/// </summary>
public class QuoteOfTheDayAsJson : QuoteOfTheDayImp
{}
/// <summary>
/// A type alias used for pox activation
/// </summary>
public class QuoteOfTheDayAsPox : QuoteOfTheDayImp
{}
}
型エイリアスの必要性がなければ、これは完全なソリューションだと思います。複数のフォーマットを同時にサポートしたくない場合、これは完全なソリューションです。これは、契約が1つしかないため、2つの契約の同期を維持する必要がないという点で、複数の契約ソリューションよりも優れています。