Asp.net mvc 4 将数据传递给所有页面共用的布局

Asp.net mvc 4 将数据传递给所有页面共用的布局,asp.net-mvc-4,Asp.net Mvc 4,我有一个网站,其中有一个布局页面。然而,这个布局页面有数据,所有页面模型都必须提供这样的页面标题、页面名称和我们实际所在的位置,我为一个HTML助手做了一些操作。此外,每个页面都有自己的视图模型属性 我该怎么做?键入布局似乎不是一个好主意,但如何传递这些信息?如果需要将相同的属性传递给每个页面,那么创建一个供所有视图模型使用的基本视图模型是明智的。然后,布局页面可以采用此基本模型 如果此数据背后需要逻辑,则应将其放入所有控制器使用的基本控制器中 您可以做很多事情,重要的方法是不要在多个地方重复相

我有一个网站,其中有一个布局页面。然而,这个布局页面有数据,所有页面模型都必须提供这样的页面标题、页面名称和我们实际所在的位置,我为一个HTML助手做了一些操作。此外,每个页面都有自己的视图模型属性


我该怎么做?键入布局似乎不是一个好主意,但如何传递这些信息?

如果需要将相同的属性传递给每个页面,那么创建一个供所有视图模型使用的基本视图模型是明智的。然后,布局页面可以采用此基本模型

如果此数据背后需要逻辑,则应将其放入所有控制器使用的基本控制器中

您可以做很多事情,重要的方法是不要在多个地方重复相同的代码

编辑:根据下面的评论更新

下面是一个简单的例子来演示这个概念

创建所有视图模型将从中继承的基础视图模型

public abstract class ViewModelBase
{
    public string Name { get; set; }
}

public class HomeViewModel : ViewModelBase
{
}
您的布局页面可以将其作为模型

@model ViewModelBase
<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Test</title>
    </head>
    <body>
        <header>
            Hello @Model.Name
        </header>
        <div>
            @this.RenderBody()
        </div>
    </body>
</html>

如果要传递整个模型,请在布局中这样做:

@model ViewAsModelBase
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta charset="utf-8"/>
    <link href="/img/phytech_icon.ico" rel="shortcut icon" type="image/x-icon" />
    <title>@ViewBag.Title</title>
    @RenderSection("styles", required: false)    
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
    @RenderSection("scripts", required: false)
    @RenderSection("head", required: false)
</head>
<body>
    @Html.Action("_Header","Controller", new {model = Model})
    <section id="content">
        @RenderBody()
    </section>      
    @RenderSection("footer", required: false)
</body>
</html>

另一个选项是创建一个单独的LayoutModel类,其中包含布局中所需的所有属性,然后将该类的实例填充到ViewBag中。我使用Controller.OnActionExecuting方法来填充它。
然后,在开始布局时,您可以将此对象从ViewBag中拉回来并继续访问此强类型对象。

我在布局中使用了RenderAction html helper for razor

@{
   Html.RenderAction("Action", "Controller");
 }
我需要它来做简单的字符串。所以我的操作返回字符串,并在视图中轻松地将其写下来。 但如果需要复杂的数据,可以返回PartialViewResult和model

 public PartialViewResult Action()
    {
        var model = someList;
        return PartialView("~/Views/Shared/_maPartialView.cshtml", model);
    }
您只需要将您的模型放在您创建的局部视图“\u maPartialView.cshtml”的开头

@model List<WhatEverYourObjeIs>
@型号列表

然后,您可以使用html在该部分视图中使用模型中的数据。

大概,这方面的主要用例是为所有(或大部分)控制器操作获取视图中的基本模型

考虑到这一点,我使用了其中几个答案的组合,主要依靠科林·培根的答案

这仍然是控制器逻辑,这是正确的,因为我们正在填充viewmodel以返回到视图。因此,将其放置在控制器中的正确位置

@{
    var myController = this.Controller(); //_BaseController
}
我们希望在所有控制器上都发生这种情况,因为我们将其用于布局页面。我将其用于布局页面中呈现的局部视图

@myController.MyCommonValue
我们还希望得到强类型ViewModel的额外好处

