Passing an optional object to all views
So, basically what I'd like is to do something like:
@if(Notification!=null){
//perform javascript notification with @Notification.Text
}
And I'd like to be able to do this on any view, so I will always have the option of specifying a notification object in my controller action, that, if defined, can be handled in the view.
My dream scenario is to allow this simply by creating the Notification开发者_如何学JAVA object somehow, and then just returning the view. Meaning, I wouldn't need to explicitly pass the Notification object to the model. Like so:
public ActionResult MyAction(){
Notification n = new Notification("Text for javascript");
return View();
}
I'm thinking, that there might be a way to do this with some ViewPage-inheritance? But I'm really unsure of how to go about this?
In an ideal world, I would also love to be able to "override" what to do. For example, if I in my 'top'-layout choose to perform a certain kind of jquery-notification if the notification object exists, but maybe in some other nested view would like to handle it differently, I'd like the option to override the top-layouts handling of the object.
I know this last thing might be a little utopian (I'm just starting out with MVC and Razor), but it would be cool :)
You could write a custom global action filter which will inject this information on all views. For example:
public class MyActionFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.Controller.ViewBag.Notification = new Notification("Text for javascript");
}
}
and then register this filter in the RegisterGlobalFilters
method of your Global.asax
:
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
filters.Add(new MyActionFilterAttribute());
}
And then in your views:
@if(ViewBag.Notification != null)
{
//perform javascript notification with @ViewBag.Notification.Text
}
Use ViewBag for simple stuff like popup message.
public ActionResult Index()
{
ViewBag.PopupMessage = "Hello!";
return View();
}
and then in view (or layout page)
@if (ViewBag.PopupMessage != null)
{
<div class="popup">@ViewBag.PopupMessage</div>
}
For more complicated stuff you will need to either create static class and save/read from HttpContext.Current.Items
or override Controller
and WebViewPage
and save/read from ViewBag
/ViewData
.
Update:
public abstract class BaseController : Controller
{
public const string NotificationKey = "_notification";
protected string Notification
{
get
{
return ViewData[NotificationKey] as string;
}
set
{
ViewData[NotificationKey] = value;
}
}
}
public abstract class BaseViewPage<TModel> : WebViewPage<TModel>
{
protected string Notification
{
get
{
return ViewData[BaseController.NotificationKey] as string;
}
}
}
Views/Web.config
<pages pageBaseType="OverrideTest.Framework.BaseViewPage">
Usage:
public class HomeController : BaseController
{
public ActionResult Index()
{
Notification = "Hello from index!";
return View();
}
}
<div>Notification: @(Notification ?? "(null)")</div>
Or get test project here
Update 2: Check out this blog post for another way to do something similar.
精彩评论