2013-03-06 63 views
1

更新:我在Build 2013和Mark Simms看着這個,並確認離開路由器的HTTP請求確實在請求中有一個「Body」。他覺得這是由於Get到達SB,然後打包發送,然後將包重新作爲Messsage類型進行管理,然後再次將其發回。在封裝和路由之間,屬性留在請求的主體中 - 違反了「GET」的協議。但是,所有這些都在MS框架中,不管是在.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,所以我不確定爲什麼會有任何內容。

所以:

  1. 我想我做的,是造成我一個問題的代碼的東西 - 如果,所以我想知道是什麼!
  2. 如果傳入請求中有某些內容,我該如何刪除它以免違規?
  3. 任何其他建議,對代碼的改進?
+0

因此......接口只指定WebInvoke,而不指定WebGet ......那麼它爲什麼會允許GET請求被中繼到服務中呢?使用這樣的通用接口,我必須以不同方式處理GET和POST嗎?在這兩種情況下,我都不會觸及請求主體... – codeputer 2013-03-10 23:27:20

+0

GET請求被中繼的原因是因爲Action和ReplyAction都指定了「*」,這意味着所有消息都在這裏發送。然後在這個接口上有一個WebInvoke屬性就少點了! – codeputer 2013-03-17 22:32:23

回答

0

放置在操作此屬性,[WebInvoke(UriTemplate =「」)],支持POST通過默認,但可以通過一個參數,指定其他動詞,例如PUT,DELETE,等等。然而,得到的是由不同的屬性支持,[WebGet]。我會建議向路由器添加額外的操作,一個使用WebGet,另一個使用WebInvoke和不同的HTTP動詞。

+0

那麼,爲什麼get請求會進入方法?它不應該簡單地放在端點上嗎? – codeputer 2013-03-11 11:39:10

+0

另外,因爲這只是傳遞請求,爲什麼錯誤?內容類型爲空,操作是GET,爲什麼違規? – codeputer 2013-03-11 11:50:39

+0

Tony - 請參閱我上面的評論 - WebInvoke/WebGet在這裏沒有意義,因爲Action和ReplyAction都設置爲「*」,返回類型爲Message。這意味着所有消息都被路由到這個接口。 – codeputer 2013-03-17 22:34:58