我一直在玩ASP.NET MVC并且有一个问题。或者也许我担心这样做是错误的。只是在一个跛足的地方工作,伸展我的翅膀。对不起,这个问题一点也不简洁。
好的,这是场景。当用户访问home / index时,该页面应显示产品列表和文章列表。文件布局是这样的(DAL是我的数据访问层):
Controllers Home Index Views Home Index inherits from ViewPage Product List inherits from ViewUserControl<IEnumerable<DAL.Product>> Single inherits from ViewUserControl<DAL.Product> Article List inherits from ViewUserControl<IEnumerable<DAL.Article>> Single inherits from 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",...)
的调用抱怨未找到“单一”视图。错误表明:
The partial view 'Single' could not be found. The following locations were searched: ~/Views/Home/Single.aspx ~/Views/Home/Single.ascx ~/Views/Shared/Single.aspx ~/Views/Shared/Single.ascx
因为我从Product中的视图调用RenderAction(),所以我希望运行时在Views \ Product中查找“Single”视图。然而,似乎查找是相对于调用原始视图的控制器(/ Controller / Home invoked / 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);
这个修复工作但但..我不明白为什么我需要指定视图的完整路径。我相对于当前视图的路径而不是原始控制器的视图路径来解释相对名称是有意义的。我想不出任何有用的情况,即相对于控制器视图而不是当前视图解释名称是有用的(除了在它们相同的典型情况下)。
这段时间我应该有问号吗?强调这一点实际上是一个问题。
答案 0 :(得分:5)
因为我正在调用RenderAction() 从产品
中的视图...
我不明白我为什么需要 指定视图的完整路径。 这对我有意义 要解释的相对名称 相对于当前视图的路径 而不是原来的控制器 查看路径
我认为你误解的部分是缺乏更好或官方术语的“执行地点”。路径与您的视图无关,甚至不是您所说的“控制器视图”。它们与您的请求URL相关,后者定义了控制器上下文。我可能不是很好说,但是如果你花了一点时间在Reflector中查看URL和路由是如何解决的,我认为这一切都会落到你的脑海中。
答案 1 :(得分:4)
[编辑:
我在想,你有2个案例:
在第一种情况下,视图用户控件确实属于家庭控制器,将它们放在家庭控制器文件夹中是有意义的。在第二种情况下,将它们放在共享文件夹中是有意义的,因为它们将由控制器共享。
在任何一种情况下,也许您可以将它们放在子文件夹中。喜欢Views / Home / Products然后尝试RendarPartial(“产品/单一”),看看会发生什么?我不知道它是否会尝试将其解析为:Home / Product / Single然后Shared / Product / Single或not。如果子文件夹有效,它似乎允许产品和文章的逻辑分离,同时显示它们仍然是家庭控制器的成员或所有控制器共享。
查看Steve Sanderson的博客文章:
http://blog.codeville.net/2008/10/14/partial-requests-in-aspnet-mvc/
你在做什么并没有错,但它确实违反了View / Controller文件夹名称的惯例。也就是说,想要定义与控制器无关的视图用户控件并嵌套它们似乎是有效的。所以我不知道!
无论如何,该链接仅描述了一种方法,而不是使用RenderPartial来呈现使用控件,它定义了一个RenderPartialRequest方法,该方法呈现控制器操作的返回值(在您的情况下是用户控件)。因此,您可以使用返回用户控件的动作列表添加Product and Articles控制器,然后从Home / Index视图中调用这两个动作。这对我来说似乎更直观,但只是一种意见。
他还提到了MVC Contrib的子控制器,我很确定这样的东西是ASP.NET MVC版本的一部分。
答案 2 :(得分: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"]); %>