У меня есть другое решение, которое работает на противоположной стороне от @Marc Gravell: вместо дублирования контракта, извлекаем 2 разных класса из службы реализация . Это просто псевдонимы типов; они необходимы, потому что система активации WCF (как минимум в IIS) не позволит вам активировать один и тот же тип сервиса на разных URL-адресах (я не уверен, почему решение Gravell не столкнулось с этой проблемой - ошибка, которую я «У меня уже есть регистрация для URI ...», когда я пытаюсь активировать один и тот же класс обслуживания по разным URL на одном сайте). Обратите внимание, что это проблема, только если вы хотите запустить один и тот же сервис с pox и json одновременно . Если все, что вам нужно, это контролировать формат ответа, этот обходной путь вам не нужен.
Ключевой концепцией моего решения является использование 2 разных URI для одной и той же службы, а затем использование поведения конечной точки для установки формата исходящего ответа по умолчанию. Вы можете узнать больше в этом вопросе , который также затрагивает концептуальную чистоту вопроса: должны ли мы использовать атрибуты контракта для указания свойств, которые являются частью сетевого протокола? Я думаю, что подход Марка Гравелла к этой проблеме сам по себе действителен, но он не соответствует первоначальной концепции WCF, в которой контракты должны быть абстрагированы от стека протоколов. Но поведение конечных точек не позволит вам указать все атрибуты, связанные с REST, вам придется использовать атрибуты для шаблонов URI и входящего формата.
Может ли REST быть реализован иначе? Хотя дизайнеры WCF отлично поработали над созданием универсальной структуры, я не думаю, что они увидели, что REST появится. Некоторые вещи, такие как шаблон URI, действительно, похоже, относятся к контракту.
Хватит говорить! Вот код Сначала файл web.config. Здесь происходит волшебство. Обратите внимание, что в этом примере я использую активацию на основе конфигурации WCF 4, но вы также можете выполнить то же самое, имея 2 файла SVC для представления 2 URI.
<?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
{}
}
Если бы не необходимость псевдонимов типов, я бы сказал, что это полное решение. Это полное решение, если вы не хотите поддерживать несколько форматов одновременно. Это превосходит решение с несколькими контрактами в том отношении, что, поскольку существует только один контракт, вам не нужно синхронизировать 2 контракта.