WCF RESTful服务中的访问请求正文

如何在WCF REST服务中访问HTTP POST请求正文?

这是服务定义:

[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只允许访问标题,而不是正文。

谢谢。

我认为最佳方式不涉及WebOperationContext

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

使用

OperationContext.Current.RequestContext.RequestMessage

对于迟到的答案很抱歉,但我想我会添加一些与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()); return ...; } } 

body从消息体的原始字节中分配一个字符串。

似乎因为WCF被设计为与传输协议无关,所以默认情况下,服务方法不提供对特定于HTTP的信息的访问。 但是,我刚刚发现了一篇描述“ASP.Net兼容模式”的好文章,它基本上允许您指定您的服务确实是通过HTTP公开的。

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

aspNetCompatibilityEnabled配置添加到Web.config ,并将AspNetCompatibilityRequirements属性与所需的服务操作相结合,应该可以解决问题。 我要自己尝试一下。

山楂斌

以上答案帮助我提出了这个解决方案。 我收到名字/价值对的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 

我为前一个答案道歉,我愚蠢地假设我刚刚使用WebOperationContext来获取OperationContext,不幸的是真正的答案更难看。

让我先说一下,必须有一个更好的方法!

首先,我创建了自己的上下文对象,可以附加到现有的OperationContext对象。

 public class TMRequestContext : IExtension { 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(); } 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 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对象。 我使用它们来记录和覆盖error handling和访问http请求对象等。 所以,它似乎并不像看起来那么荒谬。 几乎,但不完全!

我真的不记得为什么我不能直接访问OperationContext.Current。 我有一个微弱的回忆,它总是空的,这个令人讨厌的过程是我获得实际包含有效数据的实例的唯一方法。