asp.net-mvc 带有相对路径的 ASP.Net MVC 和 RenderPartial

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/277284/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-07 22:50:56  来源:igfitidea点击:

ASP.Net MVC and RenderPartial w/ relative paths

asp.net-mvcrenderpartial

提问by Frank Schwieterman

I've been playing around with ASP.NET MVC and had a question. Or maybe its a concern that I am doing this wrong. Just working on a lame site to stretch my wings a bit. I am sorry this question is not at all concise.

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

Ok, here's the scenario. When the user visits home/index, the page should show a list of products and a list of articles. The file layout is such (DAL is my data access layer):

好的,这是场景。当用户访问 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

This approach fails however. The approach makes sense to me, but maybe someone with more experience with these MVC platforms will recognize a better way.

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

The above produces an error inside View.Product.List. The call to Html.RenderPartial("Single",...)complains that "Single" view was not found. The error indicates:

以上在 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

Because I was calling RenderAction() from a view in Product, I expected the runtime to look for the "Single" view within Views\Product. It seems however the lookup is relative the controller which invoked the original view (/Controller/Home invoked /Views/Product) rather than the current view.

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

So I am able to fix this by changing Views\Product, such that:

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

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

instead of

代替

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

This fix works but.. I do not understand why I needed to specify the full path of the view. It would make sense to me for the relative name to be interpreted relative to the current view's path rather than the original controller's view path. I cannot think of any useful case where interpreting the name relative to the controller's view instead of the current view is useful (except in the typical case where they are the same).

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

Around this time I should have a question mark? To emphasis this actually is a question.

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

回答by sliderhouserules

Because I was calling RenderAction() from a view in Product

...

I do not understand why I needed to specify the full path of the view. It would make sense to me for the relative name to be interpreted relative to the current view's path rather than the original controller's view path

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

...

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

The part I think you're misunderstanding is the "execution location" for lack of a better or official term. Paths are not relative to your view, not even your "controller's view" as you put it. They are relative to your request URL, which defines a controller context. I may not be saying it very well, but if you spent a little time in Reflector looking at how URLs and routes are resolved, I think this would all fall into place in your head.

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

回答by anonymous

[edit:

[编辑:

I was thinking, you have 2 cases:

我在想,你有两种情况:

  • the Home controller is the only one that ever references Product / Articles List user control
  • the user controls are shared by several controllers
  • Home 控制器是唯一一个引用 Product / Articles List 用户控件的控制器
  • 用户控件由多个控制器共享

In the first case, the view user controls really belong to the home controller and it makes sense to put them in the home controller folder. In the second case, it makes sense to place them in the shared folder since they will be shared by controllers.

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

In either case, maybe you can place them in a sub folder. Like Views/Home/Products and then try RendarPartial("Product/Single") and see what happens? I don't know if it would try to resolve it to: Home/Product/Single and then Shared/Product/Single or not. If sub folders work, it seems to allow the logical seperation of Product and Article, while showing that they are still members of either the Home controller or Shared by all controllers.

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

]

]

Check out this blog entry by Steve Sanderson:

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

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

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

What you are doing isn't wrong, but it does seem to sort of go against the convention of View/Controller folder names. That said, it makes sense to want to define controller-agnostic view user controls and nesting them seems valid. So I dunno!

你在做什么没有错,但它似乎有点违反视图/控制器文件夹名称的约定。也就是说,想要定义与控制器无关的视图用户控件并且嵌套它们似乎是有效的是有意义的。所以我不知道!

Anyways, the link just describes a method of instead of using RenderPartial to render a use control, it defines a method of RenderPartialRequest that renders the return value (in your case a user control) of a controller action. So you could add a Product and Articles controller with an Action List that returns your user control, and then call those two actions from the Home/Index view. This seems more intuitive to me, but just an opinion.

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

He also mentions subcontrollers from MVC Contrib, and I'm pretty sure there is desire for something like this to be a part of ASP.NET MVC release.

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

回答by Todd Smith

From looking at the MVCStoreFront sample this is how they have everything structured for calling RenderPartial

从查看 MVCStoreFront 示例来看,这是他们如何构建用于调用 RenderPartial 的所有内容

Views
    Shared
        ProductSingle
        ProductList
        ArticleSingle
        ArticleList

Then render them via:

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

<% Html.RenderPartial("ProductSingle", ViewData["ProductList"]); %>
<% Html.RenderPartial("ProductList", product); %>
<% Html.RenderPartial("ArticleSingle", article); %>
<% Html.RenderPartial("ArticleList", ViewData["ArticleList"]); %>