[英]Custom routing in WCF data services
我需要為WCF數據服務創建自定義路由,該服務包含必須提取以用於過濾數據的段。
例:
http://mysample.net/mysamplesvc/client123/Users
我需要從路由中提取client123。 看起來Route類可能提供類似的東西,但我不確定如何為數據服務實現IRouteHandler。
這是正確的道路嗎? 周圍有很好的例子嗎?
TIA!
更新:
我已經設法通過IDispatchMessageInspector中的一些自定義URL重寫來實現我需要的解決方案。 下面的代碼是我最初的hack,需要一堆清理。 但是,它似乎有效。 如果有人看到任何錯誤,請告訴我。
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
{
HttpRequestMessageProperty httpmsg = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
...Additional logic for handling Query formats in OData
UriTemplate template = new UriTemplate("mysamplesvc/{ClientId}", true);
Uri prefix = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Authority));
Uri uri = new Uri(HttpContext.Current.Request.Url.AbsoluteUri);
UriTemplateMatch results = template.Match(prefix, uri);
if (results != null && !string.IsNullOrEmpty(results.BoundVariables["ClientId"]))
{
_clientId = results.BoundVariables["clientId"].ToString();
}
if (!string.IsNullOrEmpty(_clientId))
{
httpmsg.Headers.Add("ClientId", _clientId);
rewriteRequest();
}
return null;
}
private void rewriteRequest()
{
if (HttpContext.Current != null && HttpContext.Current.Session != null)
{
if (WebOperationContext.Current.IncomingRequest.UriTemplateMatch != null)
{
Uri serviceUri = HttpContext.Current.Session["ServiceUri"] as Uri;
Uri requestUri = null;
UriTemplateMatch match = WebOperationContext.Current.IncomingRequest.UriTemplateMatch;
if (serviceUri == null)
{
UriBuilder serviceUriBuilder = new UriBuilder(match.BaseUri);
serviceUri = serviceUriBuilder.Uri;
HttpContext.Current.Session["ServiceUri"] = serviceUri;
}
if (serviceUri != null)
{
OperationContext.Current.IncomingMessageProperties["MicrosoftDataServicesRootUri"] = serviceUri;
UriBuilder requestUriBuilder = new UriBuilder(match.RequestUri);
string path = string.Empty;
if (match.RelativePathSegments[0] == _clientId)
{
foreach (var seg in match.RelativePathSegments.Select((x, i) => new { Value = x, Index = i }))
{
if (seg.Index != 0)
{
path += "/";
path += seg.Value;
}
}
}
else
{
foreach (var seg in match.RelativePathSegments.Select((x, i) => new { Value = x, Index = i }))
{
path += "/";
path += seg.Value;
}
}
UriBuilder serviceUriBuilder = new UriBuilder(match.BaseUri + path);
// because we have overwritten the Root URI, we need to make sure the request URI shares the same host
// (sometimes we have request URI resolving to a different host, if there are firewall re-directs
serviceUriBuilder.Host = serviceUri.Host;
requestUri = serviceUriBuilder.Uri;
OperationContext.Current.IncomingMessageProperties["MicrosoftDataServicesRequestUri"] = requestUri;
OperationContext.Current.IncomingMessageProperties["Via"] = requestUri;
}
}
}
}
謝謝大家!
另一種選擇是使用從WebOperationContext獲得的IncomingWebRequestContext 。 IncomingRequest 。 這將允許您直接訪問URI。 缺點是您必須使用Uri.Segments進行解析,然后將另一段代碼綁定到uri格式。
你的問題最終源於這樣一個事實,即WCF聲稱它不支持REST。 REST 應該是由URI標識的資源上發生的一組操作。 相反,WCF提供了一個“靜態”端點和一組比真正的REST更類似於old-skool XML / SOAP的方法。
在處理作用於URI /資源的REST服務時,我個人發現WCF非常有問題。 坦率地說,它提供的價值很小,只是妨礙了。 有很多REST架構,許多都受到同樣的限制。 您可能會考慮在WCF上進行救援並找到支持您要公開的格式的有效負載序列化庫。
我目前最喜歡的是protobuf-csharp-port ,它支持XML,JSON,協議緩沖區和URI編碼消息。 使用protobuf-csharp-port簡要介紹如何構建REST服務 。 雖然此示例也是服務端點而不是基於資源的REST,但基礎序列化模式實際上就是您所追求的。
我假設這是一個MVC項目
我認為,MVC中的典型路由是這樣的:
//url looks like /controller/Details/42
public ViewResult Details(int id) {
//do something
}
您可以添加如下自定義路線:
routes.MapRoute(
"my special little route", // Route name
"customer/{Cid}/programs/{Pid}",
new { controller = "customer", action = "Details" }
);
所以視圖看起來像:
//url looks like /customer/{21}/programs/42
public ViewResult Details(int Cid, int Pid) {
//do something
}
所以理論上你應該能夠為你的WCF服務做到這一點。 除非我完全誤解你在說什么,我會樂意嘗試更新我的答案
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.