C# WCF数据服务中的自定义路由
我需要为WCF数据服务创建一个自定义路由,该服务包含一个必须提取以用于过滤数据的段 例如: 我需要从路线中提取客户123。看起来Route类可能提供类似的功能,但我不确定如何为数据服务实现IRoutHandler 这条路对吗?有好的例子吗 蒂亚 更新: 通过在IDispatchMessageInspector中重新编写一些自定义URL,我成功地实现了所需的解决方案。下面的代码是我最初的破解,需要一系列的清理。但是,它似乎在起作用。如果有人发现有什么大问题,请告诉我C# WCF数据服务中的自定义路由,c#,c#-4.0,wcf-data-services,C#,C# 4.0,Wcf Data Services,我需要为WCF数据服务创建一个自定义路由,该服务包含一个必须提取以用于过滤数据的段 例如: 我需要从路线中提取客户123。看起来Route类可能提供类似的功能,但我不确定如何为数据服务实现IRoutHandler 这条路对吗?有好的例子吗 蒂亚 更新: 通过在IDispatchMessageInspector中重新编写一些自定义URL,我成功地实现了所需的解决方案。下面的代码是我最初的破解,需要一系列的清理。但是,它似乎在起作用。如果有人发现有什么大问题,请告诉我 public obj
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;
}
}
}
}
谢谢大家 我假设这是一个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 /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服务做到这一点。除非我完全误解了你的意思,否则我很乐意尝试更新我的答案,另一个选择是使用从。。这将允许您直接访问URI。缺点是您必须使用Uri.Segments进行解析,然后将另一段代码绑定到Uri格式 您的问题最终源于一个事实,即WCF尽管声称不支持REST。REST应该是在URI标识的资源上进行的一组操作。相反,WCF提供了一个“静态”端点和一组比真正的REST更类似于旧的SkoolXML/SOAP的方法 我个人发现,在处理作用于URI/资源的REST服务时,WCF非常有问题。坦率地说,它没有什么价值,只是起了阻碍作用。有很多REST架构,很多都有相同的限制。您可以考虑WCF上的BAILD,并找到一个支持您想要公开的格式的有效载荷序列化库。
我目前最喜欢的是支持XML、JSON、协议缓冲区和URI编码的消息。有一个简单的介绍。尽管此示例也是一个服务端点,而不是基于资源的REST,但底层序列化模式确实是您所追求的。在您的域中,
client123
代表什么?典型的情况是http://mysample.net/mysamplesvc/Users?client=client123
但我想这不是你想要的?@oleksii:它实际上是我们saas产品的客户或租户。我们的想法是需要这个id,并通过查询参数来要求它,这似乎有点尴尬,与我们使用其他RESTful服务所做的不匹配。我也通过注册serviceroute来尝试实现此路由。问题在于,服务路由中似乎不支持占位符。请帮忙-感谢您的快速响应。这实际上不是一个MVC项目,不幸的是,我使用的是一个带有WCF数据服务的标准web项目。我没有尝试将MVC与WCF数据服务一起使用。你知道这是否可能吗?如果是的话,这可能是我的灵丹妙药,因为我对MVC路由更为熟悉。是的,你可以将WCF与MVC结合使用。不过,我并不完全确定路由,因为我通常通过foo.com/service.svc
访问它,我会自己测试,但我正在测试VS 11,MS知道WCF数据服务模板有问题。对不起,但是你知道在ASP.net MVC应用程序中托管WCF数据服务的好例子吗?我似乎找不到任何适合我的情况。主要是将MVC站点绑定到WCF数据服务的示例。谢谢斯科特·汉斯曼(Scott Hanslmen)是一名关于使用SOs数据库的专家,而netflix odataThanks则负责休息。这是非常宝贵的。不幸的是,我不能完全确定我是否能够支持protobuf,因为我需要支持WCF数据服务的OData功能。还是我遗漏了什么?作为一种选择,我考虑使用WebOperationContext,但随后需要在没有clientid的情况下重新编写请求,以避免数据服务认为Client123是EF资源。我一直在摆弄这个,但我有点笨手笨脚。@RockyMountainHigh是的,如果你需要odata,你就卡住了。URL重写可能是最好的选择。我本想提出这个建议,但听起来你已经开始了:)有很多很棒的建议,但是@csharptest.net让我最接近我的最终解决方案,无论是对是错。谢谢