MVC - 向视图传递附加信息

发布于 2024-10-16 01:05:25 字数 1488 浏览 1 评论 0 原文

我正在使用 Asp.Net MVC 框架开发一个网站。我们需要在多个页面上添加一般用户信息,类似于堆栈溢出顶部的信誉栏。

我认为重要的是,为了将这些额外信息添加到视图中,创建控制器方法时不应增加任何开销。这排除了在 ViewData 对象中传递此信息的选项,或修改 ViewModel 以接受信誉字段的选项,因为这会导致每个控制器看起来像这样:

public ActionResult Index()
{
    ViewData["reputationScore"] = GetUsersReputation(userId);

    // main controller logic here
}

如果在站点上 90% 的页面上使用此信息,则可能是如果我们还想显示用户徽章计数,则更改相当耗时。

我可以想到 4 种解决方案

使用母版页 检索后面母版页代码中的用户信誉,并将信誉标记放在母版页标记中。

缺点:

  1. 这似乎背离了 MVC 所代表的一切。
  2. 我一直在考虑转向使用替代视图引擎(例如剃刀),我不确定这些引擎的混合效果如何。
  3. 它往往会限制声誉的布局 - 很难将其放在页面中间。

扩展 HtmlHelper 以添加 GetUsersReputation 方法 这似乎有点违反了 Html 对象的用途——它不仅仅是渲染输出,而是访问数据库。除了违反隐喻之外,我想不出任何其他重大问题。

覆盖 System.Web.Mvc.ViewPage 重写 Viewpage 以公开除 Html 之外的对象,该对象可用于调用访问数据库的一系列方法。确保可以以与 HtmlHelper 相同的方式添加扩展方法,以便在需要新方法时可以适当地扩展它。这可以让我们编写如下内容:

<% DataAccess.GetUsersReputation() %>

创建基本通用视图模型 不要将视图模型直接传递给视图,而是将其包装在可以容纳您需要的所有方法的基本视图模型中:

public ActionResult Index()
{
    MyViewModel viewCoreInfo = model.GetData();

    return View(new BaseViewModel<MyViewModel>(viewCoreInfo));
}

BaseViewModel 可以公开网页上所需的额外信息所需的所有属性。例如UsersReputation(它可以在构造函数中查询数据库,或者在访问属性时加载数据)。我认为这更好地维护了 MVC 的比喻,但有点麻烦。

  1. 其他人是否提出了更好的解决方案
  2. 哪一个是最好的 - 如果您使用过它们,它们是否有效/有问题?

I am developing a website using Asp.Net MVC framework. We need to add general user information across a number of pages, in a similar way to the reputation bar at the top of stack overflow.

I consider it important that there should be no overhead added to the creation of a controller method in order to add this extra information to the view. This excludes the option of passing this info in the ViewData object, or amending the ViewModels to accept the reputation field as it would result in every controller looking like this:

public ActionResult Index()
{
    ViewData["reputationScore"] = GetUsersReputation(userId);

    // main controller logic here
}

If this is used across 90% of the pages on a site, it could be quite time consuming to alter if we also wanted to display the users badge count.

I can think of 4 solutions to this

Use Master pages
Retrieve the user reputation in the master page code behind, and put the mark up for the reputation in the master page mark up.

Disadvantages:

  1. This seems to be moving away from everything that MVC represents.
  2. I have been looking at moving to using alternative view engines (e.g. razor) I am not sure how well these will mix.
  3. It tends to restrict the layout of the reputation - hard to put it in the middle of the page.

Extend HtmlHelper to add a GetUsersReputation method
This seems to be a slight violation of what the Html object should be used for - it is not just rendering output, but hitting the database. I can't think of any other significant issues with this other than the violation of the metaphor.

Override the System.Web.Mvc.ViewPage
Overriding Viewpage to expose an object in addition to Html that can be used to call a selection of methods that access the database. Make sure that extension methods can be added in the same way as HtmlHelper, so that as and when new methods are needed it can be extended appropriately. This could allow us to write something like:

