views:

40

answers:

2

I may have the wrong "pattern" here, but I think it's a fair topic.

I have an ASP.Net MVC application in which it calls out to a WCF service to get back the ViewModels that will be rendered. (the reason it's using a WCF service is so that other small MVC apps may also call on for these ViewModels...only internally, it's not a publicly available thing so I can change anything either side of the service. The idea is to move the logic that was in the website, closer to the server/database so the roundtrips aren't so costly - and only do one roundtrip overall from the webserver to the database server).

I'm trying to work out the best thing to return these "ViewModels" in from the service. There are lots of common little bits of functionality, but each page may want to display different subsets of these things (so homepage maybe a list of tables, next page, a list of tables and users that are available).

So what's the best way of returning the information that the page wants, hopefully without the webservice knowing about the page?

Edit:

It's been suggested below that I move the logic in process. This would be a lot faster, except that's what we're moving away from because it is actually a lot slower (in this case). The reason for this is that the database is on one server, and the webapp is on another server, and the webapp is particularly chatty at points (there are pages it could end up doing 2K round trips - (I have no control over reducing this number before that's suggested)), so moving the logic closer to the db is the next best way of making it more performant.

A: 

Instead of having a web service, why don't you just implement the service as a reusable library that encapsulates the desired functionality?

This will also allow you to use polymorphism to implement customizations. WCF doesn't support polymorphism in a flexible way...

Using an in-proc service will also be a lot faster.

See this related question for outlines of a polymorphic solution: http://stackoverflow.com/questions/2151188/is-this-a-problem-typically-solved-with-ioc/2153220#2153220

Mark Seemann
Yes, that *would* be a lot faster, except that's what we're moving away from because it is a lot slower. The reason for this is that the database is on one server, and the webapp is on another server, and the webapp is particularly chatty at points (there are pages it could end up doing 2K round trips - (I have no control over reducing this number before that's suggested)), so moving the logic closer to the db is the next best way of making it more performant.
Paul
Unless your backing data changes very frequently, you could also solve that issue (perf) with caching combined with an in-proc service... Obviously I don't know the exact details of your scenario, so this may not apply in your case, but in the general case I'd prefer that over a web service.
Mark Seemann
That sounds perfectly ideal, unfortunately not possible in this case. The web service (or some other service) really is the best way to go that we can think of, it's been quite carefully considered
Paul
+1  A: 

I would look at creating a ViewModel per each MVC app/view. The service could just return the maximum amount of data for the "view" in a logical sense and each MVC app uses the information it wants when composing the ViewModel for it's view.

Your service is then only responsible for one thing, returning data specific to a view's function. The controller of each app is responsible for using/not using pieces of the returned data.

This will be more flexible as your ViewModels may require different validation rules as well. ViewModels also have MVC-specific needs(SelectList etc..) that shouldn't really be returned by a service layer. It seems like something can be shared at a glance, but there are generally lots of small differences that make sharing ViewModels a bad idea.

class MyServiceViewResult
{       
    public int SomethingEveryViewNeeds { get; set; }
    public bool OnlyOneViewMightNeedThis { get; set; }
}

class ViewModel1
{
    public int IdProperty { get; set; }

    public ViewModel1(MyServiceViewResult result)
    {
        IdProperty = result.SomethingEveryViewNeeds;
    }
}

class ViewModel2
{
    public int IdProperty { get; set; }
    public bool IsAllowed { get; set; }

    public ViewModel2(MyServiceViewResult result)
    {
        IdProperty = result.SomethingEveryViewNeeds;
        IsAllowed = result.OnlyOneViewMightNeedThis;
    }
}
Jab