Форматирование ВЕБ-HTTP WCF
Модель веб-программирования HTTP WCF позволяет динамически определять лучший формат возвращаемого ответа операции службы. Поддерживается два метода для определения формата: автоматический и явный.
Автоматическое форматирование
Если выбран этот метод, автоматическое форматирование выбирает наилучший формат возврата ответа. Наилучший формат определяется путем проверки в следующем порядке.
Типы носителей в заголовке Accept сообщения запроса.
Тип содержимого сообщения запроса.
Параметр формата по умолчанию в операции.
Параметр формата по умолчанию в WebHttpBehavior.
Если сообщение запроса содержит заголовок Accept, инфраструктура Windows Communication Foundation (WCF) ищет тип, который он поддерживает. Если заголовок Accept
указывает приоритеты типов носителей, то они учитываются. Если в заголовке Accept
не найден подходящий формат, используется тип содержимого сообщения запроса. Если не указан подходящий тип содержимого, используется параметр формата по умолчанию для операции. Формат по умолчанию задается с помощью параметра ResponseFormat
атрибутов WebGetAttribute и WebInvokeAttribute. Если не указан формат по умолчанию для операции, используется значение свойства DefaultOutgoingResponseFormat. Автоматическое форматирование основано на свойстве AutomaticFormatSelectionEnabled. Если это свойство имеет значение true
, то инфраструктура WCF определяет лучший формат для использования. Автоматический выбор формата отключен по умолчанию в целях обратной совместимости. Автоматический выбор формата можно включить программно или через конфигурацию. В следующем примере показано включение автоматического выбора формата в коде.
// 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());
}
Автоматический выбор формата также можно включить через конфигурацию. Можно задать свойство AutomaticFormatSelectionEnabled напрямую в WebHttpBehavior или с помощью WebHttpEndpoint. В следующем примере показано включение автоматического выбора формата в 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>
В следующем примере показано включение автоматического выбора формата с помощью 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>
Явное форматирование
Как следует из названия, в явном форматировании разработчик определяет наилучший формат для использования внутри кода операции. Если лучшим форматом является формат XML или JSON, разработчик устанавливает Format в формат Xml либо Json. Если свойство Format явно не задано, то используется формат операции по умолчанию.
В следующем примере для определения формата, который нужно использовать, проверяется параметр строки запроса формата. Если этот параметр был указан, формат операции задается свойством 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;
}
Если необходимо поддерживать форматы, отличающиеся от XML или JSON, операцию нужно определить таким образом, чтобы она возвращала тип Message. Внутри кода операции определите соответствующий формат для использования и создайте объект Message с помощью одного из следующих методов:
WebOperationContext.CreateAtom10Response
WebOperationContext.CreateJsonResponse
WebOperationContext.CreateStreamResponse
WebOperationContext.CreateTextResponse
WebOperationContext.CreateXmlResponse
Каждый из этих методов принимает содержимое и создает сообщение соответствующего формата. Метод WebOperationContext.Current.IncomingRequest.GetAcceptHeaderElements
можно использовать для получения списка форматов, предпочитаемых клиентом в порядке снижения предпочтения. В следующем примере показано применение WebOperationContext.Current.IncomingRequest.GetAcceptHeaderElements
для определения используемого формата, а затем используется соответствующий метод создания ответа для создания ответного сообщения.
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);
}
}