2009-06-14 1 views
21

WCF bietet zwei Optionen für ResponseFormat-Attribut in WebGet-Annotation in ServiceContract.WCF ResponseFormat für 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(); 

Die Optionen für die Response sind WebMessageFormat.Json und WebMessageFormat.Xml. Ist es möglich, mein eigenes Web-Nachrichtenformat zu schreiben? Ich möchte, dass, wenn Client foo() -Methode aufruft, er rohe Zeichenkette erhält - ohne JSON- oder XML-Wrapper.

Antwort

8

WebGetAttribute wird von Microsoft geliefert, und ich glaube nicht, dass Sie WebMessageFormat erweitern können. Sie könnten jedoch wahrscheinlich die WebHttpBinding, die WebGetAttribute verwendet, erweitern. Sie könnten Ihr eigenes Attribut wie

hinzufügen

Im Allgemeinen wird das Anpassen des Nachrichtenlayouts in WCF als benutzerdefinierte Nachrichtencodierung/Codierung bezeichnet. Microsoft bietet ein Beispiel: Custom Message Encoder: Compression Encoder. Eine weitere häufige Erweiterung, die Benutzer ausführen, besteht darin, das Verhalten so zu erweitern, dass eine benutzerdefinierte Fehlerbehandlung hinzugefügt wird, sodass Sie nach einem Beispiel in dieser Richtung suchen können.

45

Try

BodyStyle = WebMessageBodyStyle.Bare 

Dann eine System.IO.Stream aus Ihrer Funktion zurückkehren werden.

Hier einige Code, den ich verwende, um ein Bild aus einer Datenbank zurück, aber erreichbar über eine URL:

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

Umsetzung:

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

In Ihrem Fall eine rohe Zeichenfolge zurück, Setzen Sie den ContentType auf "text/plain" und geben Sie Ihre Daten als Stream zurück. Bei einer Vermutung, etwa wie folgt:

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

Nizza. Es funktioniert - scheint immer noch wie es sollte ein WebMessageFormat.Raw sein. Vielen Dank. –

0

Es gibt einen Weg, wie dies zu erreichen, wenn Sie mit HTTP zu tun hat, ist es nicht gerade schön, aber ich dachte, dass ich es nennen könnte.

Sie können den Rückgabetyp Ihrer Methode auf void setzen und Ihre rohe Zeichenfolge direkt in die Antwort ausgeben.

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

Ich implementierte dieses Attribut wie diese, vielleicht wird es jemanden in der Zukunft helfen:

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