Подпапки в контроллерах и представлениях - PullRequest
2 голосов
/ 10 апреля 2009

Я хотел иметь более одного контроллера и просматривать один и тот же объект / модель в asp.net mvc, но это оказалось немного сложнее, чем я ожидал.

В основном я хочу сделать что-то вроде этого:

site.com/product
    ->  will show product details to visitors.

site.com/admin/product
    ->  will show some extra information together with product details.
        and some commands like delete, edit etc.

Цель состоит в том, чтобы разделить URL-адреса для посетителей и администраторов.

Мой первый подход состоял в том, чтобы я создал подпапку в контроллере и папках вида, чтобы все выглядело так:

> Controllers
    > Admin
        ProductController.cs
    ProductController.cs
> Views
    > Admin
        > Product
            Index.aspx
    > Product
        Index.aspx

Я могу без проблем отобразить URL на правильные контроллеры (при условии, что я указываю их пространства имен, так как имена классов совпадают). Однако, когда я возвращаю представление из контроллера в папке администратора, оно отображает не представление индекса в папке Views / Admin / Product, а представление в Views / Product.

Я знаю, что могу сказать return View("Full path here"), чтобы вернуть желаемое представление. Но это, очевидно, не очень хорошее решение, и я не хочу этого делать.

У меня вопрос: как лучше всего справиться с этой ситуацией при условии, что URL должен быть таким?

  • Создать собственный класс контроллера, который переопределяет метод представления (или любые другие, которые должны быть переопределены для этой цели) и обеспечивает возвращение правильного представления?

    • Этот уродливый хак, но сработает.
  • Создать собственный механизм просмотра, который также учитывает папки?

    • Я точно не знаю, как я могу это сделать, но, насколько я понимаю, это также должно решить проблему
  • Использование Прототип области из Фил Хаак ?

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

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

Есть предложения?

Ответы [ 2 ]

2 голосов
/ 10 апреля 2009

Попробуйте Phil Haack's / Areas / для вашего проекта MVC: http://haacked.com/archive/2008/11/04/areas-in-aspnetmvc.aspx

У вас будет обычный Root для обычного контента и специальный раздел / Areas / Admin / для всех ваших админских материалов (и URL будет /admin/).

alt text
(источник: haacked.com )

1 голос
/ 22 сентября 2013

ASP.Net MVC по умолчанию использует плоскую структуру папок Views. Области могут в определенной степени помочь, хотя они дают вам еще один уровень!

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

Хорошей новостью является то, что вы можете написать собственный ViewEngine, чтобы сделать это с удивительно небольшими усилиями - подробности смотрите в моем проекте ControllerPathViewEngine на GitHub .

Я включил фрагмент класса ControllerPathRazorViewEngine, чтобы описать, как он работает. Перехватывая методы FindView / FindPartialView и заменяя имя контроллера на путь к папке (на основе пространства имен и имени контроллера), мы можем получить его для загрузки представлений из вложенных папок в основной папке Views.

    public class ControllerPathRazorViewEngine : RazorViewEngine
    {
        //... constructors etc.

        public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
        {
            return FindUsingControllerPath(controllerContext, () => base.FindView(controllerContext, viewName, masterName, useCache));
        }

        public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
        {
            return FindUsingControllerPath(controllerContext, () => base.FindPartialView(controllerContext, partialViewName, useCache));
        }

        private ViewEngineResult FindUsingControllerPath(ControllerContext controllerContext, Func<ViewEngineResult> func)
        {
            string controllerName = controllerContext.RouteData.GetRequiredString("controller");
            string controllerPath = controllerPathResolver.GetPath(controllerContext.Controller.GetType());
            controllerContext.RouteData.Values["controller"] = controllerPath;
            var result = func();
            controllerContext.RouteData.Values["controller"] = controllerName;
            return result;
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...