2009-08-17 67 views
16

如何訪問WCF REST服務中的HTTP POST請求正文?WCF RESTful服務中的訪問請求正文

下面是服務定義:

[ServiceContract] 
public interface ITestService 
{ 
    [OperationContract] 
    [WebInvoke(Method = "POST", UriTemplate = "EntryPoint")] 
    MyData GetData(); 
} 

這裏是實現:

public MyData GetData() 
{ 
    return new MyData(); 
} 

我雖然使用下面的代碼訪問HTTP請求:

IncomingWebRequestContext context = WebOperationContext.Current.IncomingRequest; 

但IncomingWebRequestContext只允許訪問標題,而不是正文。

謝謝。

回答

0

我對上一個答案表示歉意,我愚蠢地認爲我只是投了WebOperationContext纔得到OperationContext,不幸的是真正的答案更難看。

讓我以此爲序,一定有更好的辦法!

首先我創建了我自己的上下文對象,它可以附加到現有的OperationContext對象上。

public class TMRequestContext : IExtension<OperationContext> { 

    private OperationContext _Owner; 

     public void Attach(OperationContext owner) { 
      _Owner = owner; 
     } 

    public void Detach(OperationContext owner) { 
      _Owner = null; 
     } 

    public static TMRequestContext Current { 
      get { 
       if (OperationContext.Current != null) { 
        return OperationContext.Current.Extensions.Find<TMRequestContext>(); 
       } else { 
        return null; 
       } 
      } 
     } 
} 

爲了能夠訪問這個新的上下文對象,你需要將其添加爲一個擴展到目前的一個。我通過創建一個消息檢查器類來做到這一點。

public class TMMessageInspector : IDispatchMessageInspector { 

     public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) { 

      OperationContext.Current.Extensions.Add(new TMRequestContext()); 
      return null; 
     } 
} 

爲了使消息檢查器正常工作,您需要創建一個新的「行爲」。我用下面的代碼做了這個。

public class TMServerBehavior : IServiceBehavior { 

     public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { 
      //Do nothing 
     } 

     public void ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase) { 

      foreach (ChannelDispatcher chDisp in serviceHostBase.ChannelDispatchers) { 

       foreach (EndpointDispatcher epDisp in chDisp.Endpoints) { 
        epDisp.DispatchRuntime.MessageInspectors.Add(new TMMessageInspector()); 
       } 
      } 

     } 
} 

,你應該能夠在配置文件中添加,但我做到了通過創建一個新的主機,並在OnOpening方法手動添加行爲對象的行爲。我最終使用這些類不僅僅是訪問OperationContext對象。我用它們進行日誌記錄並覆蓋錯誤處理和訪問http請求對象等。所以,它不像看起來那麼荒謬。幾乎,但不完全!

我真的不記得爲什麼我不能直接訪問OperationContext.Current。我有一個微弱的回憶,它總是空的,這個討厭的過程是我能得到一個實際包含有效數據的實例的唯一途徑。

我覺得不涉及
+0

嗨達雷爾, 我試過你的建議,遇到了一些問題。 當我使用你的確切代碼,我得到了這個錯誤(在編譯時): 無法將類型'System.ServiceModel.Web.WebOperationContext'轉換爲'System.ServiceModel.OperationContext' 當我將其更改爲此代碼時: string body = OperationContext.Current.RequestContext.RequestMessage.ToString(); 機體在運行時爲空字符串。 任何想法? 謝謝, Uri – urini 2009-09-08 10:37:20

10

最佳方式WebOperationContext

[OperationContract] 
[WebInvoke(Method = "POST", UriTemplate = "EntryPoint", BodyStyle = WebMessageBodyStyle.Bare)] 
MyData GetData(System.IO.Stream pStream); 
+0

無論如何'BodyStyle'默認爲'WebMessageBodyStyle.Bare'。 – 2012-10-31 17:02:30

+0

嗯,如果URITemplate包含'{參數}' – LamonteCristo 2014-07-23 17:36:09

+0

這個工作,即使urltemplate有參數,這也不起作用。對我來說這適用於原始xml發佈請求,但解決方案與OperationContext.Current.RequestContext.RequestMessage.ToString() - 不起作用(結果「...流...」) – SalientBrain 2015-10-26 10:56:37

1

看來,因爲WCF被設計爲傳輸協議無關,服務方法不提供訪問默認HTTP特定的信息。但是,我剛剛遇到了一篇描述「ASP.Net兼容模式」的好文章,它基本上允許您指定您的服務確實是通過HTTP公開的。

http://blogs.msdn.com/b/wenlong/archive/2006/01/23/516041.aspx

添加aspNetCompatibilityEnabled配置Web.config,結合AspNetCompatibilityRequirements屬性所需的服務業務,應該做的伎倆。我即將自己嘗試。

山楂斌

+0

真實的,但它帶走了自我託管服務的功能。 – 2012-10-31 17:04:18

10

使用

OperationContext.Current.RequestContext.RequestMessage

+5

它會給你消息的xml,而不是POST正文 – 2011-10-26 21:03:29

1

以上答案幫我想出了這個解決方案。我正在接收帶有名稱/值對的json。 { 「P1」:7514, 「P2」:3412, 「P3」: 「張三」 ...}

[OperationBehavior(Impersonation = ImpersonationOption.Allowed)] 
    [WebInvoke(Method = "POST", 
     BodyStyle = WebMessageBodyStyle.Bare, 
     RequestFormat = WebMessageFormat.Json 
     )] 

public Stream getJsonRequest() 
    { 

     // Get the raw json POST content. .Net has this in XML string.. 
     string JSONstring = OperationContext.Current.RequestContext.RequestMessage.ToString(); 

     // Parse the XML string into a XML document 
     XmlDocument doc = new XmlDocument(); 
     doc.LoadXml(JSONstring); 

     foreach (XmlNode node in doc.DocumentElement.ChildNodes) 
     { 
       node.Name // has key 
       node.InnerText; // has value 
+0

for xml post request它給了我「...流...」,Encoding.UTF8.GetString(OperationContext.Current.RequestContext.RequestMessage.GetBody ())doesn也不行。對我來說[Kasthor]解決方案的工作原理如下:var inputStream = OperationContext.Current.RequestContext.RequestMessage.GetBody (); \t \t \t var sr = new StreamReader(inputStream,Encoding.UTF8); \t \t \t var str = sr.ReadToEnd(); – SalientBrain 2015-10-26 11:03:57

+0

而不是遍歷節點,你可以從文檔創建一個XmlNodeReader,然後將其提供給DataContractJsonSerializer.ReadObject(),它接受一個XmlReader。這樣,不是字符串的值(如數字和布爾值)就是正確的類型! – 2016-01-07 13:47:57

6

對不起,我遲到的答案,但我想我會添加具有UriTemplate參數是什麼在起作用得到請求正文。

[ServiceContract] 
public class Service 
{   
    [OperationContract] 
    [WebInvoke(UriTemplate = "{param0}/{param1}", Method = "POST")] 
    public Stream TestPost(string param0, string param1) 
    { 

     string body = Encoding.UTF8.GetString(OperationContext.Current.RequestContext.RequestMessage.GetBody<byte[]>()); 

     return ...; 
    } 
} 

body分配從消息主體的原始字節的字符串。