WCF ResponseFormat для WebGet

WCF предлагает два варианта атрибута ResponseFormat в annotations WebGet в ServiceContract.

[ServiceContract] public interface IService1 { [OperationContract] [WebGet(UriTemplate = "greet/{value}", BodyStyle = WebMessageBodyStyle.Bare)] string GetData(string value); [OperationContract] [WebGet(UriTemplate = "foo", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)] string Foo(); 

Параметры ResponseFormat – это WebMessageFormat.Json и WebMessageFormat.Xml. Возможно ли написать собственный формат веб-сообщений? Мне бы хотелось, чтобы при вызове метода foo () клиент получал необработанную строку – без json или xml-оберток.

WebGetAttribute отправляется Microsoft, и я не думаю, что вы можете расширить WebMessageFormat . Однако вы могли бы расширить WebHttpBinding который использует WebGetAttribute . Вы можете добавить свой собственный атрибут

 [WebGet2(UriTemplate = "foo", ResponseFormat = WebMessageFormat2.PlainText)] string Foo(); 

В общем, настройка макета сообщения в WCF называется настраиваемым кодировщиком / кодированием сообщений. Microsoft предоставляет пример: Custom Encoder Encoder: Compression Encoder . Кроме того, другие распространенные люди расширения – это расширение поведения для добавления пользовательской обработки ошибок, поэтому вы можете найти какой-то пример в этом направлении.

Попробуйте использовать

 BodyStyle = WebMessageBodyStyle.Bare 

Затем верните System.IO.Stream из вашей функции.

Вот код, который я использую для возврата изображения из базы данных, но доступного через URL-адрес:

 [OperationContract()] [WebGet(UriTemplate = "Person/{personID}/Image", BodyStyle = WebMessageBodyStyle.Bare)] System.IO.Stream GetImage(string personID); 

Реализация:

 public System.IO.Stream GetImage(string personID) { // parse personID, call DB OutgoingWebResponseContext context = WebOperationContext.Current.OutgoingResponse; if (image_not_found_in_DB) { context.StatusCode = System.Net.HttpStatusCode.Redirect; context.Headers.Add(System.Net.HttpResponseHeader.Location, url_of_a_default_image); return null; } // everything is OK, so send image context.Headers.Add(System.Net.HttpResponseHeader.CacheControl, "public"); context.ContentType = "image/jpeg"; context.LastModified = date_image_was_stored_in_database; context.StatusCode = System.Net.HttpStatusCode.OK; return new System.IO.MemoryStream(buffer_containing_jpeg_image_from_database); } 

В вашем случае, чтобы вернуть необработанную строку, установите ContentType как нечто вроде «text / plain» и верните ваши данные в виде streamа. В предположении, что-то вроде этого:

 return new System.IO.MemoryStream(ASCIIEncoding.Default.GetBytes(string_to_send)); 

Я применил этот атрибут так, возможно, это поможет кому-то в будущем:

 [AttributeUsage(AttributeTargets.Method)] public class WebGetText : Attribute, IOperationBehavior { public void Validate(OperationDescription operationDescription) { } public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { dispatchOperation.Formatter = new Formatter(dispatchOperation.Formatter); } public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { } public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { } } public class Formatter : IDispatchMessageFormatter { IDispatchMessageFormatter form; public Formatter (IDispatchMessageFormatter form) { this.form = form; } public void DeserializeRequest(Message message, object[] parameters) { form.DeserializeRequest(message, parameters) } public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result) { IEnumerable cl = (IEnumerable)result; StringBuilder csvdata = new StringBuilder(); foreach (object userVariableClass in cl) { Type type = userVariableClass.GetType(); PropertyInfo[] fields = type.GetProperties(); // Dim header As String = String.Join(";", fields.Select(Function(f) f.Name + ": " + f.GetValue(userVariableClass, Nothing).ToString()).ToArray()) // csvdata.AppendLine("") // csvdata.AppendLine(header) csvdata.AppendLine(ToCsvFields(";", fields, userVariableClass)); csvdata.AppendLine(""); csvdata.AppendLine("=====EOF====="); csvdata.AppendLine(""); } Message msg = WebOperationContext.Current.CreateTextResponse(csvdata.ToString()); return msg; } public static string ToCsvFields(string separator, PropertyInfo[] fields, object o) { StringBuilder linie = new StringBuilder(); foreach (PropertyInfo f in fields) { if (linie.Length > 0) { } object x = f.GetValue(o, null); if (x != null) { linie.AppendLine(f.Name + ": " + x.ToString()); } else { linie.AppendLine(f.Name + ": Nothing"); } } return linie.ToString(); } } 

Есть один способ, как достичь этого, если вы имеете дело с HTTP, это не совсем приятно, но я думал, что могу упомянуть об этом.

Вы можете установить возвращаемый тип вашего метода на void и просто вывести свою необработанную строку непосредственно в ответ.

 [OperationContract] [WebGet(UriTemplate = "foo")] void Foo() { HttpContext.Current.Response.Write("bar"); } 
Давайте будем гением компьютера.