在 MVC _Layout.cshtml 页面中设置背景

Setting the background in an MVC _Layout.cshtml page

在 ASP.Net WebForms 中设置每个页面的背景相当简单,您可以在 MasterPage 的代码隐藏中访问 Page_Load 事件,但是如何在 MVC 中最好地完成这项工作?在花了几个小时研究各种替代方案后,我选择通过 "base" 控制器将值分配给 ViewBag,从该基础派生后续控制器,然后在 _Layout.cshtml.

中访问该值

这是基本控制器,我在其中分配了一个指向特定图像的 url:

public class BaseController : Controller
{
    public BaseController()
    {
        ViewBag.url = BingImageLoader.getBingImageUrl();    
    }
}

下一步是派生后续控制器,在本例中是来自该基础的 HomeController class:

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 似乎有点矫枉过正,但有时最简单的方法并不总是最好的。

最终,问题归结为 "Is there a better way?" 引入中介是否有副作用?如果我在各个控制器方法中覆盖我的 ViewBag.url,图像会相应改变。所以我还没有发现任何问题,但这种方法可能会导致其他问题。

那么,"Is there a better way"?

我可以看到这种方法的一个可能问题是,如果开发人员忘记从 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());
}

如果您发现这种过滤器方法作为替代方法很麻烦,我建议您编写一个自定义 Html 帮助程序,可以在您的 _Layout.cshtml:

中使用
<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);
    }
}