Formatowanie protokołu HTTP sieci Web WCF
Model programowania HTTP sieci Web WCF umożliwia dynamiczne określenie najlepszego formatu operacji usługi w celu zwrócenia odpowiedzi. Obsługiwane są dwie metody określania odpowiedniego formatu: automatyczne i jawne.
Automatyczne formatowanie
Po włączeniu automatyczne formatowanie wybiera najlepszy format, w którym ma być zwracana odpowiedź. Określa najlepszy format, sprawdzając następujące elementy w następującej kolejności:
Nośniki są typami w nagłówku Accept wiadomości żądania.
Typ zawartości komunikatu żądania.
Domyślne ustawienie formatu w operacji.
Domyślne ustawienie formatu w aplikacji WebHttpBehavior.
Jeśli komunikat żądania zawiera nagłówek Accept, infrastruktura programu Windows Communication Foundation (WCF) wyszukuje typ, który obsługuje. Accept
Jeśli nagłówek określa priorytety typów multimediów, są one honorowane. Jeśli w nagłówku nie znaleziono odpowiedniego Accept
formatu, zostanie użyty typ zawartości komunikatu żądania. Jeśli nie określono odpowiedniego typu zawartości, zostanie użyte domyślne ustawienie formatu operacji. Domyślny format jest ustawiany przy użyciu ResponseFormat
parametru WebGetAttribute i WebInvokeAttribute atrybutów. Jeśli w operacji nie określono żadnego domyślnego DefaultOutgoingResponseFormat formatu, zostanie użyta wartość właściwości. Automatyczne formatowanie opiera się na AutomaticFormatSelectionEnabled właściwości . Gdy ta właściwość jest ustawiona na true
wartość , infrastruktura WCF określa najlepszy format do użycia. Automatyczne zaznaczanie formatu jest domyślnie wyłączone w celu zapewnienia zgodności z poprzednimi wersjami. Automatyczne wybieranie formatu można włączyć programowo lub za pomocą konfiguracji. W poniższym przykładzie pokazano, jak włączyć automatyczne wybieranie formatu w kodzie.
// 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());
}
Automatyczne formatowanie można również włączyć za pomocą konfiguracji. Właściwość można ustawić AutomaticFormatSelectionEnabled bezpośrednio na WebHttpBehavior obiekcie lub przy użyciu elementu WebHttpEndpoint. W poniższym przykładzie pokazano, jak włączyć wybór automatycznego formatu w pliku 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>
W poniższym przykładzie pokazano, jak włączyć automatyczne wybieranie formatu przy użyciu polecenia 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>
Jawne formatowanie
Jak wskazuje nazwa, w jawnym formatowaniu deweloper określa najlepszy format do użycia w kodzie operacji. Jeśli najlepszym formatem jest XML lub JSON, deweloper ustawia Format wartość Xml lub Json. Format Jeśli właściwość nie jest jawnie ustawiona, zostanie użyty domyślny format operacji.
Poniższy przykład sprawdza parametr ciągu zapytania formatu dla formatu do użycia. Jeśli został określony, ustawia format operacji przy użyciu polecenia 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;
}
Jeśli musisz obsługiwać formaty inne niż XML lub JSON, zdefiniuj operację tak, aby miała zwracany typ Message. W kodzie operacji określ odpowiedni format do użycia, a następnie utwórz Message obiekt przy użyciu jednej z następujących metod:
WebOperationContext.CreateAtom10Response
WebOperationContext.CreateJsonResponse
WebOperationContext.CreateStreamResponse
WebOperationContext.CreateTextResponse
WebOperationContext.CreateXmlResponse
Każda z tych metod przyjmuje zawartość i tworzy komunikat z odpowiednim formatem. Metoda WebOperationContext.Current.IncomingRequest.GetAcceptHeaderElements
może służyć do pobierania listy formatów preferowanych przez klienta w kolejności malejącej preferencji. W poniższym przykładzie pokazano, jak użyć WebOperationContext.Current.IncomingRequest.GetAcceptHeaderElements
metody określania formatu do użycia, a następnie używa odpowiedniej metody tworzenia odpowiedzi w celu utworzenia komunikatu odpowiedzi.
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);
}
}