Wcf 协议冲突-谓词不允许内容类型

Wcf 协议冲突-谓词不允许内容类型,wcf,http,servicebus,Wcf,Http,Servicebus,更新:我当时在Build 2013,查看了这一点,并确认离开路由器的HTTP请求在请求中确实有一个“主体”。他认为这是由到达SB的Get引起的,然后将其打包以进行路由,然后将该包再次作为消息类型进行管理,然后再将其发送出去。在打包和路由之间,属性留在请求体中,这违反了“GET”的协议。然而,所有这些都存在于.NET或ServiceBus中的MS框架中。由于主体是不可变的(至少我找不到改变它的方法),唯一的方法是复制请求,然后在退出时更新原始请求 这是路由应用程序的一小部分,它接收来自Azure

更新:我当时在Build 2013,查看了这一点,并确认离开路由器的HTTP请求在请求中确实有一个“主体”。他认为这是由到达SB的Get引起的,然后将其打包以进行路由,然后将该包再次作为消息类型进行管理,然后再将其发送出去。在打包和路由之间,属性留在请求体中,这违反了“GET”的协议。然而,所有这些都存在于.NET或ServiceBus中的MS框架中。由于主体是不可变的(至少我找不到改变它的方法),唯一的方法是复制请求,然后在退出时更新原始请求

这是路由应用程序的一小部分,它接收来自Azure ServiceBus端点的HTTP GET/POST请求,通过中继通道将其传送到本地工作站,在那里我重写URL,并将其发送到本地web服务