因此,我创建了BaseViewModel和BaseController。所有ViewModels控制器将分别从BaseViewModel和BaseController继承

守则:

BaseController

public class BaseController : Controller
{
    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);

        var model = filterContext.Controller.ViewData.Model as BaseViewModel;

        model.AwesomeModelProperty = "Awesome Property Value";
        model.FooterModel = this.getFooterModel();
    }

    protected FooterModel getFooterModel()
    {
        FooterModel model = new FooterModel();
        model.FooterModelProperty = "OMG Becky!!! Another Awesome Property!";
    }
}
public class HomeController : BaseController
{
    public ActionResult Index(string id)
    {
        HomeIndexModel model = new HomeIndexModel();

        // populate HomeIndexModel ...

        return View(model);
    }
}
注意OnActionExecuted的用法,该用法取自

HomeController

public class BaseController : Controller
{
    protected override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        base.OnActionExecuted(filterContext);

        var model = filterContext.Controller.ViewData.Model as BaseViewModel;

        model.AwesomeModelProperty = "Awesome Property Value";
        model.FooterModel = this.getFooterModel();
    }

    protected FooterModel getFooterModel()
    {
        FooterModel model = new FooterModel();
        model.FooterModelProperty = "OMG Becky!!! Another Awesome Property!";
    }
}
public class HomeController : BaseController
{
    public ActionResult Index(string id)
    {
        HomeIndexModel model = new HomeIndexModel();

        // populate HomeIndexModel ...

        return View(model);
    }
}
BaseViewModel

public class BaseViewModel
{
    public string AwesomeModelProperty { get; set; }
    public FooterModel FooterModel { get; set; }
}
public class HomeIndexModel : BaseViewModel
{

    public string FirstName { get; set; }

    // other awesome properties
}
public class FooterModel
{
    public string FooterModelProperty { get; set; }
}
@model WebSite.Models.BaseViewModel
<!DOCTYPE html>
<html>
<head>
    < ... meta tags and styles and whatnot ... >
</head>
<body>
    <header>
        @{ Html.RenderPartial("_Nav", Model.FooterModel.FooterModelProperty);}
    </header>

    <main>
        <div class="container">
            @RenderBody()
        </div>

        @{ Html.RenderPartial("_AnotherPartial", Model); }
        @{ Html.RenderPartial("_Contact"); }
    </main>

    <footer>
        @{ Html.RenderPartial("_Footer", Model.FooterModel); }
    </footer>

    < ... render scripts ... >

    @RenderSection("scripts", required: false)
</body>
</html>
@model string
<nav>
    <ul>
        <li>
            <a href="@Model" target="_blank">Mind Blown!</a>
        </li>
    </ul>
</nav>
@section commonLayoutData{

    <script>

        var products = @Html.Raw(Json.Encode(Model.ToList()));

    </script>

    }
@RenderSection("commonLayoutData", false)
@project_name.Controllers.HomeController.username
@project_name.Controllers.HomeController.UserType
HomeViewModel

public class BaseViewModel
{
    public string AwesomeModelProperty { get; set; }
    public FooterModel FooterModel { get; set; }
}
public class HomeIndexModel : BaseViewModel
{

    public string FirstName { get; set; }

    // other awesome properties
}
public class FooterModel
{
    public string FooterModelProperty { get; set; }
}
@model WebSite.Models.BaseViewModel
<!DOCTYPE html>
<html>
<head>
    < ... meta tags and styles and whatnot ... >
</head>
<body>
    <header>
        @{ Html.RenderPartial("_Nav", Model.FooterModel.FooterModelProperty);}
    </header>

    <main>
        <div class="container">
            @RenderBody()
        </div>

        @{ Html.RenderPartial("_AnotherPartial", Model); }
        @{ Html.RenderPartial("_Contact"); }
    </main>

    <footer>
        @{ Html.RenderPartial("_Footer", Model.FooterModel); }
    </footer>

    < ... render scripts ... >

    @RenderSection("scripts", required: false)
</body>
</html>
@model string
<nav>
    <ul>
        <li>
            <a href="@Model" target="_blank">Mind Blown!</a>
        </li>
    </ul>
</nav>
@section commonLayoutData{

    <script>

        var products = @Html.Raw(Json.Encode(Model.ToList()));

    </script>

    }
