Reputation: 1661
Hello Razor MVC Gurus:
Newbie question.
Background. I have a custom IIdentity that is set in an HttpModule before it gets to controller & views. To use it, i have to do
MyIdentity myIdentity = (MyIdentity)((GenericPrincipal)context.User).Identity;
MyComplexUser user = myIdentity.User;
//user.name //user.location //user.username //etc
The problem is, I use the object in different places such as
It really depends on what properties of "MyComplexUser" object the views need.
Currently, in the views, I have to do this really complicated casting to get to a property. For instance, if I want the "Name" of the user, I need to do
@(((MyComplexUser)(((MyIdentity)((GenericPrincipal)context.User).Identity).User)).Name)
I suppose I could put it in the controllers and then populate the ViewBag with a ViewBag.MyUser property, but then
Thanks. Again, I'm a newbie at MVC 4, any suggestion is greatly appreciate it.
Upvotes: 16
Views: 12116
Reputation: 7692
I'll explain a similar solution that works pretty well for me. With small changes, I believe that it will work for you (and others, hopefully) as well.
Basically, we'll be using inheritance.
Let's create a custom base controller, such as
public class BaseController : Controller
and let's change our controllers to inherit from it, as
public class HomeController : BaseController
You probably have lots of classes inside your Models folder, right? They act as DTOs from the controller to the views, right²? If you answered yes for both, then keep reading.
Let's create a base model class, such as public class BaseVM
, and let's change our models to inherit from it, like public class HomeIndex : BaseVM
Important: your layout file (_Layout
or whatsoever) must be strongly typed to BaseVM
or a child of it.
Now that everything's beautifuly typed, let's use the request pipeline in our favor.
At BaseController
, you'll add a method that looks like this:
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.Result is ViewResultBase)//Gets ViewResult and PartialViewResult
{
object viewModel = ((ViewResultBase)filterContext.Result).Model;
if (viewModel != null && viewModel is BaseVM)
{
BaseVM baseVM = viewModel as BaseVM;
baseVM.MyIdentity = (MyIdentity)((GenericPrincipal)context.User).Identity;
//and so on...
}
}
base.OnActionExecuted(filterContext);//this is important!
}
OnActionExecuted
is called after the execution of the action but before the view rendering. That's exactly what we want.
I hope you got it already. =)
Upvotes: 22