Formattazione di HTTP Web WCF

Il modello di programmazione HTTP Web WCF consente di determinare in modo dinamico il formato migliore in cui un'operazione di servizio debba restituire la risposta. Vengono supportati due metodi per determinare un formato appropriato: automatico ed esplicito.

Formattazione automatica

Se abilitata, la formattazione automatica sceglie il formato migliore nel quale verrà restituita la risposta, controllando gli elementi seguenti, in ordine:

  1. i tipi di supporto nell'intestazione Accept del messaggio di richiesta;

  2. il valore content-type del messaggio di richiesta;

  3. l'impostazione del formato predefinita nell'operazione;

  4. l'impostazione del formato predefinita in WebHttpBehavior.

Se il messaggio di richiesta contiene un'intestazione Accept, l'infrastruttura di Windows Communication Foundation (WCF) cerca un tipo supportato. Se l'intestazione Accept specifica le priorità per i propri tipi di supporto, queste vengono rispettate. Se non viene individuato alcun formato adatto nell'intestazione Accept, viene usato il valore content-type del messaggio di richiesta. Se non viene specificato alcun valore content-type adatto, viene usata l'impostazione del formato predefinita per l'operazione. Il formato predefinito viene impostato con il parametro ResponseFormat degli attributi WebGetAttribute e WebInvokeAttribute. Se non viene specificato alcun formato predefinito nell'operazione, viene usato il valore della proprietà DefaultOutgoingResponseFormat. La formattazione automatica si basa sulla proprietà AutomaticFormatSelectionEnabled. Quando questa proprietà è impostata su true, l'infrastruttura di WCF determina il formato migliore da usare. La selezione automatica del formato è disabilitata per impostazione predefinita per la compatibilità con le versioni precedenti. La selezione automatica del formato automatica può essere abilitata a livello di codice o tramite la configurazione. Nell'esempio seguente viene mostrato come abilitare la selezione automatica del formato nel codice.

// This code assumes the service name is MyService and the service contract is IMyContract
Uri baseAddress = new Uri("http://localhost:8000");  
  
WebServiceHost host = new WebServiceHost(typeof(MyService), baseAddress)  
try  
{  
   ServiceEndpoint sep = host.AddServiceEndpoint(typeof(IMyContract), new WebHttpBinding(), "");  
   // Check it see if the WebHttpBehavior already exists  
   WebHttpBehavior whb = sep.Behaviors.Find<WebHttpBehavior>();  
  
   if (whb != null)  
   {  
      whb.AutomaticFormatSelectionEnabled = true;  
   }  
   else  
   {  
      WebHttpBehavior webBehavior = new WebHttpBehavior();  
      webBehavior.AutomaticFormatSelectionEnabled = true;  
      sep.Behaviors.Add(webBehavior);  
   }  
         // Open host to start listening for messages  
   host.Open();
  
  // ...  
}  
  catch(CommunicationException ex)  
  {  
     Console.WriteLine("An exception occurred: " + ex.Message());  
  }  

La formattazione automatica può inoltre essere abilitata tramite la configurazione. È possibile impostare la proprietà AutomaticFormatSelectionEnabled direttamente nell'elemento WebHttpBehavior o mediante l'elemento WebHttpEndpoint. Nell'esempio seguente viene indicato come abilitare la selezione automatica del formato nell'elemento WebHttpBehavior.

<system.serviceModel>  
  <behaviors>  
    <endpointBehaviors>  
      <behavior>  
        <webHttp automaticFormatSelectionEnabled="true" />  
      </behavior>  
    </endpointBehaviors>  
  </behaviors>  
  <standardEndpoints>  
    <webHttpEndpoint>  
      <!-- the "" standard endpoint is used by WebServiceHost for auto creating a web endpoint. -->  
      <standardEndpoint name="" helpEnabled="true" />  
    </webHttpEndpoint>  
  </standardEndpoints>  
</system.serviceModel>  

Nell'esempio seguente viene mostrato come abilitare la selezione automatica del formato mediante WebHttpEndpoint.

<system.serviceModel>  
    <standardEndpoints>  
      <webHttpEndpoint>  
        <!-- the "" standard endpoint is used by WebServiceHost for auto creating a web endpoint. -->  
        <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"  />  
      </webHttpEndpoint>  
    </standardEndpoints>  
  </system.serviceModel>  

Formattazione esplicita

Come indicato nel nome, nella formattazione esplicita lo sviluppatore determina il formato migliore da usare all'interno del codice operativo. Se il formato migliore è XML o JSON, lo sviluppatore imposta Format su Xml o Json. Se la proprietà Format non è impostata in modo esplicito, viene usato il formato predefinito dell'operazione.

Nell'esempio seguente viene verificato il parametro della stringa di query di formato per un formato da usare. Se è stato specificato, viene impostato il formato dell'operazione mediante Format.

public class Service : IService  
{  
    [WebGet]  
     public string EchoWithGet(string s)  
    {  
        // if a format query string parameter has been specified, set the response format to that. If no such
        // query string parameter exists the Accept header will be used
        string formatQueryStringValue = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters["format"];  
        if (!string.IsNullOrEmpty(formatQueryStringValue))  
        {  
            if (formatQueryStringValue.Equals("xml", System.StringComparison.OrdinalIgnoreCase))  
            {
                WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Xml;
            }
            else if (formatQueryStringValue.Equals("json", System.StringComparison.OrdinalIgnoreCase))  
            {  
                WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Json;  
            }  
            else  
            {  
                throw new WebFaultException<string>($"Unsupported format '{formatQueryStringValue}'",   HttpStatusCode.BadRequest);
            }  
        }  
        return "You said " + s;  
    }  

Se è necessario supportare formati diversi da XML o JSON, definire l'operazione per ottenere un tipo restituito di Message. All'interno del codice operativo, determinare il formato appropriato da usare e creare quindi un oggetto Message usando uno dei metodi seguenti:

  • WebOperationContext.CreateAtom10Response

  • WebOperationContext.CreateJsonResponse

  • WebOperationContext.CreateStreamResponse

  • WebOperationContext.CreateTextResponse

  • WebOperationContext.CreateXmlResponse

Ognuno di questi metodi usa il contenuto e crea un messaggio con il formato appropriato. Il metodo WebOperationContext.Current.IncomingRequest.GetAcceptHeaderElements può essere usato per ottenere un elenco di formati preferiti dal client in ordine di preferenza decrescente. Nell'esempio seguente viene indicato come usare WebOperationContext.Current.IncomingRequest.GetAcceptHeaderElements per determinare il formato da usare e viene quindi impiegato il metodo di risposta di creazione appropriato per creare il messaggio di risposta.

public class Service : IService  
{  
    public Message EchoListWithGet(string list)  
    {  
        List<string> returnList = new List<string>(list.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));  
        IList<ContentType> acceptHeaderElements = WebOperationContext.Current.IncomingRequest.GetAcceptHeaderElements();  
        for (int x = 0; x < acceptHeaderElements.Count; x++)  
        {  
            string normalizedMediaType = acceptHeaderElements[x].MediaType.ToLowerInvariant();  
            switch (normalizedMediaType)  
            {  
                case "image/jpeg": return CreateJpegResponse(returnList);  
                case "application/xhtml+xml": return CreateXhtmlResponse(returnList);  
                case "application/atom+xml": return CreateAtom10Response(returnList);  
                case "application/xml": return CreateXmlResponse(returnList);  
                case "application/json": return CreateJsonResponse(returnList);  
          }  
    }  
  
    // Default response format is XML  
    return CreateXmlResponse(returnList);  
    }  
}  

Vedi anche