这是一个通用接口,它可以接收对控制器/操作URL的任何类型的调用

  // The Router, and general concept of how to recieve from the SB and redirect was taken from
  // Tony Sneed Blog - which he documented here: http://blog.tonysneed.com/2012/04/24/roll-your-own-rest-ful-wcf-router/
  //
    [ServiceContract(Namespace = "urn:Twiddler")]
    public interface IRoutingService
    {
        [WebInvoke(UriTemplate = "")]
        [OperationContract(AsyncPattern = true, Action = "*", ReplyAction = "*")]
        IAsyncResult BeginProcessRequest(Message requestMessage, AsyncCallback asyncCallback, object asyncState);

        Message EndProcessRequest(IAsyncResult asyncResult);
    }
}
代码如下:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
     AddressFilterMode = AddressFilterMode.Any, ValidateMustUnderstand = false)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class RoutingService : IRoutingService, IDisposable
{
  private IRoutingService _client;

  /// <summary>
  /// when a message is received from the SB, it arrives here as simply a message - 
  /// </summary>
  /// <param name="requestMessage"></param>
  /// <param name="asyncCallback"></param>
  /// <param name="asyncState"></param>
  /// <returns></returns>
  public IAsyncResult BeginProcessRequest(Message requestMessage, AsyncCallback asyncCallback, object asyncState)
  {
    string RequestMessageAction = requestMessage.Headers.Action;

    IAsyncResult asyncResult = null;


    //if the full URI for the namespace does not match the one contructed in Twiddler, then pass it through - we have nothing to do with it!
    if (requestMessage.Headers.To.AbsoluteUri.Contains(Utilities.ServiceFormBridge.NameSpaceName) && requestMessage.Headers.To.AbsoluteUri.Contains(Utilities.ServiceFormBridge.EndPointName) == false)
      return asyncResult;

    //as the service bus will accept anything in terms of controllers and actions, we only need alter the DestinationAddress.Authority (host and port)
    var RewriteTheURL = requestMessage.Headers.To.AbsoluteUri.Replace(string.Format("http://{0}.servicebus.windows.net/{1}/", ServiceFormBridge.NameSpaceName, ServiceFormBridge.EndPointName), ServiceFormBridge.DestinationWebSite);

    Uri DestinationAddress = new Uri(RewriteTheURL);

    System.ServiceModel.ChannelFactory<IRoutingService> factory = null;

    factory = new ChannelFactory<IRoutingService>(new WebHttpBinding(), DestinationAddress.AbsoluteUri);

    WebHeaderCollection httpHeaders = WebOperationContext.Current.IncomingRequest.Headers;
    httpHeaders.Remove("Host");
    httpHeaders.Add("Host", DestinationAddress.Authority); //give it the new host that we are re-directing to

    httpHeaders.Remove("Connection");  //todo: not sure I need this, but without it there is an exception between Keep-Alive and Closed

    // Set factory and message address
    factory.Endpoint.Address = new EndpointAddress(DestinationAddress);
    requestMessage.Headers.To = DestinationAddress;


    _client = factory.CreateChannel();

    asyncResult = _client.BeginProcessRequest(requestMessage, asyncCallback, asyncState);

    return asyncResult;
  }
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall,
AddressFilterMode=AddressFilterMode.Any,ValidateMustUnderstand=false)]
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
公共类路由服务:IRoutingService,IDisposable
{
专用IRoutingService_客户端;
/// 
///当收到来自SB的消息时,它以消息的形式到达此处-
/// 
/// 
/// 
/// 
/// 
公共IAsyncResult BeginProcessRequest(Message requestMessage、AsyncCallback AsyncCallback、object asyncState)
{
字符串RequestMessageAction=requestMessage.Headers.Action;
IAsyncResult asyncResult=null;
//如果名称空间的完整URI与Twiddler中构造的URI不匹配,请将其传递给我们-我们与此无关!
if(requestMessage.Headers.To.AbsoluteUri.Contains(Utilities.ServiceFormBridge.NameSpaceName)&&requestMessage.Headers.To.AbsoluteUri.Contains(Utilities.ServiceFormBridge.EndPointName)=false)
返回结果;
//由于服务总线将接受控制器和操作方面的任何内容,我们只需要更改DestinationAddress.Authority(主机和端口)
var RewriteTheURL=requestMessage.Headers.To.AbsoluteUri.Replace(string.Format(“http://{0}.servicebus.windows.net/{1}/”,ServiceFormBridge.NameSpaceName,ServiceFormBridge.EndPointName),ServiceFormBridge.DestinationWebSite);
Uri DestinationAddress=新Uri(重写URL);
System.ServiceModel.ChannelFactory工厂=空;
工厂=新的ChannelFactory(新的WebHttpBinding(),DestinationAddress.AbsoluteUri);
WebHeaderCollection httpHeaders=WebOperationContext.Current.IncomingRequest.Headers;
httpHeaders.Remove(“主机”);
httpHeaders.Add(“Host”,DestinationAddress.Authority);//给它一个我们重新定向到的新主机
httpHeaders.Remove(“Connection”);//todo:我不确定是否需要它,但如果没有它,则Keep Alive和Closed之间会出现异常
//设置工厂和消息地址
factory.Endpoint.Address=新的端点地址(DestinationAddress);
requestMessage.Headers.To=DestinationAddress;
_client=factory.CreateChannel();
asyncResult=\u client.BeginProcessRequest(requestMessage、asyncCallback、asyncState);
返回结果;
}
}
在BeginProcessRequest上,我得到一个异常: 协议冲突:无法发送此谓词类型的内容正文

我已经研究过了,我知道在GET请求下,请求主体中不能有任何内容

当我的代码为一篇文章工作时,我只能假设出于某种原因,身体里有某种东西

然而,由于原始请求是使用ServiceBus的URL从浏览器获取的,我不确定为什么正文中会有任何内容

因此:

  • 我在想我在代码中做了什么导致了我的问题-如果是这样,我想知道是什么
  • 如果传入请求中有内容,我如何删除它以避免违反
  • 对代码还有其他建议和改进吗

  • 将此属性放置在操作[WebInvoke(UriTemplate=”“)]上,默认情况下支持POST,但您可以传递一个指定其他谓词的参数,如PUT、DELETE等。但是,GET由另一个属性[WebGet]支持。我建议向路由器添加额外的操作,一个使用WebGet,另一个使用WebInvoke和不同的HTTP谓词。

    。。。该接口仅指定WebInvoke,而不是WebGet。。。那么为什么它允许GET请求被中继到服务中呢?使用这样一个通用接口,我是否必须以不同的方式处理GET和POST?在这两种情况下,我都没有触及请求主体……GET请求被中继的原因是Action和ReplyAction都指定了“*”,这意味着所有消息都在这里发送。在这个接口上有一个WebInvoke属性就没有意义了!那么为什么get请求会进入该方法呢?它不应该简单地在端点处丢弃吗?而且,由于这只是传递请求,为什么会出现错误?内容类型为null,操作为GET,那么为什么会发生冲突?Tony-请参阅上面的注释-WebInvoke/WebGet在这里没有意义,因为action和ReplyAction都设置为“*”,返回类型为Message。这意味着所有消息都将路由到此接口。请记住这是WCF.:)服务操作仅支持POST,除非您使用WebInvoke(加上动词表示非POST,如PUT、MERGE、DELETE等)或WebGet进行不同的指定。然而,退一步说,对于真正基于REST的路由机制来说,WCF可能不是正确的选择。有点像苹果和桔子,因为对于其他的URL,它的视角是不同的。我建议使用ASP.NETWebAPI进行REST-ful路由,它关心动词和u