@RenderSection("commonLayoutData", false)
@project_name.Controllers.HomeController.username
@project_name.Controllers.HomeController.UserType
页脚型号

public class BaseViewModel
{
    public string AwesomeModelProperty { get; set; }
    public FooterModel FooterModel { get; set; }
}
public class HomeIndexModel : BaseViewModel
{

    public string FirstName { get; set; }

    // other awesome properties
}
public class FooterModel
{
    public string FooterModelProperty { get; set; }
}
@model WebSite.Models.BaseViewModel
<!DOCTYPE html>
<html>
<head>
    < ... meta tags and styles and whatnot ... >
</head>
<body>
    <header>
        @{ Html.RenderPartial("_Nav", Model.FooterModel.FooterModelProperty);}
    </header>

    <main>
        <div class="container">
            @RenderBody()
        </div>

        @{ Html.RenderPartial("_AnotherPartial", Model); }
        @{ Html.RenderPartial("_Contact"); }
    </main>

    <footer>
        @{ Html.RenderPartial("_Footer", Model.FooterModel); }
    </footer>

    < ... render scripts ... >

    @RenderSection("scripts", required: false)
</body>
</html>
@model string
<nav>
    <ul>
        <li>
            <a href="@Model" target="_blank">Mind Blown!</a>
        </li>
    </ul>
</nav>
@section commonLayoutData{

    <script>

        var products = @Html.Raw(Json.Encode(Model.ToList()));

    </script>

    }
@RenderSection("commonLayoutData", false)
@project_name.Controllers.HomeController.username
@project_name.Controllers.HomeController.UserType
Layout.cshtml

public class BaseViewModel
{
    public string AwesomeModelProperty { get; set; }
    public FooterModel FooterModel { get; set; }
}
public class HomeIndexModel : BaseViewModel
{

    public string FirstName { get; set; }

    // other awesome properties
}
public class FooterModel
{
    public string FooterModelProperty { get; set; }
}
@model WebSite.Models.BaseViewModel
<!DOCTYPE html>
<html>
<head>
    < ... meta tags and styles and whatnot ... >
</head>
<body>
    <header>
        @{ Html.RenderPartial("_Nav", Model.FooterModel.FooterModelProperty);}
    </header>

    <main>
        <div class="container">
            @RenderBody()
        </div>

        @{ Html.RenderPartial("_AnotherPartial", Model); }
        @{ Html.RenderPartial("_Contact"); }
    </main>

    <footer>
        @{ Html.RenderPartial("_Footer", Model.FooterModel); }
    </footer>

    < ... render scripts ... >

    @RenderSection("scripts", required: false)
</body>
</html>
@model string
<nav>
    <ul>
        <li>
            <a href="@Model" target="_blank">Mind Blown!</a>
        </li>
    </ul>
</nav>
@section commonLayoutData{

    <script>

        var products = @Html.Raw(Json.Encode(Model.ToList()));

    </script>

    }
@RenderSection("commonLayoutData", false)
@project_name.Controllers.HomeController.username
@project_name.Controllers.HomeController.UserType
@model网站.Models.BaseViewModel
< ... 元标记、样式等等…>
@{Html.RenderPartial(“_Nav”,Model.FooterModel.FooterModelProperty);}
@RenderBody()
@{Html.RenderPartial(“_AnotherPartial”,Model);}
@{Html.RenderPartial(“_Contact”);}
@{Html.RenderPartial(“_Footer”,Model.FooterModel);}
< ... 渲染脚本…>
@RenderSection(“脚本”,必需:false)
\u Nav.cshtml

public class BaseViewModel
{
    public string AwesomeModelProperty { get; set; }
    public FooterModel FooterModel { get; set; }
}
public class HomeIndexModel : BaseViewModel
{

    public string FirstName { get; set; }

    // other awesome properties
}
public class FooterModel
{
    public string FooterModelProperty { get; set; }
}
@model WebSite.Models.BaseViewModel
<!DOCTYPE html>
<html>
<head>
    < ... meta tags and styles and whatnot ... >
