【问题标题】:Pass data to layout that are common to all pages将数据传递给所有页面通用的布局
【发布时间】:2012-11-05 02:44:26
【问题描述】:

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

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

【问题讨论】:

  • 对于阅读此处回复的任何人,请参阅stackoverflow.com/a/21130867/706346,在那里您将看到比此处发布的任何内容都更简单、更整洁的解决方案。
  • @AvrohomYisroel 好建议。但是我更喜欢@Colin Bacon 的方法,因为它是强类型的,而不是在ViewBag 中。也许是偏好问题。虽然支持您的评论
  • 对于 mvc 5 看到这个答案:stackoverflow.com/a/46783375/5519026

标签: asp.net-mvc-4


【解决方案1】:

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

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

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

编辑:从下面的 cmets 更新

这里有一个简单的例子来演示这个概念。

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

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>

最后在action方法中设置数据。

public class HomeController
{
    public ActionResult Index()
    {
        return this.View(new HomeViewModel { Name = "Bacon" });
    }
}

【讨论】:

  • 但是布局中使用了数据。如何将数据传递给布局?
  • 完美!我看到了我的错误。我忘了将模型传递给视图..真是个蹩脚的错误。谢谢!
  • 这种方法的问题是有时不是每个视图都有一个 ViewModel,所以在这种情况下这不起作用:O/
  • 但这不是要求每个控制器和每个动作都包含 { Name = "Bacon" } 代码吗?如果我想向 ViewModelBase 添加另一个属性,我必须转到每个控制器和每个操作并添加代码来填充该属性?您提到“如果需要逻辑 [...],则应将其放入基本控制器 [...]”。这将如何消除每个控制器和每个操作中的重复代码?
  • @Lee 如果它是跨所有页面的通用数据,那么您可以放置​​一个基本控制器。然后,您的控制器从这个基本控制器继承。例如public class HomeController : BaseController。这样通用代码只需编写一次,即可应用于所有控制器。
【解决方案2】:

我在布局中使用了 RenderAction html 助手来实现剃刀。

@{
   Html.RenderAction("Action", "Controller");
 }

我需要它来制作简单的字符串。所以我的操作返回字符串并在视图中轻松写下来。 但是如果你需要复杂的数据,你可以返回 PartialViewResult 和模型。

 public PartialViewResult Action()
    {
        var model = someList;
        return PartialView("~/Views/Shared/_maPartialView.cshtml", model);
    }

您只需将模型放在您创建的局部视图“_maPartialView.cshtml”的开头

@model List<WhatEverYourObjeIs>

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

【讨论】:

  • 这绝对是最好的答案!
  • @gingerbreadboy 同意它促进了良好的封装和关注点分离。
【解决方案3】:

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

【讨论】:

  • 这实际上听起来像是最不痛苦的解决方案,有什么缺点吗? +1
  • 绝对是最好的解决方案,我没有看到任何缺点。
  • 我看不出这给了你什么。如果您有一个包含布局所需的所有属性的类,为什么还要费心将其添加到 ViewBag 中而不得不再次将其转换回来?在布局视图中使用模型,您仍然可以在OnActionExecuting 中填充模型。使用 ViewBag 还意味着您在控制器中失去了类型安全性,这绝不是一件好事。
  • 这让我能够添加一个布局模型,而无需在一个已经存在的项目中重组所有模型以从所有控制器的所有方法中的单个“超级”模型继承.如果您是从头开始,您可以选择从公共根中派生所有模型。
  • @ColinBacon 此选项的另一个优点是您的操作不需要始终具有视图模型。此外,我认为开发人员需要知道他们必须始终从基础继承他们的视图模型是一个劣势。
【解决方案4】:

据推测,其主要用例是为所有(或大部分)控制器操作获取视图的基本模型。

鉴于此,我使用了其中几个答案的组合,主要是基于 Colin Bacon 的答案。

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

我们希望这发生在所有控制器上,因为我们将它用于布局页面。我将它用于在布局页面中呈现的部分视图。

我们还想要强类型 ViewModel 的额外好处

因此,我创建了 BaseViewModel 和 BaseController。所有的 ViewModels 控制器都将分别继承自 BaseViewModel 和 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!";
    }
}

