2012-05-09 10 views
11

में से एक के रूप में एचटीएमएल वापस जाने के लिए है मैं एक सेवा है जो मुझे लगता है कि लिख रहा हूँ जो कि प्राप्त करने या XML या JSON पार्स करने में असमर्थ होते हैं सहित कई कॉल करने, द्वारा इस्तेमाल किया जा करने का इरादा है है।यह संभव WCF बाकी 4 में प्रतिक्रिया प्रारूपों

मुझे पता है कि कच्चे स्ट्रीम का उपयोग कर एक सेवा प्रतिक्रिया से एचटीएमएल वापस करना संभव है, लेकिन मैं क्या करने में सक्षम होना चाहता हूं, एक्सेप्ट्स-टाइप हेडर पास के आधार पर एक्सएमएल, जेएसओएन, या एचटीएमएल में से एक को वापस करना है ग्राहक द्वारा

मैं अलग यूआरएल के साथ यह कर सकता है, लेकिन यह एक प्रणाली है जो पहले से ही एक अच्छी तरह से परिभाषित एपीआई परत होती है की जगह है।

इस उपलब्ध कर के किसी भी उदाहरण हैं, या किसी को भी क्या पाइपलाइन के कुछ हिस्सों के लिए बढ़ाया जा करने की आवश्यकता होगी पता है?

(परिशिष्ट): मुझे पहले से ही स्वचालितफॉर्मैट चयन के बारे में पता है और इसे सक्षम किया गया है, लेकिन मैं एक ही एंडपॉइंट से सभी तीन (या अधिक) प्रारूप (एचटीएमएल, जेएसओएन, एक्सएमएल, आदि) का समर्थन करना चाहता हूं।

उत्तर

9

हां, यह संभव है। लेकिन आपको एक नया संदेश फ़ॉर्मेटर बनाना होगा जो जानता है कि सीएलआर प्रकार (ऑपरेशन प्रतिक्रिया) और HTML पृष्ठ के बीच कैसे परिवर्तित करना है। ऐसा करने का सबसे आसान तरीका मूल फ़ॉर्मेटर को एक नए फॉर्मेटर में लपेटना है, इसलिए जब आपको Accept: text/html के अनुरोधों के लिए प्रतिक्रिया मिलती है तो आप अपने तर्क का उपयोग करते हैं, लेकिन अन्य अनुरोधों के लिए आप मूल फ़ॉर्मेटर का उपयोग करते हैं।

फ़ॉर्मेटर हालांकि, आने वाले अनुरोधों तक पहुँच प्राप्त करने के लिए एक रास्ता नहीं है, तो हम संदेश निरीक्षक का उपयोग करें कि प्रदान करने के लिए और साथ ही कर सकते हैं।

कोड के नीचे इस तरह के फ़ॉर्मेटर/निरीक्षक जोड़ी में से एक संभव कार्यान्वयन को दर्शाता है।

public class StackOverflow_10519075 
{ 
    [DataContract(Name = "Person", Namespace = "")] 
    public class Person 
    { 
     [DataMember] 
     public string Name { get; set; } 
     [DataMember] 
     public int Age { get; set; } 
    } 
    [ServiceContract] 
    public interface ITest 
    { 
     [WebGet] 
     Person GetPerson(); 
    } 
    public class Service : ITest 
    { 
     public Person GetPerson() 
     { 
      return new Person { Name = "John Doe", Age = 33 }; 
     } 
    } 
    public class MyHtmlAwareFormatter : IDispatchMessageFormatter 
    { 
     IDispatchMessageFormatter original; 
     public MyHtmlAwareFormatter(IDispatchMessageFormatter original) 
     { 
      this.original = original; 
     } 

     public void DeserializeRequest(Message message, object[] parameters) 
     { 
      this.original.DeserializeRequest(message, parameters); 
     } 

