@Marc Gravell の反対側で機能する別のソリューションがあります。契約を複製する代わりに、サービス実装から 2 つの異なるクラスを派生させます。これらは単なる型エイリアスです。WCF アクティベーション システム (少なくとも IIS では) では、異なる URL で同じサービス タイプをアクティベートできないため、それらが必要です (Gravell のソリューションでこの問題が発生しなかった理由がわかりません。同じサイトの別の URL で同じサービス クラスをアクティブにしようとすると、"A registration already exists for URI..." と表示されます)。これは、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 つのコントラクトを同期させる必要がないという点で、複数のコントラクト ソリューションよりも優れています。