tags:

views:

373

answers:

3

I am pretty new to ASP.NET MVC and I am trying to get my head around some of the design concepts at the moment. One thing I am currently stuck on is how (best) to handle a situation such as that described below.

Suppose I have a page that needs to render a number of "sections". For example, on the left hand side there is a list that is data driven and then the selected item in the list displays a further list in another section on the page. For better understanding lets suggest the left hand list is a list of movie categories and the other list displays a list of movies that are contained within that category, along with the various movie details.

Now, I have some form of ORM such as Entity Framework, LINQ to SQL or whatever that maps the tblCategory and tblMovie database tables into Category and Movie entities respectively. These entities live in the MyMVCApp.Data.Entities namespace. I then use a repository pattern located in the MyMVCApp.Data namespace to encapsulate the queries (via LINQ) against these entities to return our model entities.

This is where my first question lies. Should the repository be returning view model entities or domain entities which are then extended to produce view model entities? In my naive mind I see the entities returned from the ORM as simply containers for the data with domain entities containing the business logic. So surely there should be an abstration here?

Anyway, back to my scenario. Now lets assume I wish to present the two sections described at the beginning of this. I am assuming that what should be happening here is my domain entity model would contain a list of categories and their associated movies. So something like a List each of which contains a List.

This model would have been populated somewhere. This is my second question. Say my assumption above is correct and it is simply data entities are returned from the ORM. Now I have a namespace/project called MyMVCApp.Core.Model (or the like) with some domain entities such as the Movie and Category entities mentioned in the previous paragraph. Do these entities have methods on them to retrieve the data from the ORM and populate themselves? Or does the repository retrieve these populated entity models? And another question on this part, if I have a Movie and Customer entity in my ORM is it acceptable to be having domain entities named the same?

Finally, I assume the controller now has this populated list of Category and Movie objects and passes it back to the view. I am guessing it is best to have each of the sections described at the beginning as partial views and passing the populated model to each? So, it may be the IndexController which retrieves the populated CategoryMovies entity, passing this to the Categories partial view and the Movies partial view. I would then need to somehow determine the selected Category (quesrystring?) and display the appropriate list of Movies in that category within the view.

OK, so if anyone has got to this point in my ramblings I will take a deep bow. I hope I have explained my mixed up thoughts and questions in sufficient detail for someone to provide some kind of enlightenment.

Thanks for listening! :-)

+1  A: 

First of all, I think you should just get started with a simple project and try the various scenarios out you pictured in your long question :). There is nothing written in stone, you can use whatever architecture with datalayers and services or whatever, you like !

Or does the repository retrieve these populated entity models?

I would say yes. Your controller graps these from the service and gets them, populated and all and just moves them to the view in order to be displayed.

I am guessing it is best to have each of the sections described at the beginning as partial views and passing the populated model to each?

And again i think you're on the right track ;).

Morph
+2  A: 

Since you didn't mention it, I will assume you are new to DDD concepts. DDD compliments the "M" in MVC by placing logic where it belongs. And, I think a good amount could be applied here.

In strict DDD form, I would use your Movie example as an Aggregate Root (a DDD concept). Within Movie, you would have business logic (methods) that obtain the categories and related entities directly related to Movie (i.e. Categories-this-movie-belongs-in). This assumes the "category" list you want to display is a list of categories this movie is in.

public class Movie
{
    private IList<Category> _categories;
    public IList<Category> FetchCategories()
    {
        // you can lazy-load here, use Linq-to-Sql, etc.
        return _categories;
    }
    public void AddCategory(Category c)
    {
        _categories.Add(c);
    }
}

Of course, you can treat Categories as a Value Object (VO, a DDD concept) here if you don't have an identity on them.

Now, what gets more interesting is if you do want to keep an identity on your Categories, treating them as Aggregate Roots with multiple entities and relations to other VOs and alike. In this case, you would want to utilize the DDD concept of Services to combine the two aggregates into your requested Model you want to pass to your Controller. This allows you to create business rules around loading the categories.

public class Movie
{...}
public class Category
{...}
public class MovieCategory : Movie
{
    private IList<Category> _categories;
    public IList<Category> Categories
    {
        get
        {
            return _categories;
        }
        internal set
        {
            _categories = value;
        }
    }
}
public class MovieCategoryService
{
    public MovieCategory FetchMovieCategoryByMovieId(int id)
    {
        MovieCategory mc = _movieRepository.FetchMovie(id);
        // do some logic here, some checks, etc
        // to obtain your Categories list.  Maybe querystring?
        IList<Category> cats = ...;
        mc.Categories = cats;

        return mc;
    }
}

The concept is that you now have logic in the domain layer, in this MovieCategoryService, to handle the complex creation of these relationships, or using Factories to create complex types as well.

This gives you a model you can pass around to different View and PartialViews.

The final step in your original post is how to get this into the View. I've been playing with the ViewModel approach to this issue. Creating ViewModels either dynamically, or as a class, and hanging all of the entities on this ViewModel. A recent StackOverflow question hits on this concept. http://stackoverflow.com/questions/664205/viewmodel-best-practices

I've passed the Model directly into Views, and I am now trying this approach. It does clean things up, as your DOmain Model really should be disconnected from the "logic" on your page. I find myself thinking, "Dang it. I need to get this partialview populated based on this ID. Guess that means another method on the entity." Going the ViewModel approach removes the logic/thinking from the Domain Model, and puts it where it belong - in the Application/UI layer of where you are fine-tuning your view/partialview.

eduncan911
+1  A: 

It is a nice idea to give a view model entity to the view instead of the whole domain entity itself thereby providing the view only the required stuffs to work on

First of all return a List of Categories from your Domain, then construct a Movie view which takes the category name as a parameter something like this

 - <Host>/Movies/Comedy
 - <Host>/Movies/Horror

which would in turn display the movies which belongs to that particular category

Rony