Подтвердить что ты не робот

ASP.Net MVC и RenderPartial с относительными путями

Я играю с ASP.NET MVC и задал вопрос. Или, может быть, это беспокойство, что я делаю это неправильно. Просто работаю над хромым сайтом, чтобы немного растянуть мои крылья. Мне жаль, что этот вопрос не совсем лаконичен.

Хорошо, вот сценарий. Когда пользователь посещает дом/индекс, страница должна показывать список продуктов и список статей. Макет файла такой (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",...) жалуется, что вид "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

Поскольку я вызывал RenderAction() из представления в Product, я ожидал, что среда выполнения будет искать представление "Single" в Views\Product. Кажется, что поиск относится к контроллеру, который вызывал исходный вид (/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);

Это исправление работает, но.. Я не понимаю, почему мне нужно было указать полный путь к представлению. Для меня было бы разумно, чтобы относительное имя было интерпретировано относительно текущего пути просмотра, а не исходного пути представления контроллера. Я не могу придумать какой-либо полезный случай, когда полезно использовать интерпретацию имени относительно представления контроллера вместо текущего представления (за исключением типичного случая, когда они одинаковы).

Примерно в это же время у меня должен быть знак вопроса? Для акцента это на самом деле вопрос.

4b9b3361

Ответ 1

Потому что я звонил RenderAction() с точки зрения продукта

...

Я не понимаю, зачем мне нужно для указания полного пути представления. Для меня было бы целесообразно относительное имя для интерпретации относительно текущего пути просмотра а не исходный контроллер вид пути

Часть, я думаю, вы недопонимаете, это "место выполнения" из-за отсутствия лучшего или официального термина. Пути не относятся к вашему виду, даже ваш "просмотр контроллера", как вы выразились. Они относятся к вашему URL-адресу запроса, который определяет контекст контроллера. Я не могу сказать это очень хорошо, но если вы потратили немного времени на Reflector, глядя на то, как разрешены URL-адреса и маршруты, я думаю, что все это встанет на ваше место.

Ответ 2

[редактировать:

Я думал, у вас есть 2 случая:

  • Домашний контроллер - единственный, который когда-либо ссылается на пользовательский контроль продукта/статей.
  • пользовательские элементы управления совместно используются несколькими контроллерами.

В первом случае пользовательские элементы управления представлением действительно принадлежат домашнему контроллеру, и имеет смысл помещать их в папку домашнего контроллера. Во втором случае имеет смысл разместить их в общей папке, так как они будут совместно использоваться контроллерами.

В любом случае, возможно, вы можете разместить их в подпапке. Как Views/Home/Products, а затем попробуйте RendarPartial ( "Продукт/Одиночный" ) и посмотрите, что произойдет? Я не знаю, попытается ли это решить: Главная/Продукт/Одиночный, а затем Общий/Продукт/Одиночный или нет. Если вспомогательные папки работают, это, по-видимому, позволяет логическое разделение Продукта и Статьи, показывая, что они все еще являются членами либо Домашнего контроллера, либо Shared всеми контроллерами.

]

Посмотрите эту запись в блоге Стив Сандерсон:

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.

Ответ 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"]); %>