tags:

views:

117

answers:

4

I have an ASP.NET MVC web app whose controllers use WCF to call into the domain model on a different server. The domain code needs to talk to a database and access to the database server isn't always possible from web servers (depends on the customer site) hence the use of WCF to get to a place where my code is allowed to connect to the database server.

This is configurable so if the controllers are able to access the database server directly then I use local instances of the domain objects rather than use WCF.

Lets say I have a page asking for person details like age, name etc. This is a complex type that is a parameter on my WCF operation like this :

[OperationContract]
string SayHello( Person oPerson);

When I generate the client code (eg; by adding a service reference in my client) I get a separate Person class that fulfills the wcf contract. The client, an MVC web app, can use this client Person class as the view model and all is well. I pass that straight into the WCF client methods and it all works brilliantly.

If my mvc client app is configured to NOT use WCF I have a problem. If I am calling my domain objects directly from the controller (assume I have a domain access factory/provider setup) then I need the original Person class and not the wcf generated Person class. This results in my problem which is that I will have to perform mapping from one object to another if I don't use WCF

The main problem with this is that there are many domain objects that will need to be mapped and errors may be introduced such as new properties forgotten about in future changes

I'm learning and experimenting with WCF and MVC can you help me know what my options are in this scenario? I'm sure there will be an easy way out of this given the extensibility of WCF and MVC

Thanks

A: 

Sound service-oriented-architecture dictates that you use message based communication regardless of whether your service is on another machine, in another process, in another appdomain, or in your appdomain. You can use different endpoints with different bindings to take advantage of the speed of the link (http, tcp, named pipes) based on the location of your service, but the code using that service would remain the same.

Aviad P.
A: 

This may not be the easiest or least time-consuming answer, but one thing you can do is avoid using the "add service reference" option, and then copy your contract interfaces to your MVC application and initiate the connection to WCF manually without automatically creating a service proxy. This will allow you to use one set of classes for your model objects and you can control explicitly when to use WCF or not.

There's a good series of webcasts on WCF by Michele Leroux Bustamante, and I think in episode 2, she explains how to do exactly this. Check it out here: http://www.dasblonde.net/WCFWebcastSeries.aspx

Hope this helps!

Scott Anderson
Thanks I'm going to look into this it might mean I can avoid the service interface problem I mention in my response to John Saunders' reply
Gaz Newt
A: 

One sound option is that you always use WCF, even if client and server are in the same process, as Aviad points out.

Another option is to define the service contracts on interfaces, and to put these, together with the data contracts into an assembly that is shared between client and server. In the client, don't use svcutil or a service reference; instead, use ClientFactory<T>.

This way, your client code will use the same interfaces and classes as the server.

oefe
Am looking into this now thanks
Gaz Newt
+1  A: 

It appears that you are not actually trying to use a service-oriented architecture. In this case, you can place the domain objects into a single assembly, and share it between the WCF service and the clients. When creating the clients, use "Add Service Reference", and on the "Advanced" tab, choose "Share Types". Either choose to share all types, or choose the list of assemblies whose types you want to share.

John Saunders
Thanks you nailed it! I already had the domain data objects in a separate assembly but didn't know what "Share types" was for. This has saved me lots of work and impressed me.The generated client implements a different service interface so I can't abstract the service provider as much as I'd like but this is still a great result.It would be nice if I could share the service interface too so I could have a factory class that returns a service instance (either WCF or local) them I just call the methods. Instead I have to use instances separately in provider classes but that's not a big issue
Gaz Newt
I've sorted the service interface issue by using ChannelFactory as suggested it's really simple. Now I can use an instance of my service interface that either uses WCF or doesn't. Perfect
Gaz Newt