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