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:
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
Een reactie posten