2009-03-18 7 views
6

Afin d'obtenir un service de WCF travailler avec JQuery J'ai ajouté un attribut WebInvoke sur le contrat d'exploitation pour contrôler la sérialisation JSON comme suit:Peut-WebInvoke attributs remplacés par des configurations de liaison

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

est-il un moyen pour contrôler cette sérialisation via les liaisons de service dans la configuration à la place car cela limite ce service de fournir différentes sérialisations à différents points de terminaison.

Répondre

5

J'ai une solution différente, qui fonctionne à l'opposé de @Marc Gravell: au lieu de dupliquer le contrat, dériver 2 classes différentes du service l'implémentation. Ce ne sont que des alias de type; ils sont nécessaires parce que le système d'activation WCF (au moins sur IIS) ne vous permettra pas d'activer le même type de service à différentes URLs (je ne sais pas pourquoi la solution de Gravell n'a pas rencontré ce problème - l'erreur que je suis get est "Une inscription existe déjà pour URI ..." lorsque j'essaie d'activer la même classe de service à différentes URL sur le même site). Notez que ceci est seulement un problème si vous voulez exécuter le même service avec pox et json simultanément. Si tout ce que vous voulez est de contrôler le format de réponse, vous n'avez pas besoin de cette solution de contournement.

Le concept clé de ma solution consiste à utiliser deux URI différents pour le même service, puis à utiliser un comportement de point de terminaison pour définir le format de réponse sortant par défaut. Vous pouvez en savoir plus dans this question, qui aborde également la question de la pureté conceptuelle: devrions-nous utiliser des attributs de contrat pour spécifier les propriétés qui font partie du protocole réseau? Je pense que le point de vue de Marc Gravell sur cette question est valide en soi, mais il n'est pas cohérent avec le concept original de WCF, dans lequel les contrats sont censés être retirés de la pile protocolaire. Mais les comportements de point de terminaison ne vous permettront pas de spécifier tous les attributs liés à REST, vous devrez utiliser les attributs pour les modèles d'URI et le format entrant.

Est-ce que REST aurait pu être implémenté différemment? Bien que les concepteurs de WCF aient fait un excellent travail de conception d'un framework générique, je ne pense pas qu'ils aient vu REST venir. Certaines choses, comme le modèle URI, semblent vraiment faire partie du contrat.

Assez parlé! Voici le code. D'abord le fichier web.config. C'est là que la magie se produit. Notez que j'utilise l'activation basée sur la configuration de WCF 4 dans cet exemple, mais vous pouvez également accomplir la même chose en ayant 2 fichiers svc pour représenter les 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> 

Et voici le code, y compris contrat de service, la mise en œuvre de services et les alias de type qui sont nécessaires pour faire ce travail:

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

S'il n'y avait pas la nécessité des alias de type , Je dirais que c'est une solution complète. C'est une solution complète si vous ne voulez pas prendre en charge plusieurs formats simultanément. Ceci est supérieur à la solution de contrat multiple dans le respect que, puisqu'il n'y a qu'un seul contrat, vous n'avez pas besoin de garder les 2 contrats en synchronisation.

+0

Une réponse fantastique! –

Questions connexes