今天WCF Data Service部署在支持net.tcp的IIS站点上时会出现问题,通过分析和查找相关资料有了一些结论。
http://www.rajneeshnoonia.com/blog/2009/12/ria-wcf-configuration-finally-resolved/ 这个是在VS2008下的早期版本正常,新的VS2010不可用
框架默认支持的绑定在web.config设置了
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
在服务类中设置了[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
可见IIS的运行采用的就不是WAS形式,而是和Asp.net混合的形式,这种情况下,需要支持net.tcp的WCF服务无法在IIS中承载如何查看已有的绑定的Endpoint的配置信息:
默认的服务是由DataServiceHostFactory管理的,*.svc的文件中可以看到,此时我们可以继承该类然后就可以查看或修改
默认的配置
//System.Data.Services.DataServiceHostFactory, System.Data.Services
public class MyDataHostFactory : DataServiceHostFactory
{
protected override System.ServiceModel.ServiceHost CreateServiceHost(Type serviceType,Uri[]
baseAddresses)
{
return new MyDataServiceHost(serviceType, baseAddresses);
}
}
public class MyDataServiceHost : DataServiceHost
{
//User to add custom logic here as desired
public MyDataServiceHost(Type domainServiceType, params Uri[] baseAddresses)
: base(domainServiceType, baseAddresses)
{
Debug.WriteLine("data svc");
}
}
[AttributeUsage(AttributeTargets.Class)]
public class MyServiceBehaviorAttribute : Attribute, IServiceBehavior
{
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ServiceEndpoint endpoint in serviceHostBase.Description.Endpoints)
{
foreach (OperationDescription operation in endpoint.Contract.Operations)
{
Debug.WriteLine(operation.Name);
}
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
[MyServiceBehavior]
public class NorthWindService : DataService< NorthwindEntities >
然后设置svc中的服务承载:
<%@ ServiceHost Language="C#" Factory="DataServices.Web.Services.MyDataHostFactory"
Service="DataServices.Web.Services.NorthWindService" %>
在VS跟踪器中可以查看到Endpoint和其对应的ABC信息,当然我们在这修改一些Behavior Binding等信息以改变默认的行为,以实现定制,而且定制也仅限于此,如果想进行Endpoint的定制那就比较复杂了,见下一节。
以上把断点设置在Debug.WriteLine可以跟踪看到默认实现的DataServiceHost的绑定和契约如下
Binding : WebHttpBinding
Contract: System.Data.Services.IRequestHandler
错误现象
如果部署在IIS中,只要IIS支持net.tcp,就会出现如下错误
The provided URI scheme 'net.tcp' is invalid; expected 'http'. Parameter name: context.ListenUriBaseAddress
WCF DataService的默认实现的是不支持TCP的,不过Silverlight4已经可以支持tcp协议,因此增加这个形式的支持看来也是必要的,下一个版本不知能否增加。
实际中为什么需要TCP
假如我们在既支持远程又支持局域网环境下时下了WCF Service,同时又想类似WCF Data Service公布一个数据服务【这样对于数据的操作符等语法和WCF Data Service一致,那我们对于服务接口可以简化很多,不用自己反复写了,否则WCF 的查询和操作方法都要定义】,那tcp对于局域网是 更好的选择
分析已有的组件可以更清楚如何去做:
System.Data.Services.dll: 包含了服务的承载和默认的Endpoint和属性加入以及实现HTTP请求处理的HTTPModule,这样就实现了请求上来的HTTP请求自动跳转到服务上,同时默认实现的一些查询等可以直接使用
System.Data.Services.Client.dll: 负责客户端代理的linq查询和其他操作合成成符合WCF Data Service形式的请求发到服务端
其中一个关键类System.Data.Services.Client.DataServiceContext
如上,两者配合实现客户端可定制的各种查询和操作同时服务端通过一个框架支持,不用再编写重复的代码了。支持net.tcp也就是在这些基础库上增加一个Endpoint,虽然是使用reflector可以看到大概,不过要实现估计还是比较大的工作量,如果自己写个框架,那可以按照以上两个组件的思路处理就可以实现WCF Data Service形式的服务,不过这个是一个框架的活,希望在下一版本的WCF Data Service能提供这样的支持。
以上的跟踪为了清楚的看到客户端端代理在LINQ基础上传递的HTTP请求,可以使用Http Analyzer或其他工具查看详细信息
现有的软件如何做
对于既部署了tcp形式的wcf服务又想使用WCF Data Service的项目一个常见的可能解决方法:
将TCP服务和http协议的服务部署在IIS中的一个根应用下
将wcf data service部署在该根下的一个子应用下
参考: