簡體   English   中英

WCF數據服務中的自定義路由

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM