1

更新:我在 Build 2013,Mark Simms看了这个并确认离开路由器的 HTTP 请求在请求中确实有一个“正文”。他觉得这是因为 Get 到达 SB,然后打包进行路由,然后将包再次作为 Message 类型进行管理,然后再将其发送回去。在打包和路由之间,属性留在请求的主体中——这违反了“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;
  }
}

在 BeginProcessRequest 上,出现异常:协议违规:无法发送具有此动词类型的内容主体

我已经研究过,我知道在 GET 请求下,请求正文中不能有任何内容。

由于我的代码适用于 POST,因此我只能假设由于某种原因,体内有些东西。

但是,由于原始请求是来自使用 ServiceBus 的 URL 的浏览器的 GET,我不确定为什么正文中会有任何内容。

所以:

  1. 我在想我在代码中做了一些导致我出现问题的事情——如果是这样,我想知道是什么!
  2. 如果传入的请求中有某些内容,我怎样才能将其删除,以免违规?
  3. 还有其他建议,对代码的改进吗?
4

1 回答 1

0

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

于 2013-03-11T02:06:00.290 回答