我正在努力将服务的绑定从Restful http更改为netTcp,用于IIS 7上托管的一组应用程序服务。restful配置使用路由表,并基于a动态创建端点命名约定和依赖注入。由于我们现在需要在事务块(DTS)中调用它们,因此我们将这些服务转换为Net Tcp绑定。
我希望能够通过使用的约定模型和依赖注入来保持路由,而不是拥有大量凌乱的.svc文件。我知道ASP路由表不适用于其他绑定。对替代品的任何建议?自定义HttpModule可以做到吗?
谢谢, 亚伦
答案 0 :(得分:4)
不,net.tcp绑定没有直接等效的ASP.NET RouteTable。并且自定义HttpModule不会有帮助,因为它只适用于HTTP;)
但是,您仍然可以做一些事情。首先,如果您不希望每个服务都有.SVC文件,您可以利用新的(WCF 4)基于配置的服务激活,它允许您在应用程序中声明所有WCF服务&# 39; s Web.config(在system.serviceModel中),如下所示:
<serviceHostingEnvironment>
<serviceActivations>
<add relativeAddress="Service1.svc" service="MyNamespace.MyService1"/>
<add relativeAddress="Foo/Service2.svc" service="MyNamespace.MyService2"/>
<add relativeAddress="Bar/a/Service3.svc" service="MyNamespace.MyService3" factory="System.ServiceModel.Activation.ServiceHostFactory"/>
</serviceActivations>
</serviceHostingEnvironment>
注意:
ServiceHostFactory
,即如果您正在使用其他工厂类型(例如WebServiceHostFactory或自定义工厂类型),则只需指定它.svc
扩展名,因为默认情况下已在根Web.config中声明了该扩展名。但是,这种方法至少允许您在一个地方定义所有服务(而不是多个.svc 文件) - 在这方面,它与{{1 }}
现在,如果你被.svc扩展所困扰,你甚至可以更进一步。 WCF4中的另一个新项目是路由服务(请参阅http://msdn.microsoft.com/en-us/library/ee517423.aspx),它是一种通用WCF服务,它接收消息以便根据各种标准将其转发到其他WCF服务(如SOAP标头) ,消息内容,端点地址等。)。
使用路由服务,您可以定义各种EndpointAddress过滤器(例如,net.tcp:// {routing-service-base} / service1,net.tcp:// {routing-service-base} / service2等。) - 它让你更接近ASP.NET路由。
但是,如果您在IIS中托管路由服务本身,显然,那个仍然会以RouteTable
基地址结束!
如何绕过最后一个限制(例如,如何在一个漂亮的URI上托管路由服务本身,如 net.tcp:// servername / XYZServices )的唯一方法是例如,在Windows服务中自行托管路由服务 - 这使您可以完全控制其基址。然后,您可以继续在IIS中托管实际的目标服务 - 扩展名为.svc - 并且您的路由服务将转换&#34; nice&#34;公共URI进入IIS .svc的。
但是,放弃IIS / AppFabric托管只是为了获得不错的URI,这是一个艰难的决定。我可能不会这样做。希望你至少可以使用其中一些:)
答案 1 :(得分:2)
这个问题答案已有近一年的历史了。不过,我遇到了同样的问题。
简短的回答是你已经发现的。它不起作用。然而,这从未阻止我们。稍后进行的一些研究以及对激活机制的一些“潜入”提供了以下工作解决方案:
public class CustomRouting
{
public static void Route(string routePrefix, ServiceHostFactoryBase serviceHostFactory, Type serviceType)
{
var serviceHostingEnvironment = new StaticReflectionWrapper(typeof (ServiceHostingEnvironment));
serviceHostingEnvironment.StaticMethod("EnsureInitialized");
var hostManager = serviceHostingEnvironment.GetStaticField("hostingManager");
var hostingManager = new InstanceReflectionWrapper(hostManager);
var normalizedAddress = hostingManager.Method<string>("NormalizedRelativeAddress", routePrefix);
var serviceActivation = new KeyValuePair<string, string>(normalizedAddress, string.Format("{0}|{1}|{2}", normalizedAddress, serviceHostFactory.GetType().FullName, serviceType.FullName));
hostingManager.GetField<Hashtable>("serviceActivations").Add(serviceActivation.Key, serviceActivation.Value);
var tD = StaticReflectionWrapper.Resolve(typeof (ServiceHostingEnvironment).Assembly, "TD");
if (tD.StaticMethod<bool>("CBAEntryReadIsEnabled"))
{
tD.StaticMethod("CBAEntryRead", routePrefix, serviceActivation.Key);
}
ServiceHostingEnvironment.EnsureServiceAvailable(serviceActivation.Key);
}
}
辅助类StaticReflectionWrapper和InstanceReflectionWrapper只是辅助类,以保持反射的可读性。
您使用Route方法如下:
var fact = new CustomServiceHostFactory();
CustomRouting.Route("DynamicServices/" + service.GetType().Name + ".svc", fact, service.GetType());
服务变量是ServiceContract的实现。
自行承担使用此风险,因为这实际上会降低到我们不应该来的地区。然而,它有效。
希望这会缩短很多人的搜索时间,并且会关闭。