注意 OnActionExecuted 的使用取自this SO post

HomeController

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; }
}

HomeViewModel

public class HomeIndexModel : BaseViewModel
{

    public string FirstName { get; set; }

    // other awesome properties
}

FooterModel

public class FooterModel
{
    public string FooterModelProperty { get; set; }
}

Layout.cshtml

@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>

_Nav.cshtml

@model string
<nav>
    <ul>
        <li>
            <a href="@Model" target="_blank">Mind Blown!</a>
        </li>
    </ul>
</nav>

希望这会有所帮助。

【讨论】:

  • 我使用了这种方法,但更喜欢从接口而不是基类继承。所以我做了: var model = filterContext.Controller.ViewData.Model as IBaseViewModel if (model != null) { model.AwesomeModelProperty = "Awesome Property Value"; }
  • 很好的答案,我更喜欢这个。
  • 很好的答案,但我有一个问题。 “如果我有一些没有 ViewModels 的视图怎么办?”
  • 试过了,但是在 Index Action 上, OnActionExecuted 填充了 FooterModel,然后用 null FooterModel 创建了一个新的 HomeIndexModel :(
  • @drizzie:在你的基础控制器中,model 是 Filter 方法中的一个局部变量:var model = filterContext.Controller.ViewData.Model as BaseViewModel。我不明白 MVC 是如何理解这个局部变量与 HomeController 发送给查看的模型相同的。
【解决方案5】:

还有另一种处理方式。从架构的角度来看,这可能不是最干净的方式,但它避免了与其他答案相关的很多痛苦。只需在 Razor 布局中注入服务,然后调用获取必要数据的方法:

@inject IService myService

然后在布局视图中:

@if (await myService.GetBoolValue()) {
   // Good to go...
}

同样,在架构方面并不干净(显然服务不应该直接注入到视图中),但它可以完成工作。

【讨论】:

  • 不是最干净的方式?我不同意。我认为这很干净:对象从创建它的地方直接传递到你想要它的地方,而不会用他们不需要看到的项目“污染”其他控制器。在我看来,使用@inject 是最好的解决方案。
  • 多想想这个也许你是对的。这种方法避免了如此多的痛苦这一事实表明它可能是最干净的方法。我一直在开发一个非常大的 ASP.NET Core 应用程序,并且我将这种模式用于导航面包屑逻辑、大多数页面上的标题数据等。通过这样做,我避免了很多痛苦。
  • 这个技术也被 _LoginPartial.cshtml 使用,当你在启用了 Identity 的情况下搭建一个 Asp.Net Core Razor 页面项目时,它是一个自动生成的视图。
【解决方案6】:

您不必弄乱操作或更改模型,只需使用基本控制器并从布局视图上下文中转换现有控制器。

使用所需的公共数据(标题/页面/位置等)和操作初始化创建一个基本控制器...

public abstract class _BaseController:Controller {
    public Int32 MyCommonValue { get; private set; }

    protected override void OnActionExecuting(ActionExecutingContext filterContext) {

        MyCommonValue = 12345;

        base.OnActionExecuting(filterContext);
    }
}

确保每个控制器都使用基本控制器...

public class UserController:_BaseController {...

_Layout.cshml 页面中的视图上下文中转换现有的基本控制器...

@{
    var myController = (_BaseController)ViewContext.Controller;
}

现在您可以从布局页面引用基本控制器中的值。

@myController.MyCommonValue

更新

您还可以创建一个页面扩展,允许您使用this

//Allows typed "this.Controller()." in cshtml files
public static class MyPageExtensions {
    public static _BaseController Controller(this WebViewPage page) => Controller<_BaseController>(page);
    public static T Controller<T>(this WebViewPage page) where T : _BaseController => (T)page.ViewContext.Controller;
}

那么你只需要记住在需要控制器时使用this.Controller()

@{
    var myController = this.Controller(); //_BaseController
}

或从_BaseController继承的特定控制器...

@{
    var myController = this.Controller<MyControllerType>();
}

【讨论】:

  • .net core 中的 this 等价物是什么?由于 ViewContext.Controller 不存在并且继承链发生了一些变化
【解决方案7】:

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

@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>

并将其添加到控制器中:

public ActionResult _Header(ViewAsModelBase model)

【讨论】:

    【解决方案8】:

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

    您应该在所有控制器上都有一个基本控制器。在您的基本控制器中添加您的布局数据 OnActionExecuting(或 OnActionExecuted,如果您想推迟它)...

    public class BaseController : Controller
    {
        protected override void OnActionExecuting(ActionExecutingContext     
            filterContext)
        {
            ViewBag.LayoutViewModel = MyLayoutViewModel;
        }
    }
    
    public class HomeController : BaseController
    {
        public ActionResult Index()
        {
            return View(homeModel);
        }
    }
    

    然后在您的 _Layout.cshtml 中从 ViewBag 中拉出您的 ViewModel...

    @{
      LayoutViewModel model = (LayoutViewModel)ViewBag.LayoutViewModel;
    }
    
    <h1>@model.Title</h1>
    

    或者……

    <h1>@ViewBag.LayoutViewModel.Title</h1>
    

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

    【讨论】:

    • 我喜欢你的想法,但是如果你有一个动态创建的MyLayoutViewModel,我如何将一些参数传递给OnActionExecuting 方法?
    • 呃,你的OnActionExecuting方法中仍然需要base.OnActionExecuting(filterContext)!!!
    【解决方案9】:

    创建一个代表布局视图模型的基础视图是一种糟糕的方法。想象一下,您想要一个模型来表示布局中定义的导航。你会CustomersViewModel : LayoutNavigationViewModel吗?为什么?为什么要通过解决方案中的每个视图模型传递导航模型数据?

    布局视图模型应该是专用的,独立的,不应该强迫其余的视图模型依赖它。

    相反,您可以在 _Layout.cshtml 文件中执行此操作:

    @{ var model = DependencyResolver.Current.GetService<MyNamespace.LayoutViewModel>(); }
    

    最重要的是,我们不需要new LayoutViewModel(),我们将获得LayoutViewModel 拥有的所有依赖项,为我们解决。

    例如

    public class LayoutViewModel
    {
        private readonly DataContext dataContext;
        private readonly ApplicationUserManager userManager;
    
        public LayoutViewModel(DataContext dataContext, ApplicationUserManager userManager)
        {
        }
    }
    

    【讨论】:

    • 你在哪里填充这个模型?在 BaseController 中也是如此?
    • 我想这对于 ASP..Net Core 中的 Scoped 布局模型对象也是一个好主意。
    • 我不会让视图去获取依赖项。那绝对不是“MVC”。 Service Locator is an anti-pattern.
    • 与流行的看法相反,Service Locator 不是反模式,实际上这与 MVC 无关,你只是在抛出流行语@Jiveman? blog.gauffin.org/2012/09/service-locator-is-not-an-anti-pattern
    • Jgauffin 在那篇文章中的主要观点似乎是“反模式”一词不应该应用于服务定位器,因为 SL 至少可以有一些有效的用途。一个公平的观点。然而,正如在他自己的一些讨论 cmets 中显而易见的那样,他建议虽然 SL 在构建库和框架时可能是一种有效的方法,但在构建应用程序时不一定推荐它(我认为 OP 的问题和这里的讨论是旋转)。
    【解决方案10】:

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

    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>
    

    【讨论】:

    • 这很好用,@stun_Gravy 使用 ViewBag 传递角色或用户访问级别等数据是否会失败?
    【解决方案11】:

    您也可以使用 RenderSection ,它可以帮助您将您的 Model 数据注入到 _Layout 视图中。

    您可以注入View Model 数据、JsonScriptCSSHTML

    在此示例中,我将 Json 从我的 Index 视图注入到 Layout 视图。

    Index.chtml

    @section commonLayoutData{
    
        <script>
    
            var products = @Html.Raw(Json.Encode(Model.ToList()));
    
        </script>
    
        }
    

    _Layout.cshtml

    @RenderSection("commonLayoutData", false)
    

    这样就无需创建单独的 Base View Model

    希望能帮助别人。

    【讨论】:

    • 当您需要为少数视图呈现特定内容时的完美解决方案。
    【解决方案12】:

    为什么没有人建议 ViewData 的扩展方法?

    选项#1

    在我看来,到目前为止,该问题的侵入性最小且最简单的解决方案。没有硬编码的字符串。没有强加限制。没有魔法编码。没有复杂的代码。

    public static class ViewDataExtensions
    {
        private const string TitleData = "Title";
        public static void SetTitle<T>(this ViewDataDictionary<T> viewData, string value) => viewData[TitleData] = value;
        public static string GetTitle<T>(this ViewDataDictionary<T> viewData) => (string)viewData[TitleData] ?? "";
    }
    

    在页面中设置数据

    ViewData.SetTitle("abc");
    

    选项 #2

    另一个选项,使字段声明更容易。

    public static class ViewDataExtensions
    {
        public static ViewDataField<string, V> Title<V>(this ViewDataDictionary<V> viewData) => new ViewDataField<string, V>(viewData, "Title", "");
    }
    
    public class ViewDataField<T,V>
    {
        private readonly ViewDataDictionary<V> _viewData;
        private readonly string _field;
        private readonly T _defaultValue;
    
        public ViewDataField(ViewDataDictionary<V> viewData, string field, T defaultValue)
        {
            _viewData = viewData;
            _field = field;
            _defaultValue = defaultValue;
        }
    
        public T Value {
            get => (T)(_viewData[_field] ?? _defaultValue);
            set => _viewData[_field] = value;
        }
    }
    

    在页面中设置数据。声明比第一个选项更容易,但使用语法稍长。

    ViewData.Title().Value = "abc";
    

    选项#3

    然后可以将其与返回包含所有布局相关字段及其默认值的单个对象结合起来。

    public static class ViewDataExtensions
    {
        private const string LayoutField = "Layout";
        public static LayoutData Layout<T>(this ViewDataDictionary<T> viewData) => 
            (LayoutData)(viewData[LayoutField] ?? (viewData[LayoutField] = new LayoutData()));
    }
    
    public class LayoutData
    {
        public string Title { get; set; } = "";
    }
    

    在页面中设置数据

    var layout = ViewData.Layout();
    layout.Title = "abc";
    

    这第三种选择有几个好处,我认为在大多数情况下是最好的选择:

    • 字段和默认值的最简单声明。

    • 设置多个字段时最简单的使用语法。

    • 允许在 ViewData 中设置各种数据(例如布局、标题、导航)。

    • 允许在 LayoutData 类中添加额外的代码和逻辑。

    附:不要忘记在 _ViewImports.cshtml 中添加 ViewDataExtensions 的命名空间

    【讨论】:

      【解决方案13】:

      您可以在 App_Code 文件夹中创建一个 razor 文件,然后从您的视图页面访问它。

      项目>Repository/IdentityRepository.cs

      namespace Infrastructure.Repository
      {
          public class IdentityRepository : IIdentityRepository
          {
              private readonly ISystemSettings _systemSettings;
              private readonly ISessionDataManager _sessionDataManager;
      
              public IdentityRepository(
                  ISystemSettings systemSettings
                  )
              {
                  _systemSettings = systemSettings;
              }
      
              public string GetCurrentUserName()
              {
                  return HttpContext.Current.User.Identity.Name;
              }
          }
      }
      

      项目>App_Code/IdentityRepositoryViewFunctions.cshtml:

      @using System.Web.Mvc
      @using Infrastructure.Repository
      @functions
      {
          public static IIdentityRepository IdentityRepositoryInstance
          {
              get { return DependencyResolver.Current.GetService<IIdentityRepository>(); }
          }
      
          public static string GetCurrentUserName
          {
              get
              {
                  var identityRepo = IdentityRepositoryInstance;
                  if (identityRepo != null)
                  {
                      return identityRepo.GetCurrentUserName();
                  }
                  return null;
              }
          }
      }
      

      Project>Views/Shared/_Layout.cshtml(或任何其他 .cshtml 文件)

      <div>
          @IdentityRepositoryViewFunctions.GetCurrentUserName
      </div>
      

      【讨论】:

        【解决方案14】:

        在 .NET Core 中,您可以使用视图组件来执行此操作。

        https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-5.0

        从上面的链接中,添加一个从 ViewComponent 继承的类

        using Microsoft.AspNetCore.Mvc;
        using Microsoft.EntityFrameworkCore;
        using System.Collections.Generic;
        using System.Linq;
        using System.Threading.Tasks;
        using ViewComponentSample.Models;
        
        namespace ViewComponentSample.ViewComponents
        {
            public class PriorityListViewComponent : ViewComponent
            {
                private readonly ToDoContext db;
        
                public PriorityListViewComponent(ToDoContext context)
                {
                    db = context;
                }
        
                public async Task<IViewComponentResult> InvokeAsync(
                int maxPriority, bool isDone)
                {
                    var items = await GetItemsAsync(maxPriority, isDone);
                    return View(items);
                }
                private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)
                {
                    return db.ToDo.Where(x => x.IsDone == isDone &&
                                         x.Priority <= maxPriority).ToListAsync();
                }
            }
        }
        

        那么在你看来(_layout 在我的情况下)

        @await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
        

        如果您需要查看,请在~/Views/Shared/Components/&lt;Component Name&gt;/Default.cshtml 创建一个文件夹。您需要创建文件夹Components,然后在其中使用您的组件名称创建一个文件夹。在上面的示例中,PriorityList

        【讨论】:

          【解决方案15】:

          使用静态字符串(如页面标题、页面名称和位置等)的最佳方式是通过 ViewData 定义。只需在 ViewStart.cshtml

          中定义所需的 ViewData
          @{
              Layout = "_Layout";
              ViewData["Title"] = "Title";
              ViewData["Address"] = "1425 Lane, Skardu,<br> Pakistan";
          }
          

          并在需要时调用

          <div class="rn-info-content">
               <h2 class="rn-contact-title">Address</h2>
                   <address>
                       @Html.Raw(ViewData["Address"].ToString())
                   </address>
          </div>
          

          【讨论】:

            【解决方案16】:

            而不是经历这个 您总是可以使用另一种也很快的方法

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

            @Html.Partial("MyPartialView")
            

            在您的局部视图中,您可以调用您的数据库并执行您想做的任何事情

            @{
                IEnumerable<HOXAT.Models.CourseCategory> categories = new HOXAT.Models.HOXATEntities().CourseCategories;
            }
            
            <div>
            //do what ever here
            </div>
            

            假设您已经添加了实体框架数据库

            【讨论】:

            • 向下转型,因为获取自己的模型不应该是视图的责任。
            【解决方案17】:

            令人难以置信的是,这里没有人这么说。通过基本控制器传递视图模型是一团糟。我们正在使用用户声明将信息传递到布局页面(例如,用于在导航栏上显示用户数据)。 还有一个优势。数据通过 cookie 存储,因此无需通过部分检索每个请求中的数据。 只需在谷歌上搜索“asp 网络身份声明”即可。

            【讨论】:

            • @CodeSmith 什么?我正在提供解决方案。
            • 我的错,以为这是一个问题,但现在看到它是一个回复,已删除。
            • 如果这是试图回答问题,则应予以澄清。评论是可以容忍的,但它不应该主导整个答案;此外,关于 google 什么的提示不构成有效答案。
            【解决方案18】:

            我所做的很简单,而且很有效

            在任何控制器中声明静态属性,或者如果您愿意,可以使用静态值创建数据类:

            public static username = "Admin";
            public static UserType = "Administrator";
            

            控制器可以根据操作更新这些值。 稍后您可以在 _Layout 中使用它们

            在_layout.cshtml中

            @project_name.Controllers.HomeController.username
            @project_name.Controllers.HomeController.UserType
            

            【讨论】:

            • 为您的答案添加一些解释总是有帮助的,以使其更加清晰易懂。请阅读stackoverflow.com/help/how-to-answer
            • 这个“答案”是错误的 - 静态变量在所有用户会话之间共享,因此所有用户将获得相同的值。这绝对不是必需的。此外,它还增加了安全风险。
            【解决方案19】:

            你可以这样使用:

             @{ 
                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>
            

            【讨论】:

            • 在视图中连接数据库真是个坏主意。
            猜你喜欢
            • 2012-05-20
            • 1970-01-01
            • 2020-10-15
            • 2020-07-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多