2009-06-14 3 views
21

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

[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-оберток.

ответ

8

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

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

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

45

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

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» и верните свои данные в виде потока. В догадке, что-то вроде этого:

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

Nice. Он работает - по-прежнему кажется, что должен быть WebMessageFormat.Raw. Благодарю. –

0

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

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

[OperationContract] 
[WebGet(UriTemplate = "foo")] 
void Foo() 
{ 
    HttpContext.Current.Response.Write("bar"); 
} 
2

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

[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<object> cl = (IEnumerable<object>)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(); 
    } 
}