Можно ли заменить атрибуты WebInvoke конфигурациями привязки

StackOverflow https://stackoverflow.com/questions/658195

  •  19-08-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top