2009-03-18 14 views
6

Al fine di ottenere un servizio WCF lavorare con JQuery Ho aggiunto un attributo WebInvoke sul contratto operazione per controllare la serializzazione JSON come segue:Può WebInvoke attributi essere sostituite da configurazioni di legame

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

Esiste un modo per controllare questa serializzazione tramite i binding di servizio nella configurazione, poiché limita questo servizio dalla fornitura di serializzazioni diverse a endpoint diversi.

risposta

5

Ho una soluzione diversa, che funziona all'estremità opposta di @Marc Gravell: invece di duplicare il contratto, derivare 2 classi diverse dall'implementazione del servizio . Questi sono solo tipi di alias; sono necessari perché il sistema di attivazione WCF (come minimo su IIS) non consente di attivare lo stesso tipo di servizio su URL diversi (non sono sicuro del motivo per cui la soluzione di Gravell non ha incontrato questo problema - l'errore che sono ottenere è "Esiste già una registrazione per URI ..." quando provo ad attivare la stessa classe di servizio su URL diversi sullo stesso sito). Si noti che questo è solo un problema se si desidera eseguire lo stesso servizio con pox e json contemporaneamente. Se tutto ciò che vuoi è controllare il formato della risposta, non hai bisogno di questa soluzione alternativa.

Il concetto chiave alla base della mia soluzione consiste nell'utilizzare 2 diversi URI per lo stesso servizio, quindi utilizzare un comportamento dell'endpoint per impostare il formato di risposta in uscita predefinito. Puoi scoprire di più su this question, che tocca anche la purezza concettuale della domanda: dovremmo usare gli attributi del contratto per specificare le proprietà che fanno parte del protocollo di rete? Penso che il punto di vista di Marc Gravell su questo tema sia di per sé valido, ma non è coerente il concetto originale di WCF, in cui i contratti dovrebbero essere astratti lontano dallo stack del protocollo. Ma i comportamenti degli endpoint non ti consentono di specificare tutti gli attributi relativi a REST, dovrai utilizzare gli attributi per i modelli URI e il formato in entrata.

È possibile che REST sia stato implementato in modo diverso? Sebbene i progettisti di WCF abbiano fatto un ottimo lavoro nel progettare un framework generico, non penso che abbiano visto REST arrivare. Alcune cose, come il modello URI, sembrano davvero appartenere al contratto.

Basta parlare! Ecco il codice. Innanzitutto il file web.config. Qui è dove avviene la magia. Nota che sto usando l'attivazione basata sulla configurazione di WCF 4 in questo esempio, ma potresti anche ottenere lo stesso risultato avendo due file svc per rappresentare i 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> 

Ed ecco il codice, tra cui contratto di servizio, implementazione del servizio, e gli alias di tipo che sono necessarie per fare questo lavoro:

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

Se non fosse per la necessità degli alias di tipo , Direi che questa è una soluzione completa. È una soluzione completa se non si desidera supportare più formati contemporaneamente. Questo è superiore alla soluzione a contratto multiplo nel rispetto del fatto che, poiché esiste un solo contratto, non è necessario mantenere sincronizzati i 2 contratti.

+0

Risposta fantastica! –

Problemi correlati