简体   繁体   English

消耗WCF的ASP.NET MVC

[英]ASP.NET MVC consuming WCF

My ASP.NET MVC 2 controllers are currently instantiating service objects in their constructors by passing repository instances that are instantiated by Castle Windsor. 我的ASP.NET MVC 2控制器当前正在通过传递由Castle Windsor实例化的存储库实例来实例化其构造函数中的服务对象。 I have unit tests that call the controller actions after passing Moq instances of the repositories to the controller's constructor. 我有将存储库的Moq实例传递到控制器的构造函数后调用控制器动作的单元测试。

I want to allow a third-party UI to access these service objects through WCF. 我想允许第三方UI通过WCF访问这些服务对象。

It occurred to me that converting my existing Service layer into Web services or even adding a new Web service layer between the UI and the existing Service layer will break my unit tests unless I find a way to bridge that gap. 我想到将现有的Service层转换为Web服务,或者甚至在UI和现有Service层之间添加新的Web Service层都会破坏我的单元测试,除非我找到一种弥合这种差距的方法。

I was trying to work out a solution where my UI was coded against an interface of the service layer (it already is) and I could use DI to pass the Web service implementation at run-time and pass the existing implementation during unit testing. 我正在尝试制定一个解决方案,其中我的UI是根据服务层的接口编码的(已经是),并且我可以使用DI在运行时传递Web服务实现,并在单元测试期间传递现有实现。 The Web service implentation would simply call the existing implementation. Web服务实现将只调用现有的实现。

Questions: 问题:

  1. Is such an approach advisable / possible? 这种方法是否明智/可行?
  2. Are there any examples of this in a tutorial or open source project? 在教程或开源项目中是否有任何示例?

EDIT: 编辑:

I believe I have a workable solution now thanks to the suggestions below. 由于以下建议,我相信我现在有一个可行的解决方案。 I created a WCF Service Application that uses the existing service interfaces from my domain model. 我创建了一个WCF服务应用程序,该应用程序使用了域模型中的现有服务接口。 The WCF implementation is a class where the constructor takes repository instances from Ninject 's WCF extension and creates an instance of the service from the domain model. WCF实现是一个类,其中的构造函数从NinjectWCF扩展中获取存储库实例,并从域模型中创建服务的实例。 Each method/function in WCF simply calls the same method/function from the existing service layer. WCF中的每个方法/函数都简单地从现有服务层调用相同的方法/函数。

There were some caveats. 有一些警告。 For example, I can no longer pass a reference to my ASP.NET MVC ModelState when I create the service in the controller (actually, I use Ninject to create an instance of the WCF service and supply that to the controller's constructor). 例如,当我在控制器中创建服务时,我不能再传递对ASP.NET MVC ModelState的引用(实际上,我使用Ninject创建WCF服务的实例并将其提供给控制器的构造函数)。 The reason is that WCF is a messaging platform - changes must be explicitly communicated back with each call (ie my validation errors are now communicated back as reference parameters on individual functions/methods). 原因是WCF是消息传递平台-每次调用都必须明确传达更改(例如,我的验证错误现在作为各个功能/方法的参考参数传递回)。

I also had to add some serialization/servicemodel references to my formerly POCO Core project. 我还必须向以前的POCO Core项目添加一些序列化/服务模型引用。

Also, I switched from Castle to Ninject because Castle's WCF solution has a maturity level of low and I wasn't comfortable using that at this time. 另外,我从Castle切换到Ninject,因为Castle的WCF解决方案的成熟度很低,我现在不习惯使用它。

Can you explain in more detail why your tests would break? 您能否更详细地解释为什么测试会失败?

I do this type of development all the time. 我一直在进行这种开发。 Services as classes => services as WCF services. 服务作为类=>服务作为WCF服务。

Your tests shouldn't break. 您的测试应该不会失败。 A WCF Service is almost 100% contract, the underlying business code and logic shouldn't have to change. WCF服务几乎是100%合同,底层的业务代码和逻辑不必更改。

Check out the Web Services Software Factory created by the Patterns & Practices team. 查看由模式和实践团队创建的Web服务软件工厂 It is a good way to structure your services into contract projects (data, message, service) and "business code". 这是将服务构建为合同项目(数据,消息,服务)和“业务代码”的好方法。 Once you get a better understanding of how to structure your code, you can refactor their style to something that fits you a little better. 一旦对如何构造代码有了更好的了解,就可以将它们的样式重构为更适合您的样式。 Their example tends to separate everything into lots of VS projects, which can be a little overkill for most shops. 他们的示例倾向于将所有内容分解为许多VS项目,这对于大多数商店而言可能有点过大。 Example, I don't see many shops sharing data contracts across projects. 例如,我看不到很多商店在项目之间共享数据合同。 Yes, in a perfect world, you should probably share a lot os types (like address) across projects, but I don't see it done very often. 是的,在一个理想的世界中,您可能应该在项目之间共享很多os类型(例如地址),但是我并不认为它经常执行。 So, I tend put all my contract stuff in one VS project. 因此,我倾向于将所有合同内容放在一个VS项目中。

If your services are already defined as interfaces then you've got a head start. 如果您的服务已被定义为接口,那么您将获得领先。

Pass the services into the controllers as constructor dependencies, rather than the repositories. 将服务作为构造函数依赖项而不是存储库传递给控制器​​。 Let your DI container A) provide the repositories to the services, and B) provide the services to the controllers. 让您的DI容器A)为服务提供存储库,B)向控制器提供服务。

If you want to stand up your service layer as wcf services to be accessed by other applications, you'll want to use the wcf service factory to pull the concrete service implementations out of your DI container. 如果您希望将服务层作为wcf服务站起来供其他应用程序访问,则需要使用wcf服务工厂将具体的服务实现从DI容器中提取出来。 Here's an example with windsor , it should be easy to adapt to whatever container you use. 这是一个使用windsor的示例 ,它应该很容易适应您使用的任何容器。

At this point you can modify your website to either A) continue to invoke the services directly, or B) have them call back to the web services using service clients. 此时,您可以将您的网站修改为:A)继续直接调用服务,或B)使用服务客户端使它们回调到Web服务。 There are pros and cons to both methods. 两种方法都有优点和缺点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM