ASP.NET MVC Razor传递模型来布局
我看到的是一个string布局属性。 但是,我怎样才能明确地将模型传递给布局呢?
好像你已经build立了你的viewmodels有点错误,如果你有这个问题。
就个人而言,我绝不会input布局页面。 但是,如果你想这样做,你应该有一个基本的视图模型,你的其他视图模型inheritance,并键入您的布局基本viewmodel和页面到特定的一次。
- 添加一个属性到您的控制器(或基本控制器)称为MainLayoutViewModel(或其他)与您想使用的任何types。
- 在控制器(或基础控制器)的构造函数中,实例化types并将其设置为属性。
- 将其设置为ViewData字段(或ViewBag)
- 在“布局”页面中,将该属性转换为您的types。
示例:控制器:
public class MyController : Controller { public MainLayoutViewModel MainLayoutViewModel { get; set; } public MyController() { this.MainLayoutViewModel = new MainLayoutViewModel();//has property PageTitle this.MainLayoutViewModel.PageTitle = "my title"; this.ViewData["MainLayoutViewModel"] = this.MainLayoutViewModel; } }
布局页面顶部的示例
@{ var viewModel = (MainLayoutViewModel)ViewBag.MainLayoutViewModel; }
现在,您可以在布局页面中引用variables“viewModel”,并完全访问input的对象。
我喜欢这种方法,因为它是控制布局的控制器,而单个页面视图模型保持布局不可知。
MVC Core的注意事项
Mvc Core似乎在第一次调用每个动作时就会吹走ViewData / ViewBag的内容。 这意味着在构造函数中分配ViewData不起作用。 但是,有什么工作是使用IActionFilter
并在OnActionExecuting
相同的工作。 将MyActionFilter
放在MyController
。
public class MyActionFilter: Attribute, IActionFilter { public void OnActionExecuted(ActionExecutedContext context) { } public void OnActionExecuting(ActionExecutingContext context) { var myController= context.Controller as MyController; if (myController!= null) { myController.Layout = new MainLayoutViewModel { }; myController.ViewBag.MainLayoutViewModel= myController.Layout; } } }
这是非常基本的东西,所有你需要做的是创build一个基本视图模型,并确保ALL! 我的意思是全部! 你的意见,将使用该布局将收到使用该基本模型的意见!
public class SomeViewModel : ViewModelBase { public bool ImNotEmpty = true; } public class EmptyViewModel : ViewModelBase { } public abstract class ViewModelBase { }
在_Layout.cshtml中:
@model Models.ViewModelBase <!DOCTYPE html> <html> and so on...
在家庭控制器中的索引(例如)方法中:
public ActionResult Index() { var model = new SomeViewModel() { }; return View(model); }
Index.cshtml:
@model Models.SomeViewModel @{ ViewBag.Title = "Title"; Layout = "~/Views/Shared/_Layout.cshtml"; } <div class="row">
我不同意将模型传递给_layout是一个错误,一些用户信息可以传递,数据可以在控制器inheritance链中填充,所以只需要一个实现。
显然,为了更高级的目的,您应该考虑使用注入来创build自定义静态联系人,并在_Layout.cshtml中包含该模型名称空间。
但对于基本的用户来说,这将是诀窍
为什么不只是添加一个新的局部视图与我自己的特定控制器将所需的模型传递给局部视图,最后使用RenderPartial或RenderAction渲染你的Layout.cshtml上提到的局部视图?
我使用这种方法来显示login用户的信息,如姓名,个人资料图片等
假设你的模型是对象的集合(或者可能是单个对象)。 对于模型中的每个对象,请执行以下操作。
1)把你想要显示的对象放在ViewBag中。 例如:
ViewBag.YourObject = yourObject;
2)在_Layout.cshtml的顶部添加using语句,该语句包含对象的类定义。 例如:
@using YourApplication.YourClasses;
3)当你在_Layout中引用你的对象时, 因为你在(2)中做了什么,所以你可以申请演员。
也许从技术上讲它不是正确的方法来处理它,但对我来说最简单和最合理的解决scheme是在布局中创build一个类并将其实例化。 这是一个例外,否则正确的做法。 如果这样做比在布局中做得更多,那么你需要认真地重新思考自己在做什么,也许在你的项目进一步发展之前再读一些教程。
public class MyLayoutModel { public User CurrentUser { get { .. get the current user .. } } }
然后在视图中
@{ // Or get if from your DI container var myLayoutModel = new MyLayoutModel(); }
在.net内核中,您甚至可以跳过并使用dependency injection。
@inject My.Namespace.IMyLayoutModel myLayoutModel
这是那种阴凉的地方之一。 但是鉴于我在这里看到的极其复杂的select,我认为以实用性的名义来说,这不仅仅是一个例外。 特别是如果你确保保持简单,并确保任何重逻辑(我认为真的不应该有任何,但要求不同)是在其所属的另一个类/层。 为了基本上只有一个观点,它肯定比污染你所有的控制器或模型更好。
老问题,但只是提到MVC5开发人员的解决scheme,您可以使用Model
属性相同的视图。
视图和布局中的Model
属性都与相同的ViewDataDictionary
对象相关联,因此您不必执行任何额外的工作将模型传递到布局页面,也不必在布局中声明@model MyModelName
。
但是请注意,当在布局中使用@Model.XXX
,intelliSense上下文菜单将不会出现,因为这里的Model
是一个像ViewBag
一样的dynamic对象。
public interface IContainsMyModel { ViewModel Model { get; } } public class ViewModel : IContainsMyModel { public string MyProperty { set; get; } public ViewModel Model { get { return this; } } } public class Composition : IContainsMyModel { public ViewModel ViewModel { get; set; } }
在布局中使用IContainsMyModel。
解决了。 接口规则。
例如
@model IList<Model.User> @{ Layout="~/Views/Shared/SiteLayout.cshtml"; }
阅读更多关于新的@model指令