C# MVC-向视图传递附加信息
我正在使用Asp.NETMVC框架开发一个网站。我们需要跨多个页面添加一般用户信息,方法与堆栈顶部的信誉栏类似C# MVC-向视图传递附加信息,c#,asp.net-mvc,asp.net-mvc-2,C#,Asp.net Mvc,Asp.net Mvc 2,我正在使用Asp.NETMVC框架开发一个网站。我们需要跨多个页面添加一般用户信息,方法与堆栈顶部的信誉栏类似 我认为重要的是,在创建控制器方法时不应该添加任何开销,以便将额外的信息添加到视图中。这排除了在ViewData对象中传递此信息的选项,或修改ViewModels以接受信誉字段的选项,因为这将导致每个控制器的外观如下所示: public ActionResult Index() { ViewData["reputationScore"] = GetUsersReputation(
我认为重要的是,在创建控制器方法时不应该添加任何开销,以便将额外的信息添加到视图中。这排除了在ViewData对象中传递此信息的选项,或修改ViewModels以接受信誉字段的选项,因为这将导致每个控制器的外观如下所示:
public ActionResult Index()
{
ViewData["reputationScore"] = GetUsersReputation(userId);
// main controller logic here
}
如果一个站点上90%的页面都使用了这种方法,那么如果我们还想显示用户的徽章数量,那么修改它可能会非常耗时
我可以想出4种解决方案
使用母版页
在母版页代码中检索用户信誉,并在母版页标记中标记信誉
缺点:
<% DataAccess.GetUsersReputation() %>
创建基本通用视图模型
与其将视图模型直接传递给视图,不如将其包装在可以容纳所有所需方法的基础视图模型中:
public ActionResult Index()
{
MyViewModel viewCoreInfo = model.GetData();
return View(new BaseViewModel<MyViewModel>(viewCoreInfo));
}
public ActionResult Index()
{
MyViewModel viewCoreInfo=model.GetData();
返回视图(新的BaseViewModel(viewCoreInfo));
}
BaseViewModel可以公开网页上需要的额外信息所需的所有属性。e、 g.用户计算(它可以在构造函数中查询数据库,也可以在访问属性时加载数据)。我认为这更好地保持了MVC的比喻,但有点麻烦
我已经完成了这项工作,并创建了一个基本模型类,其中包含所有共同的信息。我的所有其他viewmodel类都继承自此类。但是您必须在每个控制器中填充这些信息。这就是我选择的解决方案。为什么不让
MyViewModel
继承BaseViewModel
您可以使用BaseController.OnResultExecuting
填充公共值:
protected override void OnResultExecuting(ResultExecutingContext ctx) {
base.OnResultExecuting(ctx);
var baseView = ctx.Result as BaseViewModel;
if (baseView != null)
{
//assign values here
}
}
既然您提到了使用razor视图引擎的可能性,我想ScottGu的博客文章可能会引起兴趣 他讨论了如何在razor中使用“sections”,这将允许您在布局(“母版页”)上创建一个可以加载附加内容的部分。以这种方式创建SO样式信息栏将是干净而简单的 编辑: 至于根据下面的评论呈现局部视图…新的有一些例子 在本例中,他们使用的是Html.RenderAction。Html.RenderPartial是另一个选项。 在这一点上,差异是显而易见的,但我确信网络上还有其他资源 控制器只会返回部分视图,如下所示:
return PartialView();
您可以使用代码隐藏文件创建局部视图,并在其中使用数据填充局部视图。这是一种有点非mvc的方式,但它会起作用。您可以创建操作筛选器,覆盖OnResultExecuting,填充公共值并将其添加到操作/控制器:
public class AddCommonData : ActionFilterAttribute
{
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
ViewResult viewResult = filterContext.Result as ViewResult;
if (viewResult != null)
{
//...
}
}
}
节与Webforms引擎中的内容占位符一样。这并不能真正解决OP的问题。OP想知道如何从控制器传输视图/分区/任何内容中的信息。谢谢您的回答。我认为这仍然存在同样的问题,尽管razor允许您使用母版页创建标记,但通常认为在视图(而不是显示逻辑)中编写代码是不好的做法。它当然不是放置数据访问方法的地方——这实际上是模型/控制器的责任。但是,为了防止重复,我希望避免在每个控制器中调用声誉方法。@Giles我明白你的意思。如果该部分呈现一个partialview,调用自己的控制器/操作或类似的东西,会怎么样?@Stephen776如果可能的话,这听起来是一个不错的解决方案。可以从局部视图中调用控制器吗?你在任何地方见过这样的例子吗?@Giles是的,我相信它就像Html.RenderPartial(“动作”、“控制器”、“其他参数(可选)”)一样简单。我知道我的开发机器上有一个这样的示例。当我找到答案时,我可以贴一个例子。我喜欢重写OnResultExecuting方法的想法。我担心的是让MyViewModel继承BaseViewModel,然后在这两个类之间引入耦合。如果您后来决定需要另一组页面来显示好友数,但您仍然使用MyViewModel作为主要数据,则需要允许BaseViewModel同时实现好友和信誉方法。与我的解决方案一样,您只需更改FriendDataBaseVie的BaseViewModel