</head>
<body>
    <header>
        @{ Html.RenderPartial("_Nav", Model.FooterModel.FooterModelProperty);}
    </header>

    <main>
        <div class="container">
            @RenderBody()
        </div>

        @{ Html.RenderPartial("_AnotherPartial", Model); }
        @{ Html.RenderPartial("_Contact"); }
    </main>

    <footer>
        @{ Html.RenderPartial("_Footer", Model.FooterModel); }
    </footer>

    < ... render scripts ... >

    @RenderSection("scripts", required: false)
</body>
</html>
@model string
<nav>
    <ul>
        <li>
            <a href="@Model" target="_blank">Mind Blown!</a>
        </li>
    </ul>
</nav>
@section commonLayoutData{

    <script>

        var products = @Html.Raw(Json.Encode(Model.ToList()));

    </script>

    }
@RenderSection("commonLayoutData", false)
@project_name.Controllers.HomeController.username
@project_name.Controllers.HomeController.UserType
@模型字符串

希望这会有所帮助。

而不是经历这些 您始终可以使用另一种同样快速的方法

在共享目录中创建一个新的局部视图,并在布局中将局部视图称为

@Html.Partial("MyPartialView")
在局部视图中,您可以调用db并执行任何您想要执行的操作

@{
    IEnumerable<HOXAT.Models.CourseCategory> categories = new HOXAT.Models.HOXATEntities().CourseCategories;
}

<div>
//do what ever here
</div>
@{
IEnumerable categories=新的HOXAT.Models.HOXATEntities().CourseCategories;
}
//你在这儿干什么
假设您已经添加了实体框架数据库,您可以这样使用:

 @{ 
    ApplicationDbContext db = new ApplicationDbContext();
    IEnumerable<YourModel> bd_recent = db.YourModel.Where(m => m.Pin == true).OrderByDescending(m=>m.ID).Select(m => m);
}
<div class="col-md-12">
    <div class="panel panel-default">
        <div class="panel-body">
            <div class="baner1">
                <h3 class="bb-hred">Recent Posts</h3>
                @foreach(var item in bd_recent)
                {
                    <a href="/BaiDangs/BaiDangChiTiet/@item.ID">@item.Name</a>
                }
            </div>
        </div>
    </div>
</div>
public static username = "Admin";
public static UserType = "Administrator";
@{
ApplicationDbContext db=新的ApplicationDbContext();
IEnumerable bd_recent=db.YourModel.Where(m=>m.Pin==true).OrderByDescending(m=>m.ID).选择(m=>m);
}
最近的职位
@foreach(bd_-recent中的var项目)
{
}

我认为这些答案对于大型企业级应用程序来说都不够灵活。我不喜欢过度使用ViewBag,但在这种情况下,为了灵活性,我会破例。这是我要做的

所有控制器上都应该有一个基本控制器。将布局数据添加到基本控制器中正在执行的OnActionExecuting(或者,如果您想延迟此操作,则添加OnActionExecuted)

然后在_Layout.cshtml中,从ViewBag中提取ViewModel

@{
  LayoutViewModel model = (LayoutViewModel)ViewBag.LayoutViewModel;
}

<h1>@model.Title</h1>
@{
LayoutViewModel=(LayoutViewModel)ViewBag.LayoutViewModel;
}
@模型名称
或者

@ViewBag.LayoutViewModel.Title

这样做不会影响页面控制器或视图模型的编码。

其他答案几乎涵盖了我们如何将模型传递到布局页面的所有内容。但是我发现了一种方法,可以使用它将变量动态地传递到布局页面,而无需在布局中使用任何模型或局部视图。假设你有这个模型-

public class SubLocationsViewModel
{
    public string city { get; set; }
    public string state { get; set; }
}
你想要动态地得到城市和州。例如

在index.cshtml中,您可以将这两个变量放在ViewBag中

@model  MyProject.Models.ViewModel.SubLocationsViewModel
@{
    ViewBag.City = Model.city;
    ViewBag.State = Model.state;
}
然后在layout.cshtml中,您可以访问这些viewbag变量

<div class="text-wrap">
    <div class="heading">@ViewBag.City @ViewBag.State</div>
</div>

@ViewBag.City@ViewBag.State

创建表示布局视图的基础视图