views:

48

answers:

1

I'm just starting to learn asp.net mvc and I'm not sure what the right thing to do is.

I have a user and a user has a collection of (0 or more) reminders. I have a controller for the user which gets the reminders for the currently logged in user from a reminder service. It populates a model which holds some information about the user and the collection of reminders.

My question is should I have 2 different views, one for when there are no reminders and one for when there are some reminders? Or should I have 1 view which checks the number of reminders and displays different things? Having one view seems wrong as then I end up with code in my view which says if (Model.Reminders.Count==0){//do something} else {do something else}, and having logic in the view feels wrong. But if I want to have 2 different views then I'd like to have some code like this in my controller:

[Authorize]
public ActionResult Index()
{
    MembershipUser currentUser = m_membershipService.GetUser();
    IList<Reminder> reminders = m_reminderRepository.GetReminders(currentUser);
    if (reminders.Count == 0)
    {
        var model = new EmptyReminderModel
        {
            Email = currentUser.Email,
            UserName = currentUser.UserName
        };
        return View(model);
    }
    else
    {
        var model = new ReminderModel
                       {
                           Email = currentUser.Email,
                           UserName = currentUser.UserName,
                           Reminders = reminders
                        };
        return View(model);
    }

but obviously this doesn't compile as the View can't take both different types. So if I'm going to do this should I return a specific named view from my controller, depending on the emptiness of the reminders, or should my Index() method redirect to other actions like so:

[Authorize]
public ActionResult Index()
{
    MembershipUser currentUser = m_membershipService.GetUser();
    IList<Reminder> reminders = m_reminderRepository.GetReminders(currentUser);
    if (reminders.Count == 0)
    {
        return RedirectToAction("ShowEmptyReminders");
    }
    else
    {
        return RedirectToAction("ShowReminders");
    }            
}

which seems nicer but then I need to re-query the reminders for the current user in the ShowReminders action.

Or should I be doing something else entirely?

+1  A: 

For minor complexity like that, I don't find a problem with just having an '<% if.. else %>' block in the view. However, if you feel like really going the distance...

One potential answer would be to use DisplayTemplates. If you have one base UserBaseViewModel, and then your UserWithRemindersViewModel and UserWithoutRemindersViewModel inherit from UserBaseViewModel, then you can pass the UserBaseViewModel as the Generic type for your view, aka System.Web.Mvc.ViewPage<UserBaseViewModel>.

Then, depending your logic in the controller, you pass back a UserWithRemindersViewModel or the other to the view. (aka. return View(new UserWithoutRemindersViewModel()); // Inherits UserBaseViewModel, so everything is ok! )

Then, you can simply invoke the Html.DisplayFor(m => m) on your view.

If you make two templates in the \Views\<ControllerName>\DisplayTemplates\, UserWithRemindersViewModel.ascx, and UserWithoutRemindersViewModel.ascx. MVC will select the right display template for the type of your model you passed down, and since each of those PartialViews would be strongly typed to the right view model type, there is no need to <% if ... else %> to display the right HTML.

Tejs
I hear you about the minor complexity, but as my goal is to learn, I want something fairly simple but want to 'do things the right way' so your suggestion sounds ideal. I'll have a play with that and see where it gets me. Never used the Html.DisplayFor either so something else to play with. Thanks.
Sam Holder