<% DataAccess.GetUsersReputation() %>

Create a base generic view model
Rather than passing your view model straight to the view, wrap it in a base view model that can hold all the methods you need:

public ActionResult Index()
{
    MyViewModel viewCoreInfo = model.GetData();

    return View(new BaseViewModel<MyViewModel>(viewCoreInfo));
}

BaseViewModel can expose all the properties that you need for extra information required on the web page. e.g. UsersReputation (it could either query the database in the constructor, or load the data when the property is accessed). I think this maintains the MVC metaphor better, but is a little cumbersome.

  1. Has someone else come up with a better solution
  2. Which is best - if you have used them have they been effective /problematic?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

你又不是我 2024-10-23 01:05:25

既然您提到了迁移到剃刀视图引擎的可能性,我认为 ScottGu 的这篇博客文章可能会引起兴趣。

他讨论了使用 razor 的“部分”,这将允许您在布局(“母版页”)上创建一个部分,您可以加载附加内容。以这种方式创建 SO 风格的信息栏将会干净简单。

编辑:

按照下面的评论渲染部分视图...新的mvc 音乐商店教程 有一些示例。

在本例中,他们使用 Html.RenderAction。 Html.RenderPartial 是另一种选择。
这个问题中概述了这些差异,但我确信网上还有其他资源。

您的控制器只会返回部分视图,如下所示:

 return PartialView();

Since you mentioned the possibility of moving to the razor view engine, I think that THIS blog post by ScottGu might be of interest.

He discusses using 'sections' with razor that will alow you to create a section on your Layout("Masterpage") that you can load with addition content. Creating your SO style info bar in this manner would be clean and simple.

EDIT:

As far as rendering partial views as per the comments below...the new mvc music store tutorial has some examples.

In this case they are using Html.RenderAction. Html.RenderPartial is another option.
The differences are outlned in this question but im sure there are other resources on the net.

Your controller would just return a partial view as such:

 return PartialView();
少女情怀诗 2024-10-23 01:05:25

为什么不让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
    }
}

Why don't you let MyViewModel inherit BaseViewModel?

The you can use BaseController.OnResultExecuting to fill the common values:

protected override void OnResultExecuting(ResultExecutingContext ctx) {
    base.OnResultExecuting(ctx);
    var baseView = ctx.Result as BaseViewModel;
    if (baseView != null)
    {
        //assign values here
    }
}
秋千易 2024-10-23 01:05:25

您可以创建操作过滤器,覆盖 OnResultExecuting,填充通用值并将其添加到您的操作/控制器中:

public class AddCommonData : ActionFilterAttribute 
{
  public override void OnResultExecuting(ResultExecutingContext filterContext)
  {
    ViewResult viewResult = filterContext.Result as ViewResult;
    if (viewResult != null)
    {
      //...
    } 
  }
}

You can create action filter, override OnResultExecuting, fill the common values and add it to your action/controller:

public class AddCommonData : ActionFilterAttribute 
{
  public override void OnResultExecuting(ResultExecutingContext filterContext)
  {
    ViewResult viewResult = filterContext.Result as ViewResult;
    if (viewResult != null)
    {
      //...
    } 
  }
}
终遇你 2024-10-23 01:05:25

我已经做到了这一点,并创建了一个包含所有共同信息的基础模型类。我的所有其他视图模型类都继承自这个类。但是您必须在每个控制器中填充这些信息。这是我选择的解决方案。

I've done that and i made a base model class with all the information in common. All my other viewmodel class inherits from this one. But you have to populate in each controller these informations. This is the solution I've choosed.

度的依靠╰つ 2024-10-23 01:05:25

您可以使用代码隐藏文件创建部分视图,您将在其中使用数据填充部分视图。这有点非 mvc 方式,但它会起作用。

You can create partial view with codebehind file where you'll populate partial view with data. It is a bit non-mvc way but it'll work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文