c# - WCF 数据服务中的自定义路由

标签 c# c#-4.0 wcf-data-services

我需要为 WCF 数据服务创建一个自定义路由,其中​​包含一个必须提取以用于过滤数据的段。

例子:

http://mysample.net/mysamplesvc/client123/Users

我需要从路由中提取 client123。看起来 Route 类可能提供类似的东西,但我不确定如何为数据服务实现 IRouteHandler。

这是正确的路径吗?周围有好的例子吗?

TIA!

更新:

我已经设法通过在 IDispatchMessageInspector 中重写一些自定义 URL 来实现我需要的解决方案。下面的代码是我最初的黑客攻击,需要大量清理。但是,它似乎正在工作。如果有人发现任何错误,请告诉我。

    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;
                }
            }

        }
    }

谢谢大家!

最佳答案

另一种选择是使用 IncomingWebRequestContextWebOperationContext获得. IncomingRequest .这将允许您直接访问 URI。缺点是您必须使用 Uri.Segments 进行解析,然后将另一段代码绑定(bind)到 uri 格式。

你的问题最终源于这样一个事实,即 WCF,就其所有声明而言,不支持 REST。 REST 应该 是一组发生在由 URI 标识的资源上的操作。相反,WCF 提供了一个“静态”端点和一组比真正的 REST 更类似于老式 XML/SOAP 的方法。

在处理作用于 URI/资源的 REST 服务时,我个人发现 WCF 非常有问题。坦率地说,它提供的值(value)很小,而且只是碍事。那里有很多 REST 架构,许多都受到同样的限制。您可能会考虑放弃 WCF 并找到一个支持您想要公开的格式的有效负载序列化库。

我目前最喜欢的是 protobuf-csharp-port它支持 XML、JSON、 Protocol Buffer 和 URI 编码消息。里面有简介building a REST service using protobuf-csharp-port .尽管此示例也是一个服务端点而不是基于资源的 REST,但底层序列化模式正是您所追求的。

关于c# - WCF 数据服务中的自定义路由,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8438233/

相关文章:

c# - 如何在 C# mongo 驱动程序中设置复数集合名称?

c# - Xamarin Build Error 编译无法完成,因为缺少一些库类

asp.net-mvc-3 - 如果填充了另一个字段,则 MVC 3 字段为必填字段

javascript - JayData 创建对象未按预期工作

windows-8 - 如何将自定义授权 header 添加到Windows Store App OData客户端?

c# - wcf 类库中的 WCF 数据服务(让客户端通过该服务与数据库对话)

c# - 如何检查正在单击哪个按钮? Visual Studio C#

c# - 将普通类转换为 Web 服务类时出现 System.NotSupportedException 的原因

c# - 如何计算 Nullable<T> 数据类型的大小

c# - 找出在DeSerialization过程中是否调用了property setter