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