让DomainService暴露在其他客户端

       我们往往在在新建Wcf ria service时,通常是再silverlight中添加Wcf ria service的,但是微软说过Wcf ria service也是一种特殊的wcf ,wcf 能暴露在其他客户端,那么wcf ria service也应能暴露在其他客户端,列入winform ,wpf等!下面记录下如何将wcf ria service 暴露到其他客户端让winform,wpf调用。这里我以winform调用wcf ria sercice为列来说明。

  (一)暴露OData端点
       1. 关于OData
        (1)OData是Open Data Protocol(开放数据协议的缩写,它是REST-base的web service协议暴露数据通过web services查询,而且可选择通过web service惊醒更新操作。你可以在 http://www.odata.org/ 上研读相关Odata相关资料
        (2)OData用的是ATOM协议编码从你服务流出或流入的RES 消息中HTTP body部分的数据的。
        (3)OData允许你快递一个复杂的查询通过服务地址的URL的参数
        (4)OData支持部分普通LINQ查询操作像Filtering(where),投影(select)分页(Take,Skip)
        (5)除此之外,OData还允许你发送Insert,Update,Delte
       2. 关于Wcf ria service与OData
        RIA Service允许你在Domain Service中只能暴露查询的OData端点
        这个暴露只提供了获取整个集合的查询方法,你不能传递过滤或分页操作到到服务通过OData协议
        所以功能在此版本的Wcf ria service相当的受限,将来的Wcf ria Services将可能支持更新操作或者更复杂的查询操作
        但是现在你只能调用Domain Service查询方法和从服务器上返回没有过滤的集合到客户端

     3.在新建domain server时,如下图就行了

    4.订阅暴露OData端点的服务
     (1)添加服务时的服务格式为(以我当前的Demo为例):http://localhost:5187/WcfRiaServiceDemo-Web-CatalogService.svc/odata,斜杠后面的odata千万别忘了,如图:

     (2)客户端调用代码,这种方式不会在客户端生成配置文件(app.config,ServiceReferences.ClientConfig等),需要自己写代码中,如果想灵活处理,可以在服务器端的配置文件中填写,然后读取到客户端。

 public Form1()
{
InitializeComponent();
string strUri="http://localhost:5187/Services/WcfRiaServiceDemo-Web-CatalogService.svc/odata";
Uri uri = new Uri(strUri);
ODataClientWinForm.ServiceReference1.CatalogService client = new ServiceReference1.CatalogService(uri);
List<Catalog> catalogs= client.CatalogSet.ToList<Catalog>();
}

    小结:这种暴露方式虽然很简单,但操作受限,只能去集合,如果我们只取部分数据,我们需要把整个结合取到,在再客户端过滤,这种效率很低,且又不能进行更新,删除、添加操作。所以就有下面的通过暴露SOAP 端 

 (二)暴露SOAP端

      1.关于SOAP
    (1)如果你想执行复杂的查询和更新操作在其他客户端,你可以通过暴露SOAP或者JSON端来实现
    (2)你需要下载Ria Services Tookit,添加引用icrosoft.ServiceModel.DomainServices.Hosting.dll程序集(我的版本是v1.0)
        程序集路径为:C:\Program Files\Microsoft SDKs\RIA Services\v1.0\Toolkit\Libraries\Server
    (3)SOAP端是WCF basicHttpBinding兼容端以便很容易被其他任何平和订阅,为添加SOAP端,你必须在domainServices节点在你的web.config文件中
     子啊添加OData端地方
    2. 在.NET客户端订阅SOAP端消息
    (1)你在只需要在客户端添加服务引用,就跟添加WCF Service一样,WCF RIA Service数据服务的格式为:http://[hostname]/[namespacename]-[classname].svc
      这里的服务为http://localhost:5187/WcfRiaServiceDemo-Web-CatalogService.svc,他会产生在客户端(WinForm 中的app.config)或(Silverlight 中 ServiceReferences.ClientConfig)
    (2)SOAP端的处理是最复杂的,是通过包装贼ChangeSetEntries的改变中,这种类型支持发送原始实体和修改的入口和主动的一致性减产以便服务端能优化查询知道哪些属性已经改变。除了包装的实体外,还有只是通常WCF proxy-based服务调用

 public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
SOAPClientWinForm.ServiceReference1.CatalogServicesoapClient client = new CatalogServicesoapClient();
QueryResultOfCatalog result = client.GetCatalogs();
Catalog[] catalogs= result.RootResults;

//编辑
ChangeSetEntry changeEntry = new ChangeSetEntry();
Catalog catalog = catalogs[0];
catalog.CatalogName = "21211";
changeEntry.Entity =catalog;
changeEntry.Operation = DomainOperation.Update;
client.SubmitChanges(new ChangeSetEntry[] { changeEntry });

//添加
//ChangeSetEntry changeSet = new ChangeSetEntry();
//Catalog catalog=new Catalog();
//catalog.CatalogName="Add by SOAP Client";
//catalog.CatalogParentID=1;
//changeSet.Entity = catalog;
//changeSet.Operation = DomainOperation.Insert;
//client.SubmitChanges(new ChangeSetEntry[]{changeSet});

//删除
//ChangeSetEntry changeSet = new ChangeSetEntry();
//changeSet.Entity = catalogs[4];
//changeSet.Operation = DomainOperation.Delete;
//client.SubmitChanges(new ChangeSetEntry[] { changeSet });
//Catalog[] newFetchCatalog = client.GetCatalogs().RootResults;

client.Close();

}
}

    (3)安全机制方面,为落实端的安全,你仅仅只需要要再Domain Service上添加[RequiresAuthentication]属性标记符,在客户你只需要做Session或者Cookie验证
 (三)暴露REST/JSON端点
 1.只需要在配置文件中添加如下

