2016-03-02 78 views
0

我正在用WCF構建一組Rest服務。我使用郵遞員來提出測試請求。一切都很好,直到我想在請求頭中指定「Content-Type」。WCF服務不喜歡我的內容類型

服務合同:

[OperationContract] 
    [WebInvoke(Method = "POST", 
       UriTemplate = "data")] 
    Stream GetData(Stream iBody); 

和它背後的代碼:

public Stream GetData(Stream iBody) { 
    StreamReader objReader = new StreamReader(iBody); 
    string strBody = objReader.ReadToEnd(); 

    XmlDocument objDoc = new XmlDocument(); 
    objDoc.LoadXml(strBody); 

    return GetStreamData("Hello There. " + objDoc.InnerText); 
} 

private Stream GetStreamData(string iContent) { 
    byte[] resultBytes = Encoding.UTF8.GetBytes(iContent); 
    return new MemoryStream(resultBytes); 
} 

這一切,只要我不包括「內容類型」與「文本的值工作正常/ xml「。

隨着: enter image description here

無: 「文本/ XML;字符集= UTF-8」 的 enter image description here

我還試圖組合和 「應用程序/ xml」 的無濟於事。它與服務方法正在接受的類型有什麼關係?任何指針將不勝感激。

回答

2

由於您在WCF服務中使用raw programming model(使用Stream作爲參數/返回類型),因此您需要告訴WCF堆棧不要試圖將XML內容類型的傳入請求解釋爲XML,而是改爲讓它通過。您可以使用WebContentTypeMapper來完成此操作,該操作會將所有傳入請求(不管其內容類型)映射到原始模式。在頂部鏈接的博客文章中有更多關於此的信息,下面的代碼顯示了處理您的案例的映射器的示例。

public class StackOverflow_35750073 
{ 
    [ServiceContract] 
    public class Service 
    { 
     [OperationContract] 
     [WebInvoke(Method = "POST", UriTemplate = "data")] 
     public Stream GetData(Stream iBody) 
     { 
      StreamReader objReader = new StreamReader(iBody); 
      string strBody = objReader.ReadToEnd(); 

      XmlDocument objDoc = new XmlDocument(); 
      objDoc.LoadXml(strBody); 

      return GetStreamData("Hello There. " + objDoc.InnerText); 
     } 
     private Stream GetStreamData(string iContent) 
     { 
      byte[] resultBytes = Encoding.UTF8.GetBytes(iContent); 
      return new MemoryStream(resultBytes); 
     } 
    } 
    class RawMapper : WebContentTypeMapper 
    { 
     public override WebContentFormat GetMessageFormatForContentType(string contentType) 
     { 
      return WebContentFormat.Raw; 
     } 
    } 
    public static void Test() 
    { 
     string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; 
     ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); 
     ServiceEndpoint endpoint1 = host.AddServiceEndpoint(
      typeof(Service), 
      new WebHttpBinding { ContentTypeMapper = new RawMapper() }, 
      "withMapper"); 
     endpoint1.Behaviors.Add(new WebHttpBehavior()); 

     ServiceEndpoint endpoint2 = host.AddServiceEndpoint(
      typeof(Service), 
      new WebHttpBinding(), 
      "noMapper"); 
     endpoint2.Behaviors.Add(new WebHttpBehavior()); 

     host.Open(); 
     Console.WriteLine("Host opened"); 

     var input = "<hello><world>How are you?</world></hello>"; 
     Console.WriteLine("Using a Content-Type mapper:"); 
     SendRequest(baseAddress + "/withMapper/data", "POST", "text/xml", input); 
     SendRequest(baseAddress + "/withMapper/data", "POST", null, input); 

     Console.WriteLine("Without using a Content-Type mapper:"); 
     SendRequest(baseAddress + "/noMapper/data", "POST", "text/xml", input); 
     SendRequest(baseAddress + "/noMapper/data", "POST", null, input); 

     Console.Write("Press ENTER to close the host"); 
     Console.ReadLine(); 
     host.Close(); 
    } 
    public static string SendRequest(string uri, string method, string contentType, string body) 
    { 
     string responseBody = null; 

     HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(uri); 
     req.Method = method; 
     if (!String.IsNullOrEmpty(contentType)) 
     { 
      req.ContentType = contentType; 
     } 

     if (body != null) 
     { 
      byte[] bodyBytes = Encoding.UTF8.GetBytes(body); 
      req.GetRequestStream().Write(bodyBytes, 0, bodyBytes.Length); 
      req.GetRequestStream().Close(); 
     } 

     HttpWebResponse resp; 
     try 
     { 
      resp = (HttpWebResponse)req.GetResponse(); 
     } 
     catch (WebException e) 
     { 
      resp = (HttpWebResponse)e.Response; 
     } 

     if (resp == null) 
     { 
      responseBody = null; 
      Console.WriteLine("Response is null"); 
     } 
     else 
     { 
      Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription); 
      foreach (string headerName in resp.Headers.AllKeys) 
      { 
       Console.WriteLine("{0}: {1}", headerName, resp.Headers[headerName]); 
      } 
      Console.WriteLine(); 
      Stream respStream = resp.GetResponseStream(); 
      if (respStream != null) 
      { 
       responseBody = new StreamReader(respStream).ReadToEnd(); 
       Console.WriteLine(responseBody); 
      } 
      else 
      { 
       Console.WriteLine("HttpWebResponse.GetResponseStream returned null"); 
      } 
     } 

     Console.WriteLine(); 
     Console.WriteLine(" *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* "); 
     Console.WriteLine(); 

     return responseBody; 
    } 
} 
+0

謝謝。這使得現在更有意義了(WCF新手)。我建立它接受XML或JSON,但不知道哪些運行時間。因此需要內容類型來確定任意內容實際是什麼。 – mac