在ASP.Net WebForms中设置每个页面的背景相当简单,您可以在MasterPage的代码隐藏中访问Page_Load事件但是如何在MVC中最好地完成?在花了几个小时研究各种替代方案后,我选择通过" base"将值分配给ViewBag。 controller,从该基础派生后续控制器,然后在_Layout.cshtml中访问该值。
这是基本控制器,我在其中指定一个指向特定图像的URL:
public class BaseController : Controller
{
public BaseController()
{
ViewBag.url = BingImageLoader.getBingImageUrl();
}
}
下一步是派生后续控制器,在本例中是来自该基类的HomeController:
public class HomeController : BaseController
{
public ActionResult Index()
{
return View();
}
.
.
最后,使用_Layout.cshtml的head元素中的ViewBag来设置背景图像样式属性。
.
.
<style type="text/css">
body {
background-image: url(@ViewBag.url);
background-repeat: no-repeat;
background-size: cover;
}
</style>
</head>
这确实完成了我的目标;但是,在此过程中还有许多替代方案,包括使用ActionFilters。老实说,创建一个CustomActionFilter并使用ActionFilterAttributes并重写OnActionExecuting似乎有点矫枉过正,但有时候最简单的方法并不总是最好的。
最终,问题归结为&#34;有更好的方法吗?&#34;引入中间人是否有副作用?如果我在各个控制器方法中覆盖我的ViewBag.url,则图像会相应更改。所以我还没有发现任何问题,但这种方法可能会产生其他问题。
再次,&#34;有更好的方式&#34;?
答案 0 :(得分:2)
我可以通过这种方法看到的一个可能的问题是开发人员是否忘记从BaseController
继承hist控制器。
使用global action filter
将确保永远不会发生这种情况,并且该属性将始终可用:
public class BackgroundImageFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext context)
{
context.Controller.ViewBag.url = BingImageLoader.getBingImageUrl();
}
}
只会在Application_Start
protected void Application_Start()
{
...
// Register global filter
GlobalFilters.Filters.Add(new BackgroundImageFilterAttribute());
}
如果您发现这种过滤方法很麻烦,我可以建议您编写一个可以在_Layout.cshtml
中使用的自定义Html帮助程序:
<style type="text/css">
body {
background-image: url(@Html.GetBackgroundImageUrl());
background-repeat: no-repeat;
background-size: cover;
}
</style>
可能被定义为一个简单的扩展方法:
public static class HtmlExtensions
{
public static IHtmlString GetBackgroundImageUrl(this HtmlHelper html)
{
string url = BingImageLoader.getBingImageUrl();
return new HtmlString(url);
}
}