更新:我在Build 2013,Mark Simms看了这个,并确认离开路由器的HTTP请求确实有一个" Body"在请求中。他认为这是由于Get到达SB,然后打包被路由,然后包再次作为Messsage类型管理,然后再将其发回。在打包和路由之间,属性留在请求的主体中 - 这违反了" GET"的协议。但是,所有这些都存在于.NET框架中的.NET框架中或ServiceBus中。由于正文是不可变的(至少我找不到改变它的方法),唯一的方法是复制请求,然后在出路时更新原始请求。
这是路由应用程序的一小部分,它从Azure ServiceBus端点接收HTTP GET / POST请求,通过中继通道将其关闭到我的本地工作站,在那里我重写URL,并将其发送给我本地网络服务。
这是接口 - 通用,以便它可以接收对控制器/操作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;
}
}
在BeginProcessRequest上,我得到一个例外: 违反协议:无法使用此动词类型
发送内容正文我已经研究过,据我所知,根据GET请求,请求正文中不能包含任何内容。
由于我的代码适用于POST,我只能假设由于某种原因,身体中存在某些东西。
但是,由于原始请求是使用ServiceBus的URL从浏览器获取的GET,我不确定为什么身体中会有任何内容。
所以:
答案 0 :(得分:0)
在操作上放置此属性,[WebInvoke(UriTemplate =“”)]默认支持POST,但是您可以传递指定其他谓词的参数,例如PUT,DELETE等。但是,GET支持不同的属性,[WebGet]。我建议在路由器上添加额外的操作,一个用WebGet,另一个用WebInvoke和不同的HTTP动词。