2009-06-14 19 views
21

WCF cung cấp hai tùy chọn cho thuộc tính ResponseFormat trong chú thích WebGet trong ServiceContract.WCF ResponseFormat Đối với 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(); 

Các tùy chọn cho ResponseFormat là WebMessageFormat.Json và WebMessageFormat.Xml. Có thể viết định dạng tin nhắn web của riêng tôi không? Tôi muốn rằng khi khách hàng gọi foo() phương pháp ông được chuỗi thô - không có json hoặc xml wrappers.

Trả lời

8

WebGetAttribute được vận chuyển bởi Microsoft và tôi không nghĩ rằng bạn có thể mở rộng WebMessageFormat. Tuy nhiên, bạn có thể mở rộng WebHttpBinding sử dụng WebGetAttribute. Bạn có thể thêm thuộc tính riêng của bạn như

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

Nói chung, tùy biến layout nhắn trong WCF được gọi là thông báo tùy chỉnh bộ mã hóa/giải mã. Microsoft cung cấp một ví dụ: Custom Message Encoder: Compression Encoder. Một phần mở rộng phổ biến khác mà mọi người làm là mở rộng hành vi để thêm xử lý lỗi tùy chỉnh, vì vậy bạn có thể tìm một số ví dụ theo hướng đó.

45

Hãy thử sử dụng

BodyStyle = WebMessageBodyStyle.Bare 

Sau đó trả về một System.IO.Stream từ chức năng của bạn.

Dưới đây là một số mã tôi sử dụng để trả lại một hình ảnh ra khỏi một cơ sở dữ liệu, nhưng truy cập thông qua một địa chỉ URL:

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

Thực hiệ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); 
} 

Trong trường hợp của bạn, để trả về một chuỗi nguyên, đặt ContentType thành nội dung như "text/plain" và trả lại dữ liệu của bạn dưới dạng luồng. Tại một đoán, một cái gì đó như thế này:

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

Nice. Nó hoạt động - vẫn có vẻ như có một WebMessageFormat.Raw. Cảm ơn. –

0

Có một cách làm thế nào để đạt được điều này nếu bạn đang làm việc với HTTP, nó không chính xác thoải mái, nhưng tôi nghĩ tôi có thể đề cập đến nó.

Bạn có thể đặt kiểu trả về của phương thức của mình thành vô hiệu và chỉ xuất chuỗi thô của bạn trực tiếp vào phản hồi.

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

tôi thực hiện thuộc tính này như thế này, có lẽ nó sẽ giúp một người nào đó trong tương lai:

[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(); 
    } 
} 
Các vấn đề liên quan