style-sheets style-sheets - 1 month ago 9
ASP.NET (C#) Question

(asp.net MVC4) Reference a global base model in _layout.cshtml and custom models in other views?

I have two controllers:

HomeController
and
CustomersController
(the 2nd controller has been generated using vs.net add scafolded item dialog)

I created this
base view model
which works with
_layout.cshtml
(to pass data like app name, meta description and other global info that's pulled from DB / changed depending on language set by the user)

public abstract class BaseViewModel
{
public string AppName { get; set; }
public string Author { get; set; }
public string PageTitle { get; set; }
...
}


Then I derived another
CommonModel
from it:

public class CommonModel: BaseViewModel


so that I can use it with my
HomeController()
, ie.

public class HomeController : Controller
{
public ActionResult Index()
{
string LocalizedTitle = "Greeting in user language...";
CommonModel Model = new CommonModel { PageTitle = LocalizedTitle };

return View(Model);
}
...


Then, in
_layout.cshtml
, I have something like this:

@model PROJECT_NAME.Models.CommonModel

<!DOCTYPE html>
<html>
<head>
<title>@Model.PageTitle - @Model.AppName</title>
...


The problem is, this doesn't work if a user tries to access
Customers/Index
, in this case, I'm getting the dreaded error
The model item passed into the dictionary is of type
...

Customers/Index.cshtml looks like this:

@model IEnumerable<PROJECT_NAME.Models.Customer>

<h2>Show your list here...</h2>
...


My
CustomersController
looks like this:

public class CustomersController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();

// GET: Customers
public ActionResult Index()
{
return View(db.Customers.ToList());
}


My question is How can I make each view call its own model without interfering with each other?

In other words, how can I make
_Layout.cshtml
reference
@model PROJECT_NAME.Models.CommonModel
, while
Customers/Index.cshtml
reference
@model IEnumerable<PROJECT_NAME.Models.Customer>
without having an error?




Disclaimer!


  1. I'm very new to asp.net MVC, please be nice!

  2. Yes, I did look a lot before, but none of the questions/answers I found in SO fix my issue (either that or I didn't understand them)


Answer

You base view model is BaseViewModel (which contains the properties you want ot display in the layout), therefore your _Layout.cshtml file should have

@model PROJECT_NAME.Models.BaseViewModel // not CommonModel

Then all views that use that layout need to use a view model that derives from that base model, so in the case of a view that displays IEnumerable<Customer>, the view model for that view would be

public class CustomerListVM : BaseViewModel
{
    public IEnumerable<Customer> Customers { get; set; }
}

and in the GET method for that view

string LocalizedTitle = "Greeting in user language...";
CustomerListVM model = new CustomerListVM()
{
    PageTitle = LocalizedTitle,
    ... // other properties of BaseViewModel
    Customers = db.Customers
}
return View(model);

and the view will then be

@model CustomerListVM
....
@foreach(var customer in Model.Customers
{
    ....
Comments