带有相对路径的 ASP.Net MVC 和 RenderPartial
Posted
技术标签:
【中文标题】带有相对路径的 ASP.Net MVC 和 RenderPartial【英文标题】:ASP.Net MVC and RenderPartial w/ relative paths 【发布时间】:2008-11-10 07:28:44 【问题描述】:我一直在使用 ASP.NET MVC 并有一个问题。或者也许它担心我做错了。只是在一个蹩脚的网站上工作以伸展我的翅膀。很抱歉这个问题一点都不简洁。
好的,这就是场景。当用户访问主页/索引时,页面应显示产品列表和文章列表。文件布局是这样的(DAL是我的数据访问层):
控制器 家 指数 意见 家 索引继承自 ViewPage 产品 列表继承自 ViewUserControlControllers.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",...)
的调用抱怨找不到“单一”视图。错误提示:
因为我是从 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);
此修复有效,但是.. 我不明白为什么我需要指定视图的完整路径。对我来说,相对于当前视图的路径而不是原始控制器的视图路径来解释相对名称是有意义的。我想不出任何有用的情况来解释相对于控制器视图而不是当前视图的名称是有用的(除了在它们相同的典型情况下)。
大约在这个时候我应该有一个问号?强调这一点实际上是一个问题。
【问题讨论】:
刚刚偶然发现这个寻找相关的东西(我意识到它已经超过 6 个月了)。但是你提到使用 RenderAction(),但是你所有的例子都使用 RenderPartial(),这是一个错字吗?我会假设 RenderAction(而不是 RenderPartial)应该在这种情况下工作? 【参考方案1】:因为我在调用 RenderAction() 从产品视图
...
我不明白我为什么需要 指定视图的完整路径。 这对我来说是有意义的 要解释的相对名称 相对于当前视图的路径 而不是原来的控制器 查看路径
我认为您误解的部分是“执行地点”,因为没有更好的或官方的术语。路径与您的视图无关,甚至与您所说的“控制器视图”无关。它们与定义控制器上下文的请求 URL 相关。我可能说得不太好,但是如果您花一点时间在 Reflector 中查看 URL 和路由是如何解析的,我想这一切都会在您的脑海中形成。
【讨论】:
这种行为是有道理的,但我不明白为什么会是这样的设计。我认为视图中的代码不需要知道调用它的路径。【参考方案2】:[编辑:
我在想,你有两种情况:
Home 控制器是唯一一个引用产品/文章列表用户控件的控制器 用户控件由多个控制器共享在第一种情况下,视图用户控件确实属于主控制器,将它们放在主控制器文件夹中是有意义的。在第二种情况下,将它们放在共享文件夹中是有意义的,因为它们将被控制器共享。
在任何一种情况下,您都可以将它们放在子文件夹中。喜欢 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 版本的一部分。
【讨论】:
RenderPartial("Product/Single") 将适用于产品视图文件夹中的子文件夹。我刚刚将这种技术用于一些部分视图,我希望将其保存在与控制器关联的其余 ASPX/ASCX 的子文件夹中。【参考方案3】:通过查看 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"]); %>
【讨论】:
以上是关于带有相对路径的 ASP.Net MVC 和 RenderPartial的主要内容,如果未能解决你的问题,请参考以下文章
更改 ASP.NET MVC 或 IIS 中的 URL 根路径