maandag 11 mei 2009

Isolating the domain model from your view

When working with the ASP.NET MVC framework I have a strong urge to not pass my domain models directly to the view (and I feel that’s a good thing). Actually, I should refine that. I do not pass my domain models to the view as a domain class. Let’s investigate.

My model at the moment consists of a class called Contact. It’s very simple:

	public class Contact
{
public int Id { get; set; }
public string LastName { get; set; }
}


This class is populated with data from my datasource (a static List<Contact> for now), and later on it’ll be used in my domain logic. For now it’s a simple data class. Now, for a view which is used to edit this entity, the first idea is to go with a strongly typed viewdata, like such:



<%@ Page Title="" 
Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="ViewPage<Contact>" %>




Basically I’m passing the domain model directly into the view. Not really a good thing in my opinion, because I’m exposing waaay too much of the model to the view. I only need a few simple getters, and perhaps some combined getters (in case of a person, one which appends first/lastname for instance). The solution I use for this is to wrap the domain model in a viewdata class, without exposing the actual model itself.



	public class ViewContact
{
private readonly Contact contact;

public ViewContact(Contact contact)
{
this.contact = contact;
}

public int Id { get { return contact.Id; } }

public string DisplayName
{
get { return contact.LastName; }
}
}




As you can see, the actual model is passed in as a parameter to the constructor, but I’m not exposing it directly. What I can do now is pass this object to the view, without exposing the model:



<%@

Page Title=""


Language="C#"


MasterPageFile="~/Views/Shared/Site.Master"


Inherits="ViewPage<ViewContact>" %>



<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">



    <h2>Editing: [<%= Model.Id %>] <%= Model.DisplayName %></h2>

    <% using (Html.BeginForm("Update", "Contact")){ %>


        …


        …


    <% } %>



</asp:Content>



Now I’ve got a simple way to isolate my domain model from my view, by using a wrapper class. This way I can explicitly specify what I want to be able to use in my views, without having to conform my domain model to that. I can have a rich domain model, while still limiting the amount of information I get in my view. I’m not sure how this will work out, so I’ll probably follow up on this blog with new insights, or perhaps a complete abandoning of the pattern later ;-)

1 opmerking:

Matt Hinze zei

Instead of hand-coding all that repetitive wrapper code you can use the excellent AutoMapper tool to do it automatically.

http://www.codeplex.com/AutoMapper