2009-03-18 2 views
6

Для того, чтобы получить услугу WCF работы с JQuery я добавил атрибут WebInvoke по договору операции для управления сериализации JSON следующим образом:Может WebInvoke атрибуты быть заменены связывания конфигураций

[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)] 

Есть ли способ для управления этой сериализацией через привязки сервисов в конфигурации вместо этого, поскольку это ограничивает эту службу от предоставления различных сериализаций различным конечным точкам.

ответ

5

У меня есть другое решение, которое работает на противоположном конце от @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 
    {} 
} 

Если бы не было необходимости псевдонимами типа , Я бы сказал, что это полное решение. Это полное решение, если вы не хотите поддерживать несколько форматов одновременно. Это превосходит решение нескольких контрактов в том отношении, что, поскольку существует только один контракт, вам не нужно синхронизировать два контракта.

+0

Фантастический ответ! –

Смежные вопросы