2009-06-14 5 views
21

WCF oferuje dwie opcje dla atrybutu ResponseFormat w adnotacji WebGet w ServiceContract.WCF ResponseFormat dla 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(); 

Możliwości ResponseFormat są WebMessageFormat.Json i WebMessageFormat.Xml. Czy mogę napisać własny format wiadomości internetowej? Chciałbym, aby gdy klient wywoływał metodę foo(), otrzymywał nieprzetworzony ciąg znaków - bez wrapperów json lub xml.

Odpowiedz

8

WebGetAttribute jest wysyłany przez firmę Microsoft i nie sądzę, że można przedłużyć WebMessageFormat. Jednak prawdopodobnie można przedłużyć WebHttpBinding, który używa WebGetAttribute. Możesz dodać własny atrybut, taki jak

Ogólnie, dostosowywanie układu komunikatów w WCF jest nazywane niestandardowym kodowaniem/kodowaniem wiadomości. Microsoft podaje przykład: Custom Message Encoder: Compression Encoder. Innym popularnym rozszerzeniem jest rozszerzenie zachowania w celu dodania niestandardowej obsługi błędów, abyś mógł szukać przykładu w tym kierunku.

45

Spróbuj użyć

BodyStyle = WebMessageBodyStyle.Bare 

Następnie zwrócić System.IO.Stream ze swojej funkcji.

Oto niektóre kodu używam do powrotu obrazu z bazy danych, ale dostępny za pośrednictwem adresu URL:

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

Realizacja:

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); 
} 

W twoim przypadku, aby powrócić do surowego ciąg, ustaw ContentType na coś takiego jak "text/plain" i zwróć dane jako strumień. Na oko, mniej więcej tak:

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

Nicea. Działa - nadal wydaje się, że powinien istnieć WebMessageFormat.Raw. Dzięki. –

0

Jest jeden sposób, jak to osiągnąć, jeśli masz do czynienia z HTTP, to nie jest dokładnie to miłe, ale myślałem, że mógłbym go wymienić.

Możesz ustawić typ zwrotu swojej metody, aby anulować i po prostu wypisać surowy ciąg bezpośrednio do odpowiedzi.

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

I wdrożone tego atrybutu takiego, może to pomoże komuś w przyszłości:

[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(); 
    } 
}