ASP.Net MVC и RenderPartial с относительными путями - PullRequest
11 голосов
/ 10 ноября 2008

Я играл с 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",...) жалуется на то, что «Единый» просмотр не найден. Ошибка указывает:

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, я ожидал, что среда выполнения будет искать «одиночное» представление в Views \ Product. Однако, похоже, что поиск относится к контроллеру, который вызвал исходное представление (/ Controller / Home invoked / Views / Product), а не к текущему представлению.

Так что я могу это исправить, изменив Views \ Product, например:

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

вместо

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

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

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

Ответы [ 3 ]

5 голосов
/ 11 ноября 2008

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

...

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

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

4 голосов
/ 11 ноября 2008

[править:

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

  • Контроллер Home является единственным, который когда-либо ссылался на пользовательский элемент управления Product / Articles List
  • пользовательские элементы управления используются несколькими контроллерами

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

В любом случае, возможно, вы можете поместить их в подпапку. Нравится Views / Home / Products, а затем попробуйте RendarPartial («Product / Single») и посмотрите, что произойдет? Я не знаю, попытается ли это решить: Домой / Продукт / Одиночный, а затем Общий / Продукт / Одиночный или нет. Если подпапки работают, это, кажется, позволяет логически разделить Product и Article, показывая, что они все еще являются членами контроллера Home или 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.

2 голосов
/ 11 ноября 2008

Из примера 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"]); %>
...