Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

View-specific Models in ASP.NET MVC?

I am relatively new to MVC, so this is likely a novice question.

I am trying to understand the best practices for how to maintain clear separation of concerns in a few scenarios that don't appear straightfoward.

There are two scenarios I am looking at right now. Imagine a very basic app that lets users view and edit online profiles for lawyers. There is an action/view to display a particular user's profile and an action/view to edit a particular user's profile. It's easy to imagine a nice and clean Model class to represent the details of a user's profile, perhaps made with the Entity Framework and mapped to the user profile SQL table.

In the view action/view for displaying a user's profile, functionally, I need to have a button or link that lets a user edit the profile. But that should only be available to some subset of users. For example, the user can edit their own profile. Also, super users can edit anyone's profile. My question is how should the View decide if the link should be there when rendering a particular profile. I assume it is wrong for the View to contain the logic to determine if the current user can edit the current profile. Should I add a IsEditable property to the UserProfile model class? That doesn't feel tragic, but it doesn't feel completely right either. Should I make a new Model class that aggregates the UserProfile with additional information about security?

Another scenario... When editing a particular profile, one of the things that is editable is the list of specialties for a particular lawyer. The list of possible specialties is not fixed. If the view wants to render them in combo box, it needs the list of all possible specialties form the database. The view shouldn't be getting them from the database directly, so do I do the aggregate Model thing again and provide the View with both the UserProfile and a list of valid specialties?

I guess the generic issue I am trying to figure out is should I be comfortable with creating lots of little Model classes that are essentially specific to individual views. Each class would include the various unrelated parts of the larger Domain Model needed for that particular view.

like image 881
Erv Walter Avatar asked Feb 05 '09 14:02

Erv Walter


3 Answers

ViewModel pattern is more specifically geared towards the scenario that you have described. You can use the ViewData but this is the less recommended solution since you loose lots of the benefits of the ASP.NET MVC framework. For example, when you use ViewData you do not have type-safety, compile-time chekcing and intellisense support in your views.

like image 130
Bikal Lem Avatar answered Oct 05 '22 22:10

Bikal Lem


For your scenario I pass along another parameter in the ViewData, ViewData["AllowEdit"] which is set to true if the View should show the edit link. I prefer this to cloning the model into a view-specific model to add this single attribute. I do sometimes create view specific models -- for instance I have Grid ViewUserControl that takes a Grid model, which I can produce from any list of other model classes -- but I wouldn't in this case.

In my view I would do something like this:

<% if (Convert.ToBoolean(ViewData["AllowEdit"])) { %>
<%= Html.ActionLink("Edit", "Edit", "Profile",
                    new { id = ViewData.Model.ID }, null ) %>
<% } %>
like image 25
tvanfosson Avatar answered Oct 05 '22 21:10

tvanfosson


For your first situation, I would probably try to encapsulate the logic for this in the profile model, perhaps with a function like CanEdit() which accepts user information parameters and checks whether the user is the owner of the profile or if they have superuser permissions. Then in the controller I would call the function and pass the results to the view using ViewData.

For the second, in the edit profile controller action, retrieve the specialties list (via the model) and pass it on to the view using ViewData.

like image 28
Misko Avatar answered Oct 05 '22 22:10

Misko