     public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result) 
     { 
      MyUseHtmlExtension useHtml = OperationContext.Current.Extensions.Find<MyUseHtmlExtension>(); 
      if (useHtml != null && useHtml.UseHtmlResponse) 
      { 
       StringBuilder sb = new StringBuilder(); 
       sb.AppendLine("<html><head><title>Result of " + useHtml.OperationName + "</title></head>"); 
       sb.AppendLine("<body><h1>Result of " + useHtml.OperationName + "</h1>"); 
       sb.AppendLine("<p><b>" + result.GetType().FullName + "</b></p>"); 
       sb.AppendLine("<ul>"); 
       foreach (var prop in result.GetType().GetProperties()) 
       { 
        string line = string.Format("{0}: {1}", prop.Name, prop.GetValue(result, null)); 
        sb.AppendLine("<li>" + line + "</li>"); 
       } 
       sb.AppendLine("</ul></body></html>"); 
       byte[] bytes = Encoding.UTF8.GetBytes(sb.ToString()); 
       Message reply = Message.CreateMessage(messageVersion, null, new RawBodyWriter(bytes)); 
       reply.Properties.Add(WebBodyFormatMessageProperty.Name, new WebBodyFormatMessageProperty(WebContentFormat.Raw)); 
       HttpResponseMessageProperty httpResp = new HttpResponseMessageProperty(); 
       reply.Properties.Add(HttpResponseMessageProperty.Name, httpResp); 
       httpResp.Headers[HttpResponseHeader.ContentType] = "text/html"; 
       return reply; 
      } 
      else 
      { 
       return original.SerializeReply(messageVersion, parameters, result); 
      } 
     } 

     class RawBodyWriter : BodyWriter 
     { 
      private byte[] bytes; 

      public RawBodyWriter(byte[] bytes) 
       : base(true) 
      { 
       this.bytes = bytes; 
      } 

      protected override void OnWriteBodyContents(XmlDictionaryWriter writer) 
      { 
       writer.WriteStartElement("Binary"); 
       writer.WriteBase64(this.bytes, 0, this.bytes.Length); 
       writer.WriteEndElement(); 
      } 
     } 
    } 
    public class MyHtmlAwareInspector : IDispatchMessageInspector 
    { 
     public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) 
     { 
      HttpRequestMessageProperty httpRequest = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name]; 
      string accept = httpRequest.Headers[HttpRequestHeader.Accept]; 
      string operationName = request.Properties[WebHttpDispatchOperationSelector.HttpOperationNamePropertyName] as string; 
      if (accept == "text/html") 
      { 
       OperationContext.Current.Extensions.Add(new MyUseHtmlExtension { UseHtmlResponse = true, OperationName = operationName }); 
      } 

      return null; 
     } 

     public void BeforeSendReply(ref Message reply, object correlationState) 
     { 
     } 
    } 
    class MyUseHtmlExtension : IExtension<OperationContext> 
    { 
     public void Attach(OperationContext owner) { } 
     public void Detach(OperationContext owner) { } 
     public bool UseHtmlResponse { get; set; } 
     public string OperationName { get; set; } 
    } 
    public class MyHtmlAwareEndpointBehavior : IEndpointBehavior 
    { 
     public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
     { 
     } 

     public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
     { 
     } 

     public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) 
     { 
      endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MyHtmlAwareInspector()); 
      foreach (DispatchOperation operation in endpointDispatcher.DispatchRuntime.Operations) 
      { 
       operation.Formatter = new MyHtmlAwareFormatter(operation.Formatter); 
      } 
     } 

     public void Validate(ServiceEndpoint endpoint) 
     { 
     } 
    } 
    public static void Test() 
    { 
     string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; 
     ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); 
     var endpoint = host.AddServiceEndpoint(typeof(ITest), new WebHttpBinding(), ""); 
     endpoint.Behaviors.Add(new WebHttpBehavior { AutomaticFormatSelectionEnabled = true }); 
     endpoint.Behaviors.Add(new MyHtmlAwareEndpointBehavior()); 
     host.Open(); 
     Console.WriteLine("Host opened"); 

     WebClient c; 

     c = new WebClient(); 
     c.Headers[HttpRequestHeader.Accept] = "application/json"; 
     Console.WriteLine(c.DownloadString(baseAddress + "/GetPerson")); 
     Console.WriteLine(); 

     c = new WebClient(); 
     c.Headers[HttpRequestHeader.Accept] = "text/xml"; 
     Console.WriteLine(c.DownloadString(baseAddress + "/GetPerson")); 
     Console.WriteLine(); 

     c = new WebClient(); 
     c.Headers[HttpRequestHeader.Accept] = "text/html"; 
     Console.WriteLine(c.DownloadString(baseAddress + "/GetPerson")); 
     Console.WriteLine(); 

     Console.Write("Press ENTER to close the host"); 
     Console.ReadLine(); 
     host.Close(); 
    } 
} 
+0

वाह अद्भुत @carlosfigueira, धन्यवाद। मैं इसे देख लूंगा और इसे लागू करूंगा। – GrayWizardx

संबंधित मुद्दे