遇到麻烦了!
嗯,让我先来整理一下思路,如何讲清楚这个问题。好的,就让我们这样来说吧,首先我们创建两个Project,第一个Project是Class Library,即类库的,里面有一个实体类及一个控制类,假设实体类如何下:
public class User
{
public User()
{
}
private string name;
private int age;
private DateTime birthDay;
public string Name
{
get{return this.name;}
set{this.name=value;}
}
public int Age
{
get{return this.age;}
set{this.age=value;}
}
public DateTime BirthDay
{
get{ return this.birthDay;}
set{ this.birthDay=value;}
}
}
然后再做一个控制类,里面就一个方法,这个方法返回一个User[]的数组。
public User[] GetUser(){…}
OK,第二个Project是一个ASP.NET的Web应用程序,并且引用上面的这个Class Library,在其默认ASP.NET页面上放一个DataGrid,然后这个DataGrid的数据源指定为上面那个项目中的控制类的方法,即将DataGrid1绑定到一个User[]数组上,大家可以试一下,这是可以成功的。因为DataSource的数据源可以为实现了System.Collections.IEnumerable接口的对象,而数组类型是继承自System.Array的,System.Array实现了System.Collections.IEnumerable接口。
但是接下来,我们引入Web Service,即先解除ASP.NET的Web应用对于Class Library的引用关系,然后Web Service引用Class Library,而ASP.NET通过Web引用建立与Web Service项目的联系。如下图所示
ASP.NET__WEB引用__Web Service___引用____Class Library
在Web Service项目当中,建立一个Web Method对Class Library进行一下Wrap:
[WebMethod] public User[] GetUser()
{
//直接调用Class Library中的GetUser方法,并且返回其结果;
}
然后在ASP.NET的默认ASP.NET页面中调用此Web方法,进行数据绑定,现在再查看,肯定会得到一个异常,说无法绑定。
我追踪了一下午,基本上发现了问题所在:
- 当加入Web Service的时候,ASP.NET将User类进行了一个包装,注意,这时候的User不是Class Library中定义的User类了,而是Web Service Client端由VS.NET自己定义的一个User类;
- Web Service中的这个User类所创建的数组无法进行数据绑定,甚至无法将这个类的数组通过强制类型转换转换为Class Library中声明的那个User类的数组。
问题就是这样,但解决方案尚未出来,希望哪位大侠不吝赐教!
需求又出来新版本了,数据库设计也基本上出来了。不过今天晚上他们又要去需求方汇报,不知道需求是不是还会改?
周末拜见了岳父岳母大人,已经正式取得合法的恋爱执照了
恭喜告别无证驾驶的岁月
只有你取得而已,还差你GF的
User都没有序列化,怎么可以可以???
我想WebService那里就Error了:)
合法的恋爱执照? cool
我GF上上周就见过我父母了:D
你可以将一个一个对象放入Array 类的对象中,在Web Service中传Array对象
TO 开心:
不要使用IDE添加web ref的方法来使用web service,这样子我们无法方便的对代理类编写(刷新web ref后改动就被覆盖了)。
可以使用wsdl程序生成代理类,然后把自动生成的User类那段代码去掉,把此代理类中所有“User”字符串替换为你定义的User。
这样是可以的,试试
To 小峰:我用过ArrayList了,将User压入ArrayList传给客户端,但仍然有问题。所以我想与这个无关,应该是小气的神所提出来的方式吧?
To ccBoy:Web Service那儿倒没有Error,原来直接试过,是可以的。你所说的User序列化,是实现ISerializable接口,还是在特性中直接声明其是可序列化的,即加上[Serializable]?
To Mic:这样肯定是可以的,但降低了开发效率。而且最主要的是,我不想让ASP.NET Web应用再添加对Class Library的引用。也就是说,Web Service作为完全绝缘的隔离层。
Congratulations
Many thanks 😀
哈哈,恭喜恭喜,又一对幸福的人:P
问题已经解决了:D,根据Mic的提示,我发现添加Web Service后,它生成的代理类会将User声明为如下
public class User
{
public string Name;
public int Age;
public System.DateTime BirthDay;
}
我只要将其扩展为属性的声明方法就正常了。
看来VS.NET代理类的编写人员是够懒的。不过如何更改一下呢?希望微软的人员可以向上反应一下。
这与序列化无关。
@开心:
可是小心:这个文件是自动生成的,只要你一更新Web引用,你作的这些改动就都over了!至于说为什么生成的User代理类中所有的属性都变成了普通实例成员,你应该还发现所有的方法都不会出现在这些类中吧?一个属性等于两个属性访问器方法,因此属性更不可能出现在这些用于串行化的类了。这可不是什么代理类的人员够懒噢!:)
其实还是得提醒你,应用内部层间调用是不应该使用Web Services的!这样做不仅很影响性能,也因为Web Services引入的更受限的类型系统而使得整个应用程序内部的调用过分松藕,实属得不偿失啊。请再三思吧!:)
呵呵,我刚刚想说生成的代理类是public field,没有用属性。这样的类是不能作为DataSource的
JGTM:
为什么没有方法呢?
@开心:
实在要用Web Services做你内部的facade接口的话,可以考虑使用DataSet/DataTable等返回数据用于界面数据绑定。XmlDocument也是可以考虑的。本来Web Services的类型系统就相对弱,你还要使用很依赖于类型系统的数据绑定,那肯定是会遇到问题的。
其实问题还不仅如此,当你开始测试性能的时候,你还会遇到HTTP连接数量限制、线程池限制等等……不过也有办法,就是可以考虑使用异步请求处理,这样可就真是得不偿失了。
其实Web界面层(人-机界面)直接使用你的业务层一点儿问题也没有,而web services其实严格讲算是界面层(机-机界面),你用它做内部隔离有什么特别的道理吗?
@kkwoof:
看到你这个问题我话匣子就要开……不过先简单说吧,为什么WS代理类中那些在参数中出现的类型被“压缩成了”只有简单数据成员的类了呢?因为在调用WS的过程中只用到这些类型的"值",这些类型实际都是远程类型,实际上你根本不知道也不必知道它有哪些方法。WS调用是service-oriented而不是object-oriented,在面向服务的架构中传输的只是document,而不是object。包括在设计松藕的、跨平台的、面向服务的应用架构的时候,其实设计师关注的核心是在服务间需要传递的document及其schema,而在设计平台内、面向对象的软件架构的时候设计师考虑的是对象实例的传递和其类型的关系,这是两种截然不同的视角。
很多人不很理解Web Services和.NET Remoting的本质区别,其实这就是最本质的一个。因此在设计和实现web services的时候记住:Messages, not Methods。:)
JGTM’2003:有道理,又长一智!
JGTM’2003,
返回DataSet可不是平板对象哦^_^
从开心的代码看来是一个典型的DTO(Data Transfer Object)模式
目前.NET中有三个方法可以实现
1。使用DataSet实现DTO
2。使用Typed DataSet实现DTO
3。使用Serialized Object来实现DTO
DSP中已经分别说了,看来开心一样也没有用:) DataSet自动实现序列化,方法三是需要你手动的控制序列化。
对于Web Services诸位不会是只知VS.NET和IDE,而不知道WSDL/Schema吧,我想不是编写VS.NET编写代理类的人懒,而是你没有告诉他该怎么做吧:)
从架构上讲
ASP.NET–WEB引用–Web Service–引用—Class Library
的架构是"传奇中"的架构,但事实如JGTM’2003 所言,性能极差,Web Services必是瓶颈
JGTM’2003 讲Web Service适用于面向服务的应用,但并没有讲明什么样的情况下在我们用Web Services,Web Services绝非只为了松散耦合,ESP说:
Web service最好用于使用服务的应用程序无法控制远程服务,或者必须在不同的编程语言或平台之上的解决方案或产品需要互交互.
开心为什么你一定要用Web Service? 🙂
需要Review一下你的架构和设计,是否你的项目组中有许多J2EE背景的成员,甚至很多时候你在和他们战斗?
ps:
ESP –Enterprise Solution Patterns Using Microsoft.NET V2.0
sorry ,
原文:
Service-Based Collaboration works well in scenarios where the consuming application does not have any control over the remote services or has to interoperate with solutions developed on top of different programming languages or platforms.
意思应该是互操作而不是"互交互" —:)
^@^
我说一下我目前的使用策略吧
1。WebService的传递,我基本上都是用简单类型。业务实体主要方式是DataSet,因为我使用Typed DataSet,所以向下兼容DataSet。我只要再实现一个从DataSet到业务实体的构造方法即可。而且所有的业务实体有一个基类,所以所有的代码都很Easy。
2。通过方法类转换,实现可序列化对象<->String,DataTable<->DataSet这种双向转换方法。
3。我很费解的是为啥ASP.NET还要Call Asp.net的Web service
如果你的Web Service没有其他消费者,你根本不用写。
如果你的Web Service有其他消费者,你可以把业务逻辑放到ServicedComponent里面,Web Service对其包装。ASP.NET直接Call ServicedCompoent。
ASP.NET再调ASP.NET将是你的一个性能瓶颈。
To ccBoy
ESP说:
Web service最好用于使用服务的应用程序无法控制远程服务,或者必须在不同的编程语言或平台之上的解决方案或产品需要互交互
没错,不过还要加上,如果领导希望在项目中看到可以炫耀的新技术
don’t beat up on 开心就好, we have discussed this in the last episode, it is beyond his control
by the way, congratulations!
To All:正如Saucer所说,这个项目真的是脱离我的控制,但我不能在这儿诉苦了。如果说这个世界上还有甜蜜的事情,就是12月17日能够早日到来。
Web Service开始只是我在培训的时候向大家演示了一下,然后大家感觉不错,所以我就加了进来了。当然还是有以下的考虑的:
1)需求中有大量的文书处理(可能有35%左右的工作量),而这些处理我们准备使用InfoPath 2003,而InofPath 2003我并不是很熟悉,当时第一个念头是使用Web Service可能更好一些(我现在准备采用的是在服务器态动态生成InfoPath的XML文本,不过我已经向MS申请专人来负责这部分的设计实现了)。第二期中有可能会加上移动式开发,这也是为了未来的一个想法。
2)项目负责人在我刚来的时候,一直询问我如何实现CLB,这也是我引入Web Service的一个原因。当然我应该设计业务外观层包装一下调用,可是现在很多设计完全脱节了。
3)开发起来方便一些,团队成员原来搞.NET的人员没有,就只听过一节.NET的课程,而且部分人员没有参加过B/S的开发,所以我想能够让他们互相看不见。接口完全的隔离出来,相当于两个独立的团队在开发,当然,做ASP.NET层的人员的开发就没有层次概念。
当然,以上理由现在看起来也是很牵强的.
系统内部如果使用 Web Service , 确实影响性能,如果 Service 除了内部使用,还有其它外部的 Consumer ,还是建议内部使用 Service Component ,外部 Cosumer 使用 Service Component 的 Web Service 包装(壳)。
To ccBoy: 关于实体类的设计,我现在的架构设计中的实体类是这样设计的:包含DataSet、Typed DataSet及自定义实体类,即你上面所提的三种我都已经涉及到了。不过自定义实体类我没有考虑序列化问题,这是我失误。
但在实际操作过程当中,我们为了追求项目进度,基本上全部使用了自定义实体类,这也是我的问题。
我的确想把Web Service这一层抽掉它,而只在InfoPath的应用中去使用它,不过我得考虑整个的项目成本。毕竟工作量很大,而进度在压着。
To Moslem:其实在一起打太极系列的前几篇当中,我们已经讨论过这个问题,但是就目前来说,没有时间来讨论这个问题了。我当时只是想简化一下架构设计。
Service Component就我理解,应该是业务逻辑层的模块,我们现在就是把业务逻辑层使用Web Service整个包装起来了,但为了种种考虑,我们没有让ASP.NET直接调用Service Component,而是通过Web Service来调用的。
Web Service里面没有任何业务逻辑,其实就是一个Wrap而已:)
@开心就好:
在Application Architecture for .NET中Service Components有两种,一个是在业务服务层的Service Interfaces,一个是在数据服务层的Service Agent。前者将本业务系统对外提供服务接口,而后者是在本业务系统内使用外面系统提供的服务。
虽然Service Interfaces确实是画在了整个业务服务层的最上面且覆盖了其它三类业务组件,但我想它的意思并不是说要用Service Interfaces来隔离界面服务层和内部的这些业务组件(虽然也有这样用的而且也有道理这样用的,参见文档的通信策略部分)。既然已经选择了.NET作为整个系统的开发和运行平台,实践上看(主要从性能和开发量的角度看)确实得不偿失,*何况*只为了这么一个没有任何逻辑在里面的wrap。;)
这个项目确实很为难你,不过希望我们的讨论对以后的项目和其它朋友的其它项目设计会有参考价值吧!:)
BTW, InfoPath + Web Services, um, smells delicious!
To JGTM’2003:
如果把Web Service拿掉,我如何实现多服务器部署?服务器之间如何通讯呢?
BTW:我也希望通过这样的讨论能够对大家有好处,另外,很多项目的进度其实并不受技术控制的。目前这个团队只有我一个人稍微懂一些.NET,而且我不是项目负责人,所以很麻烦。今天有领导问我,为什么不直接从ASP.NET当中直接调用数据库,所有东西都混合在一起。
上周我感觉团队已经开始朝气蓬勃了,可是现在我感觉大家心情都不怎么样。
看到这里, 学到很多, 也有很多不懂.
请教 开心:
你希望Web Service作为完全绝缘的隔离层, 是否就是要让客户端看不见实体层?
那它操作什么? 操作代理类里的那个user类?
项目的事情还是交给开心,我想他一定能把握得了。
大家也别搞得太复杂,别从完全Web Services转向完全的.NET 设计模式。毕竟项目以实际情况和用户需求而定。
祝开心项目顺利,年底的项目都特别多特别赶
我是来学习的。
顺便祝福.
@开心就好:如果把Web Service拿掉,我如何实现多服务器部署?服务器之间如何通讯呢?
你是想前面的ASP.NET先做个NLB,然后把Web Services这层的服务器再做一个NLB?这样的话部署的整体工作量会加大很多,且不一定有什么回报(就不说性能带来的严重损失了先;)。一般的经验都是在前端服务器统一部署UIC+BC+DAC(组件之间都在AppDomain内通信,BC/DAC一定要做无状态设计和实现),使用NLB + ASP.NET State Server/SQL Server State Server(或者最好在ASP.NET前端也是无状态设计就不用State Server了)实现负载均衡,然后统一访问后端数据存储。你可以参见Application Architecture for .NET P.135的方式。如果你希望采用P.136的方式,建议你使用Remoting w. TCP/Binary(而不是WS w. HTTP/SOAP)让ASP.NET前端应用调用业务服务层的组件。
既然你赶项目,那这么做可能更有利吧?这也是目前所见大部分.NET分布式应用程序的部署选择。
To oo789 : 隔离只是为了隔离业务逻辑,实体类我有一个专门的实体类项目层:D
To JGTM:我的意思是CLB,即把各种业务组件给部署在不同的机器上,比如ASP.NET在一台机器上,而业务逻辑在一台机器上,数据库是一个小型机上的Oracle,当然在其它机器上。所以此时就有问题了,如何让ASP.NET与业务逻辑通讯,这里面,最简单的,我想就是Web Service了。当然,用.NET Remoting也无不可,不过目前团队没有这方面的开发经验(Web Service可以基本上不用学,抄一个接口直接写就是了),而且开发时间也不允许。
要知道,需求有161页(参见本系列前三集),开发时间只有短短一个月,而且快速页面原型昨天才出来(说是最后版本了),数据库设计也昨天出来的(其实就表结构,表间关系还没有),最主要的是,数据库设计与页面原型不是我掌控范围内的,两者的设计完全脱节。
我现在最担心的是项目的进度问题,而不是如何实现一个优秀的架构了。
你想光用HTML+JavaScript搭建页面就用了一个月,而我们的开发剩下不到一个月了,这些工作真不知道该如何完成?
即使使用他们熟悉的JSP或者ASP(可惜,大部分人没有这方面的技能),也不可能一个月内完成这个项目,这本来就是不可能的任务。
确实是不可能完成的任何,就算需求不发生任何变动,也不可能完成,更要命的是项目组的大多数人不熟悉.net。
请问开心,你的这个系统总共包含了哪些项目,如asp.net web项目、Web services项目、类库项目、实体项目,还有哪些呀,我是来学习的。呵呵。
by the way,祝你开心
在这里我看到N多失败项目的影子:不合理的项目进度、没有合适的开发人员(包括您自己,作为技术顾问本身对使用的技术都很陌生)却又还要最求一些新技术、没有明确的需求、项目管理的混乱。
我个人认为这样的情况下看你的构架越简单越好,只要能实现功能就行了。简单用下面的结构:
1、一个封装SQL语句的DAL,或者干脆就把DAL拿掉,用存储过程。
2、一个业务逻辑层
3、界面层asp.net
看到你说你用web services的这么多原因,其实只有一条有点理由,就是你希望可以把界面层和业务层分开部署到不同计算机上。基于你和你的小组成员对WEB SERVICES、.NEG REMOTTING等分布式部署技术的陌生,我想你应该暂时不去考虑这个需求了。
当然之间在asp.net中访问数据库这样的结构最简单,但什么都混在一起了,太乱了。特别你现在需求还不清晰,以后修改的地方还有很多,所以还是稍微分一下层次。
To tony:
感谢指教。看来我得回家卖红薯了:'(
什么时候给在下补补课呢?
To 开心:
把4缉太极全观赏完毕,从中学到很多东西。目前我也正有一个类似这样的项目,发表一下我迟来的看法:
1、WS大家都是认同不应当作内部的中间层,效率低!
2、认同不少前辈的—界面层(ASP.NET)+逻辑层(CLASS LIB)+数据层
3、对于要要实现上面三层分布,用WS或RM都号,只会降低效率,虽然界面曾和逻辑曾分到2台机器,单独运行效率当然高,但结合在一起相信就相反了,我一直不建议把界面层和逻辑层分布,除非这两层各自都有很大很大的运算量。
我正在进行的项目大概要实现:
CLIENT SERVER State
============================================================================
.ASPX (.Net) <—Class (String/DataSet)——–> .CS OK/OK
.ASPX (SOAP) <—WebService(String/DataSet.XML)—-> .ASMX ? /?
.ASP (XMLHTTP/Rs) <—WebService(String/RecordSet.XML)–> .ASMX OK/ing
.HTML (XMLHTTP/XMLDOM) <—WebService(String/DataSet.XML)—-> .ASMX OK/ing
我用JAVA作的web service,其中一个方法返回的是ArrayList类型,ArrayList中放的是引用类型(比如User)对象。
用C#客户端调用,ArrayList.Count正确,而其中的引用类型对象不明确(或者说不是User对象了)。
请问哪位大虾能给出解释,有什么解决办法吗?
与tony同感 ,开心无疑是个好的程序员,但不是一个好的项目经理,这个项目注定失败~~~
1 使用了会导致架构变更的新技术
2 无法正常调度项目组资源
3 试图锁定永远不可能被锁定的需求
4 在开发出原型后没有立即取得客户认可(非常严重)
5 目前为止没有从太极系列中看到任何里程碑的痕迹,也没有明确延期责任及补救措施,没有就最新进展取得上级支持
6 参与太多编码工作
看了这篇讨论真的受益非浅!
我也正在进行类似的项目设计和开发,几乎同样的问题也出现了,到现在我一直都觉得项目可以成功,但是却感觉怪怪的,总觉得有什么不太对劲的地方,有说不出来,其实问题就在于引入了可有可无的WS,使表现层(ASP.NET)与数据曾完全脱节,以致到了沟通都很困难的地步。
我觉得真的应该吸取经验教训了!
看到大家的讨论,感觉使用新技术有很大的风险。看来我的这个项目中只好直接采用dataset了,因为对 typed dataset还处在了解阶段,虽然大家一致认为不错,也只好采用熟悉的dataset了。
另外 taber列举的几点让我受益颇多。
1 使用了会导致架构变更的新技术
2 无法正常调度项目组资源
3 试图锁定永远不可能被锁定的需求
4 在开发出原型后没有立即取得客户认可(非常严重)
5 目前为止没有从太极系列中看到任何里程碑的痕迹,也没有明确延期责任及补救措施,没有就最新进展取得上级支持
6 参与太多编码工作