<!--
要添加Microsoft.ServiceModel.DomainServices.Hosting.dll程序集
<程序集路径为:C:\Program Files\Microsoft SDKs\RIA Services\v1.0\Toolkit\Libraries\Server
-->
<add name="JSON"
type
="Microsoft.ServiceModel.DomainServices.Hosting.JsonEndpointFactory, Microsoft.ServiceModel.DomainServices.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />



这样你可以用你喜欢的方式像WebClient或者HttpWebRequest发布或者请求REST端而且用WCF DataContractJsonSerializer编码和解码JSON负载在HTTP body的消息
地址模式是基于WCF服务的地址模式以便你可以通过REST暴露,例如调用GetCatalog方法,你只需要输入http://localhost:5187/WcfRiaServiceDemo-Web-CatalogService.svc/json/GetCatalogs

2.关于订阅暴露的JSON的DomainService,这里在讲解。下面有篇文章

How to open a WCF RIA Services application to other type of clients: the JSON endpoint,这个可以用于HTML5的数据传输服务

总结:

    研究这个问题花了好多时间,在前面的一篇文章 《Silverlight多个系统独立系统,通过一个登陆入口登录的问题 》中提到的其他类型的Client端怎样调用外部的Wcf ria service,终于解决了,发现一个个问题解决慢慢的前进,这个过程是艰难和痛苦的,但最后能解决问题,也能学到新的东西也挺高兴的,觉得以后多看下老外的文章,能快速解决掉问题和学习新的东西。 开始的时候同一个命名空间下的其他Client端可以调用,但外部不能调用,后来这个问题也解决了,我做的一个实验 新建一个解决方案InvokeWcfRiaService,调用wcf ria service成功,但是出现跨域的问题,下一篇将仔细研究跨域和动态引用wcf ria service暴露的服务地址。

     虽然问题解决了,但公司VSS中的wcf ria service虽然可以添加引用,但不能正确生成,但单独的可以。这个问题很怪,弄的我狠郁闷!还得仔细研究!

 源代码下载

 参考文章:

WCF RIA Services Part 10 - Exposing Domain Services To Other Clients

 

 

posted @ 2011-10-14 21:03  焦涛  阅读(2060)  评论(0)    收藏  举报