Reputation: 3410
I'm trying to pass my UserModel to every view, so it can show on top the current user information.
This is my BaseViewModel:
public class BaseViewModel
{
public UserModel currentUser { get; set; }
}
BaseController:
public class BaseController : Controller
{
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
UserRepository userRep = new UserRepository();
BaseViewModel model = new BaseViewModel
{
currentUser = userRep.getCurrentUser()
};
base.OnActionExecuted(filterContext);
}
}
HomeController: (default)
public class HomeController : BaseController
{
public ActionResult Index()
{
ListRepository listRep = new ListRepository();
return View(listRep.GetAllLists());//returns IEnumerable<ListModel>
}
}
My shared _layout.cshtml:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - My ASP.NET Application</title>
@Styles.Render("~/Public/css")
</head>
<body>
<header>
@Html.Partial("_Header")
</header>
@RenderBody()
</body>
</html>
and finally, my _Header.cshtml:
<div id="logo">
<h1>Hello @Model.currentUser.username</ h1 >
</div>
But I get this error message when I run it:
'System.Collections.Generic.List' does not contain a definition for 'currentUser'
I thought my BaseViewModel
would always get appended
Upvotes: 1
Views: 93
Reputation: 683
Another possible solution using BaseController.
Instantiate your BaseViewModel model in OnResultExecuting method instead of OnActionExecuted. And save the model in ViewData to access it in _Header partial view.
E.g.
public class BaseController : Controller
{
protected override void OnResultExecuting(ResultExecutingContext filterContext)
{
UserRepository userRep = new UserRepository();
BaseViewModel model = new BaseViewModel
{
currentUser = userRep.getCurrentUser()
};
filterContext.Controller.ViewData["customData"] = model;
}
}
Now you need to pass ViewData to _Header partial view.
E.g.
@Html.Partial("_Header", ViewData["customData"])
In _Header partial view, you can simply access the data.
<div id="logo">
<h1>Hello @Model.currentUser.username</ h1 >
</div>
Upvotes: 0
Reputation: 218852
If you want that in every view, you may consider calling a child action method using Html.Action.
So replace
<header>@Html.Partial("_Header")</header>
with
<header>@Html.Action("Header","YourControllerName")</header>
Now have an action method called Header where you will pass the needed data to it's partial view
[ChildActionOnly]
public ActionResult Header()
{
var vm = new YourHeaderViewModel();
vm.UserName="Shyju"; // Replace with whatever you want.
return PartialView(vm);
}
Where YourHeaderViewModel is your view mode for the header with the properties needed for the header.
public class YourHeaderViewModel
{
public string UserName {set;get;}
}
Now in your Header partial view which is strongly typed to the YourHeaderViewModel class,
@model YourHeaderViewModel
<div id="logo">
<h1>Hello @Model.UserName</ h1 >
</div>
Upvotes: 2
Reputation:
The model in the view is IEnumerable<ListModel>
and that is what will be passed to the partial unless you specify a model, for example, using
@Html.Partial("_Header", someOtherModel)
Instead, create a ChildActionOnly
method that returns your user data to the _Header.cshtml
partial view and in the main view use @Html.Action()
to render it
[ChildActionOnly]
public ActionResult _Header()
{
var model = .... // get the model you want to render in the partial
return PartialView(model);
}
and in the main view
@{ Html.RenderAction("_Header", controllerName); }
Upvotes: 2