Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WCF RESTful服务中的访问请求正文_C#_Wcf_Http_Rest - Fatal编程技术网

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

C# WCF RESTful服务中的访问请求正文,c#,wcf,http,rest,C#,Wcf,Http,Rest,如何在WCF REST服务中访问HTTP POST请求正文 以下是服务定义: [ServiceContract] public interface ITestService { [OperationContract] [WebInvoke(Method = "POST", UriTemplate = "EntryPoint")] MyData GetData(); } 以下是实施方案: public MyData GetData() { return new M

如何在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来获取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 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());
                }
            }

        }
}
公共类TMServerBehavior:IServiceBehavior{
public void AddBindingParameters(ServiceDescription ServiceDescription,System.ServiceModel.ServiceHostBase ServiceHostBase,System.Collections.ObjectModel.Collection端点,System.ServiceModel.Channel.BindingParameterCollection bindingParameters){
//无所事事
}
public void ApplyDispatchBehavior(ServiceDescription ServiceDescription,System.ServiceModel.ServiceHostBase ServiceHostBase){
foreach(serviceHostBase.ChannelDispatchers中的ChannelDispatcher chDisp){
foreach(chDisp.Endpoints中的EndpointDispatcher epDisp){
添加(新的TMMessageInspector());
}
}
}
}
您应该能够在配置文件中添加行为,尽管我是通过创建一个新主机并在OnOpening方法中手动添加行为对象来实现的。我最终使用这些类的目的不仅仅是访问OperationContext对象。我使用它们来记录和覆盖错误处理以及对http请求对象的访问等。因此,这并不像看起来的那么荒谬。差不多,但不完全


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

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

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

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

aspnetcompatibilitynabled
配置添加到
Web.config
,并结合
AspNetCompatibilityRequirements
属性添加到所需的服务操作中,应该可以达到目的。我打算自己试试这个

山楂酱


OperationContext.Current.RequestContext.RequestMessage

上述答案帮助我想出了这个解决方案。我正在接收带有名称/值对的json。{“p1”:7514,“p2”:3412,“p3”:“乔·史密斯”…}


很抱歉回答得太晚了,但我想我应该添加与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 ...;
    }
}
[服务合同]
公务舱服务
{        
[经营合同]
[WebInvoke(UriTemplate=“{param0}/{param1}”,Method=“POST”)]
公共流TestPost(字符串param0,字符串param1)
{
string body=Encoding.UTF8.GetString(OperationContext.Current.RequestContext.RequestMessage.GetBody());
返回。。。;
}
}
body
从消息正文的原始字节中分配了一个字符串。

以下是我所做的:

using System.IO;
using System.ServiceModel;
using System.ServiceModel.Web;
using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;

namespace YourSpaceName
{
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    public class YourClassName
    {
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "YourMethodName({id})", BodyStyle = WebMessageBodyStyle.Bare)]
        public Stream YourMethodName(Stream input, string id)
        {
            WebOperationContext ctx = WebOperationContext.Current;
            ctx.OutgoingResponse.Headers.Add("Content-Type", "application/json");

            string response = $@"{{""status"": ""failure"", ""message"": ""Please specify the Id of the vehicle requisition to retrieve."", ""d"":null}}";
            try
            {
                string response = (new StreamReader(input)).ReadToEnd();
            }
            catch (Exception ecp)
            {
                response = $@"{{""status"": ""failure"", ""message"": ""{ecp.Message}"", ""d"":null}}";
            }

            return new MemoryStream(Encoding.UTF8.GetBytes(response));
        }
    }
}
这段代码只是读取输入并将其写出。
POST请求的主体自动分配给输入,而不考虑变量名。如您所见,您的UriTemplate中仍然可以有变量。

此代码返回正文文本。需要使用
System
System.Text
System.Reflection
System.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;
}
公共字符串GetBody()
{
var requestMessage=OperationContext.Current.RequestContext.requestMessage;
var messageDataProperty=requestMessage.GetType().GetProperty(“MessageData”,(BindingFlags)0x1fffffff);
var messageData=messageDataProperty.GetValue(requestMessage);
var bufferProperty=messageData.GetType().GetProperty(“缓冲区”);
var buffer=bufferProperty.GetValue(messageData)作为ArraySegment?;
var body=Encoding.UTF8.GetString(buffer.Value.Array);
返回体;
}

你好,达雷尔,我尝试了你的建议,但遇到了一些问题。当我使用您的确切代码时,我(在编译时)遇到了以下错误:无法将类型“System.ServiceModel.Web.WebOperationContext”转换为“System.ServiceModel.OperationContext”,并且当我将其更改为以下代码时:string body=OperationContext.Current.RequestContext.RequestMessage.ToString();正文在运行时是一个空字符串。有什么想法吗?谢谢,Urit将为您提供消息的xml,而不是发布正文
BodyStyle
默认为
WebMessageBodyStyle.Bare
。即使urltemplate有参数,这也可以工作。对我来说,这适用于原始xml post请求,但带有OperationContext.Current.RequestContext.RequestMessage.ToString()的解决方案不起作用(结果“…stream…”)True,但它会带走服务的自托管功能。对于xml post请求,它会给我“…stream…”Encoding.UTF8.GetString(OperationContext.Current.RequestContext.RequestMessage.GetBody())也不起作用。对我来说,[Kastor]解决方案起作用,或者如下:var inputStream=OperationContext.Current.RequestContext.RequestMessage.GetBody();var sr=new StreamReader(inputStream,Encoding.UTF8);var str=sr.ReadToEnd();您可以创建一个
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Web;
using System;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Text;

namespace YourSpaceName
{
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    public class YourClassName
    {
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "YourMethodName({id})", BodyStyle = WebMessageBodyStyle.Bare)]
        public Stream YourMethodName(Stream input, string id)
        {
            WebOperationContext ctx = WebOperationContext.Current;
            ctx.OutgoingResponse.Headers.Add("Content-Type", "application/json");

            string response = $@"{{""status"": ""failure"", ""message"": ""Please specify the Id of the vehicle requisition to retrieve."", ""d"":null}}";
            try
            {
                string response = (new StreamReader(input)).ReadToEnd();
            }
            catch (Exception ecp)
            {
                response = $@"{{""status"": ""failure"", ""message"": ""{ecp.Message}"", ""d"":null}}";
            }

            return new MemoryStream(Encoding.UTF8.GetBytes(response));
        }
    }
}
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;
}