2009-06-14 8 views
21

WCF ofrece dos opciones para el atributo ResponseFormat en la anotación WebGet en 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(); 

Las opciones para ResponseFormat son WebMessageFormat.Json y WebMessageFormat.Xml. ¿Es posible escribir mi propio formato de mensaje web? Me gustaría que cuando el cliente llama al método foo() obtiene una cadena sin formato, sin envoltorios json o xml.

Respuesta

8

WebGetAttribute es enviado por Microsoft, y no creo que pueda ampliar WebMessageFormat. Sin embargo, probablemente podría extender el WebHttpBinding que usa WebGetAttribute. Se podría añadir su propio atributo como

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

En general, personalizar el diseño de mensajes en WCF se llama mensaje personalizado codificador/codificación. Microsoft proporciona un ejemplo: Custom Message Encoder: Compression Encoder. También otra extensión común que las personas hacen es extender el comportamiento para agregar un manejo de error personalizado, por lo que podría buscar algún ejemplo en esa dirección.

45

Intente utilizar

BodyStyle = WebMessageBodyStyle.Bare 

A continuación, devuelven un System.IO.Stream de su función.

Aquí hay un código que utilizo para devolver una imagen de una base de datos, pero accesible a través de una URL:

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

Implementación:

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

En su caso, para devolver una cadena prima, configura ContentType a algo como "texto/normal" y devuelve tus datos como una secuencia. En una conjetura, algo como esto:

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

Niza. Funciona, todavía parece que debería haber un WebMessageFormat.Raw. Gracias. –

0

hay una manera de cómo lograr esto si usted está tratando con HTTP, que no es exactamente agradable, pero pensé que podría mencionar.

Puede establecer que el tipo de devolución de su método se anule y simplemente envíe su cadena sin procesar directamente a la respuesta.

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

he implementado este atributo como este, tal vez va a ayudar a alguien en el futuro:

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