2009-11-17 3 views
17

J'ai un contrat de service décrivant une méthode utilisée dans un service WCF. La méthode a un attribut WebGet qui définit un UriTemplate et un ResponseFormat.Est-ce qu'un attribut WebGet de la méthode WCF OperationContract peut avoir plusieurs types ResponseFormat?

Je souhaite réutiliser une seule méthode et avoir plusieurs attributs WebGet avec des UriTemplates différents et des ResponseFormats différents. Fondamentalement, j'espère éviter d'avoir plusieurs méthodes juste pour différencier des choses comme le type de retour étant XML vs JSON. Dans tous les exemples que j'ai vus jusqu'à présent, je suis cependant obligé de créer une méthode différente pour chaque attribut WebGet. Voici un exemple OperationContract

[ServiceContract] 
public interface ICatalogService 
{ 
    [OperationContract] 
    [WebGet(UriTemplate = "product/{id}/details?format=xml", ResponseFormat = WebMessageFormat.Xml)] 
    Product GetProduct(string id); 

    [OperationContract] 
    [WebGet(UriTemplate = "product/{id}/details?format=json", ResponseFormat = WebMessageFormat.Json)] 
    Product GetJsonProduct(string id); 
} 

En utilisant l'exemple ci-dessus, je voudrais utiliser la méthode getProduct pour les deux types de xml et retour JSON comme celui-ci:

[ServiceContract] 
public interface ICatalogService 
{ 
    [OperationContract] 
    [WebGet(UriTemplate = "product/{id}/details?format=xml", ResponseFormat = WebMessageFormat.Xml)] 
    [WebGet(UriTemplate = "product/{id}/details?format=json", ResponseFormat = WebMessageFormat.Json)] 
    Product GetProduct(string id); 
} 

est-il un moyen d'y parvenir si Je ne suis pas coincé écrire différentes méthodes juste pour retourner différents ResponseFormats?

Merci!

Répondre

12

Vous pouvez le faire

[ServiceContract] 
public interface ICatalogService 
{ 
    [OperationContract] 
    [WebGet(UriTemplate = "product/{id}/details?format={format}")] 
    Stream GetProduct(string id, string format); 
} 

Et puis dans votre code sérialisation poignée en fonction de la valeur indiquée sur le paramètre.

Pour XML, écrivez une méthode d'assistance qui gère votre sérialisation.

public static Stream GetServiceStream(string format, string callback, DataTable dt, SyndicationFeed sf) 
     { 
      MemoryStream stream = new MemoryStream(); 
      StreamWriter writer = new StreamWriter(stream, Encoding.UTF8); 
      if (format == "xml") 
      { 
       XmlSerializer xmls = new XmlSerializer(typeof(DataTable)); 
       xmls.Serialize(writer, dt); 
       WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml"; 
      } 
      else if (format == "json") 
      { 
       var toJSON = new JavaScriptSerializer(); 
       toJSON.RegisterConverters(new JavaScriptConverter[] { new JavaScriptDataTableConverter() }); 
       writer.Write(toJSON.Serialize(dt)); 
       WebOperationContext.Current.OutgoingResponse.ContentType = "text/json"; 
      } 
      else if (format == "jsonp") 
      { 
       var toJSON = new JavaScriptSerializer(); 
       toJSON.RegisterConverters(new JavaScriptConverter[] { new JavaScriptDataTableConverter() }); 
       writer.Write(callback + "(" + toJSON.Serialize(dt) + ");"); 
       WebOperationContext.Current.OutgoingResponse.ContentType = "text/json"; 
      } 
      else if (format == "rss") 
      { 
       XmlWriter xmlw = new XmlTextWriter(writer); 
       sf.SaveAsRss20(xmlw); 
       WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml"; 
      } 
      else if (format == "atom") 
      { 
       XmlWriter xmlw = new XmlTextWriter(writer); 
       sf.SaveAsAtom10(xmlw); 
       WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml"; 
      } 
      else 
      { 
       writer.Write("Invalid formatting specified."); 
       WebOperationContext.Current.OutgoingResponse.ContentType = "text/html"; 
      } 

      writer.Flush(); 
      stream.Position = 0; 
      return stream; 
     } 
} 
8

Si je me souviens bien, au-dessous méthode a fonctionné pour moi:

contrat pour le service JSON:

[ServiceContract] 
public interface IServiceJson { 
    [OperationContract()] 
    [WebGet(UriTemplate = "Operation/?param={param}", 
         ResponseFormat = WebMessageFormat.Json)] 
    ReturnType Operation(string param); 
} 

Contact pour le service xml:

[ServiceContract] 
public interface IServiceXml { 
    [OperationContract(Name = "OperationX")] 
    [WebGet(UriTemplate = "Operation/?param={param}", 
         ResponseFormat = WebMessageFormat.Xml)] 
    ReturnType Operation(string param); 
} 

mise en œuvre à la fois:

public class ServiceImplementation : IServiceJson, IServiceXml { 
    ReturnType Operation(string param) { 
    // Implementation 
    } 
} 

et la configuration web.config (points d'extrémité de notes pour les réponses JSON et XML):

<system.serviceModel> 
    <behaviors> 
     <endpointBehaviors> 
     <behavior name="webHttp"> 
      <webHttp /> 
     </behavior> 
     </endpointBehaviors> 
     <serviceBehaviors> 
     <behavior name="serviceBehaviour"> 
      <serviceMetadata httpGetEnabled="true" /> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <services> 
     <service behaviorConfiguration="serviceBehaviour" name="ServiceImplementation"> 
     <endpoint address="json/" behaviorConfiguration="webHttp" binding="webHttpBinding" 
     bindingConfiguration="webHttpBindingSettings" contract="IServiceJson"> 
      <identity> 
      <dns value="localhost" /> 
      </identity> 
     </endpoint> 
     <endpoint address="xml/" behaviorConfiguration="webHttp" binding="webHttpBinding" 
     bindingConfiguration="webHttpBindingSettings" contract="IServiceXml"> 
      <identity> 
      <dns value="localhost" /> 
      </identity> 
     </endpoint> 
     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 
     </service> 
    </services> 
    <bindings> 
     <webHttpBinding> 
     <binding name="webHttpBindingSettings"> 
      <readerQuotas maxStringContentLength="5000000"/> 
     </binding> 
     </webHttpBinding> 
    </bindings> 
    </system.serviceModel> 

Maintenant, vous pouvez appeler votre service comme celui-ci: réponse JSON: http://yourServer/json/Operation/?param=value réponse xml: http://yourServer/xml/Operation/?param=value

(Désolé s'il y a des bogues dans le code ci-dessus, je ne l'ai pas exécuté pour la vérification).

Questions connexes