更新:我在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,所以我不確定爲什麼會有任何內容。
所以:
- 我想我做的,是造成我一個問題的代碼的東西 - 如果,所以我想知道是什麼!
- 如果傳入請求中有某些內容,我該如何刪除它以免違規?
- 任何其他建議,對代碼的改進?
因此......接口只指定WebInvoke,而不指定WebGet ......那麼它爲什麼會允許GET請求被中繼到服務中呢?使用這樣的通用接口,我必須以不同方式處理GET和POST嗎?在這兩種情況下,我都不會觸及請求主體... – codeputer 2013-03-10 23:27:20
GET請求被中繼的原因是因爲Action和ReplyAction都指定了「*」,這意味着所有消息都在這裏發送。然後在這個接口上有一個WebInvoke屬性就少點了! – codeputer 2013-03-17 22:32:23