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

uri*_*ini 17 c# rest wcf http

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

这是服务定义:

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

这是实施:

public MyData GetData()
{
    return new MyData();
}
Run Code Online (Sandbox Code Playgroud)

我使用以下代码来访问HTTP请求:

IncomingWebRequestContext context = WebOperationContext.Current.IncomingRequest;
Run Code Online (Sandbox Code Playgroud)

但IncomingWebRequestContext只允许访问标题,而不是正文.

谢谢.

kas*_*hor 11

我认为最好的方法不涉及WebOperationContext

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


saj*_*ith 9

使用

OperationContext.Current.RequestContext.RequestMessage

  • 它会给你消息的xml而不是POST正文 (6认同)

Дми*_*тик 8

此代码返回正文。需要使用System,,,System.TextSystem.ReflectionSystem.ServiceModel

public string GetBody()
{
  var requestMessage = OperationContext.Current.RequestContext.RequestMessage;
  var messageDataProperty = requestMessage.GetType().GetProperty("MessageData", (BindingFlags)0x1FFFFFF);
  var messageData = messageDataProperty.GetValue(requestMessage);
  var bufferProperty = messageData.GetType().GetProperty("Buffer");
  var buffer = bufferProperty.GetValue(messageData) as ArraySegment<byte>?;
  var body = Encoding.UTF8.GetString(buffer.Value.Array);
  return body;
}
Run Code Online (Sandbox Code Playgroud)


Ger*_*ton 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 ...;
    }
}
Run Code Online (Sandbox Code Playgroud)

body 从消息正文的原始字节分配一个字符串.


Dar*_*ler 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;
                }
            }
        }
}
Run Code Online (Sandbox Code Playgroud)

为了能够访问这个新的上下文对象,您需要将其添加为当前上下文对象的扩展。我通过创建一个消息检查器类来做到这一点。

public class TMMessageInspector : IDispatchMessageInspector {

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

            OperationContext.Current.Extensions.Add(new TMRequestContext());
            return null;
        }
}
Run Code Online (Sandbox Code Playgroud)

为了使消息检查器正常工作,您需要创建一个新的“行为”。我使用以下代码完成了此操作。

    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());
                }
            }

        }
}
Run Code Online (Sandbox Code Playgroud)

您应该能够在配置文件中添加行为,尽管我是通过创建新主机并在 OnOpening 方法中手动添加行为对象来实现的。我最终使用这些类的目的不仅仅是访问 OperationContext 对象。我用它们来记录和覆盖错误处理以及访问 http 请求对象等。所以,这并不是看起来那么荒谬的解决方案。几乎,但不完全是!

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