11

我一直在玩 ASP.NET MVC 并且有一个问题。或者也许它担心我做错了。只是在一个蹩脚的网站上工作以伸展我的翅膀。很抱歉,这个问题一点也不简洁。

好的,这是场景。当用户访问主页/索引时,页面应显示产品列表和文章列表。文件布局是这样的(DAL 是我的数据访问层):

控制器
    家
        指数       

意见
    家
        索引继承自 ViewPage
    产品         
        列表继承自 ViewUserControl<IEnumerable<DAL.Product>>
        Single 继承自 ViewUserControl<DAL.Product>
    文章
        List 继承自 ViewUserControl<IEnumerable<DAL.Article>>
        Single 继承自 ViewUserControl<DAL.Article>
Controllers.HomeController.Index produces a View whose ViewData contains two entries, a IEnumerable<DAL.Product> and a IEnumerable<DAL.Article>.

View.Home.Index will use those view entries to call:
Html.RenderPartial("~/Views/Product/List.ascx", ViewData["ProductList"])
and Html.RenderPartial("~/Views/Article/List.ascx", ViewData["ArticleList"])

View.Product.List will call
foreach(Product product in View.Model)
    Html.RenderPartial("Single", product);

View.Article.List does something similar to View.Product.List

然而,这种方法失败了。这种方法对我来说很有意义,但也许对这些 MVC 平台有更多经验的人会发现更好的方法。

以上在 View.Product.List 中产生错误。调用Html.RenderPartial("Single",...)抱怨未找到“单一”视图。该错误表明:

找不到局部视图“单一”。搜索了以下位置:
~/Views/Home/Single.aspx
~/Views/Home/Single.ascx
~/Views/Shared/Single.aspx
~/Views/Shared/Single.ascx

因为我是从 Product 中的视图调用 RenderAction(),所以我希望运行时在 Views\Product 中查找“Single”视图。然而,查找似乎是相对于调用原始视图(/Controller/Home 调用 /Views/Product)的控制器而不是当前视图。

所以我可以通过更改 Views\Product 来解决这个问题,例如:

View.Product.List will call
foreach(Product product in View.Model)
    Html.RenderPartial("~/Views/Product/Single.ascx", product);

代替

View.Product.List will call
foreach(Product product in View.Model)
    Html.RenderPartial("Single", product);

此修复程序有效,但是.. 我不明白为什么我需要指定视图的完整路径。对我来说,相对于当前视图的路径而不是原始控制器的视图路径来解释相对名称是有意义的。我想不出任何有用的情况,其中解释相对于控制器视图而不是当前视图的名称是有用的(除了在它们相同的典型情况下)。

这个时候我应该打个问号吧?强调这一点实际上是一个问题。

4

3 回答 3

5

因为我是从 Product 的视图中调用 RenderAction()

...

我不明白为什么我需要指定视图的完整路径。对我来说,相对于当前视图的路径而不是原始控制器的视图路径来解释相对名称是有意义的

我认为您误解的部分是“执行地点”,因为没有更好的或官方的术语。路径与您的视图无关,甚至与您所说的“控制器视图”无关。它们与定义控制器上下文的请求 URL 相关。我可能说得不太好,但是如果您在 Reflector 中花一点时间查看 URL 和路由是如何解析的,我想这一切都会在您的脑海中形成。

于 2008-11-11T20:33:07.970 回答
4

[编辑:

我在想,你有两种情况:

  • 家庭控制器是唯一一个引用产品/文章列表用户控件的控制器
  • 用户控件由多个控制器共享

在第一种情况下,视图用户控件确实属于主控制器,将它们放在主控制器文件夹中是有意义的。在第二种情况下,将它们放在共享文件夹中是有意义的,因为它们将由控制器共享。

无论哪种情况,您都可以将它们放在子文件夹中。喜欢 Views/Home/Products 然后尝试 RendarPartial("Product/Single") 看看会发生什么?我不知道它是否会尝试将其解决为:Home/Product/Single,然后是 Shared/Product/Single。如果子文件夹有效,它似乎允许产品和文章的逻辑分离,同时表明它们仍然是主控制器的成员或由所有控制器共享。

]

查看史蒂夫·桑德森的这篇博文:

http://blog.codeville.net/2008/10/14/partial-requests-in-aspnet-mvc/

您所做的并没有错,但它似乎确实违反了 View/Controller 文件夹名称的约定。也就是说,想要定义与控制器无关的视图用户控件并嵌套它们似乎是有效的。所以我不知道!

无论如何,该链接仅描述了一种方法,而不是使用 RenderPartial 来呈现使用控件,它定义了 RenderPartialRequest 的方法,该方法呈现控制器操作的返回值(在您的情况下为用户控件)。因此,您可以添加带有返回用户控件的操作列表的产品和文章控制器,然后从主页/索引视图中调用这两个操作。这对我来说似乎更直观,但只是一种意见。

他还提到了来自 MVC Contrib 的子控制器,我很确定有人希望这样的东西成为 ASP.NET MVC 版本的一部分。

于 2008-11-11T18:14:23.587 回答
2

通过查看 MVCStoreFront 示例,这就是他们为调用 RenderPartial 构建所有内容的方式

Views
    Shared
        ProductSingle
        ProductList
        ArticleSingle
        ArticleList

然后通过以下方式渲染它们:

<% Html.RenderPartial("ProductSingle", ViewData["ProductList"]); %>
<% Html.RenderPartial("ProductList", product); %>
<% Html.RenderPartial("ArticleSingle", article); %>
<% Html.RenderPartial("ArticleList", ViewData["ArticleList"]); %>
于 2008-11-11T20:56:34.240 回答