¿Se pueden reemplazar los atributos de WebInvoke por configuraciones de enlace?

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

  •  19-08-2019
  •  | 
  •  

Pregunta

Para que un servicio WCF funcione con JQuery, he agregado un atributo WebInvoke en el contrato de operación para controlar la serialización JSON de la siguiente manera:

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

¿Hay alguna manera de controlar esta serialización a través de los enlaces de servicio en la configuración, ya que limita que este servicio proporcione diferentes serializaciones a diferentes puntos finales?

¿Fue útil?

Solución

Tengo una solución diferente, que funciona en el extremo opuesto al de @Marc Gravell: en lugar de duplicar el contrato, deriva 2 clases diferentes del servicio implementación . Estos son solo alias de tipo; son necesarios porque el sistema de activación WCF (como mínimo en IIS) no le permitirá activar el mismo tipo de servicio en diferentes URLS (no estoy seguro de por qué la solución de Gravell no se encontró con este problema; el error es que estoy obtener es "Ya existe un registro para URI ..." cuando trato de activar la misma clase de servicio en diferentes URL en el mismo sitio). Tenga en cuenta que esto solo es un problema si desea ejecutar el mismo servicio con pox y json simultáneamente . Si todo lo que desea es controlar el formato de respuesta, no necesita esta solución.

El concepto clave detrás de mi solución es usar 2 URI diferentes para el mismo servicio, luego usar un comportamiento de punto final para establecer el formato de respuesta saliente predeterminado. Puede obtener más información en esta pregunta , que también toca la pregunta pureza conceptual: ¿Deberíamos usar atributos de contrato para especificar propiedades que son parte del protocolo de red? Creo que la opinión de Marc Gravell sobre este tema es válida per se, pero no es coherente con el concepto original de WCF, en el que se supone que los contratos deben abstraerse de la pila de protocolos. Pero los comportamientos de punto final no le permitirán especificar todos los atributos relacionados con REST, tendrá que usar los atributos para las plantillas de URI y el formato de entrada.

¿Podría REST haber sido implementado de manera diferente? Aunque los diseñadores de WCF hicieron un excelente trabajo al diseñar un marco genérico, no creo que hayan visto venir REST. Algunas cosas, como la plantilla de URI, realmente parecen pertenecer al contrato.

¡Basta de hablar! Aquí está el código. Primero el archivo web.config. Aquí es donde sucede la magia. Tenga en cuenta que estoy usando la activación basada en la configuración de WCF 4 en este ejemplo, pero también podría lograr lo mismo al tener 2 archivos svc para representar los 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>

Y aquí está el código, incluido el contrato de servicio, la implementación del servicio y los alias de tipo que son necesarios para que esto funcione:

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
    {}
}

Si no fuera por la necesidad de los alias de tipo, diría que esta es una solución completa. Es una solución completa si no desea admitir múltiples formatos simultáneamente. Esto es superior a la solución de contratos múltiples en el sentido de que, dado que solo hay un contrato, no necesita mantener los 2 contratos sincronizados.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top