Маршрутизация с настраиваемым представлением ASP.NET MVC
Наша иерархия решений выглядит следующим образом:
Контроллер \ Категория \View
Пример: Контроллеры \ Анализ данных \DataRetrieve
Теперь я хотел бы отобразить маршрутизацию так, чтобы, когда пользователь просто вводил имя представления в URL, он автоматически отображал URL на соответствующий контроллер.
IE: localhost:1234\DataAnalysis\DataRetrieve
Должен отображаться на
Просмотр \DataAnalysis\DataRetrieve\Index.cshtml
Аналогично, любые URL-запросы, включая действие, должны получать соответствующее представление.
IE: localhost:1234\DataAnalysis\DataRetrieve\TestAction
Должен отображаться на
Просмотр \DataAnalysis\DataRetrieve\TestAction.cshtml
В настоящее время мы используем маршрутизацию по умолчанию
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
}
Это означает, что если я введу URL-адрес, показанный выше, он игнорирует категорию и не возвращает представление.
Есть ли способ настроить маршрутизацию, чтобы получить поведение выше?
--Редактировать
Чтобы уточнить мой вопрос на основе комментариев, вот скриншот моего обозревателя решений
Теперь, если я вызову localhost:12346/DataAnalysis/DataRetrieve, это приведет меня к индексу. Маршрутизация это не проблема, так как я могу сделать что-то вроде этого:
routes.MapRoute(
name: "ExampleRouting",
url: "{category}/{controller}/{action}"
);
Но вот в чем проблема. Я также хотел бы организовать мою файловую структуру следующим образом:
По умолчанию, когда я пытаюсь получить индекс передачи данных, он выглядит в представлениях \DataRetrieve \ Index, а не Views \ DataAnalysis \DataRetrieve \ Index.
Как я могу изменить это поведение?
Edit2 ------------------------
Основываясь на ответе, я добавил пользовательский механизм просмотра, зарегистрировал его в Application_Start, обновил мою маршрутизацию. По-прежнему возникают идентичные проблемы.
Global.asax
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
ViewEngines.Engines.Add(new SPCViewEngine());
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
}
}
RouteConfig.cs
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{category}/{action}/{id}",
defaults: new { controller = "Login", action = "Index", category = "Login", id = UrlParameter.Optional }
);
}
SPCViewEngine (механизм пользовательского просмотра)
public class SPCViewEngine : RazorViewEngine
{
public SPCViewEngine()
: base()
{
ViewLocationFormats = new[] {
"~/Views/{1}/%1/{0}.cshtml",
"~/Views/{1}/%1/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml"
};
PartialViewLocationFormats = new[] {
"~/Views/%1/{1}/{0}.cshtml",
"~/Views/%1/{1}/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml"
};
}
protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
{
var categoryName = controllerContext.RouteData.Values["category"].ToString();
return base.CreatePartialView(controllerContext, partialPath.Replace("%1", categoryName));
}
protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
var categoryName = controllerContext.RouteData.Values["category"].ToString();
return base.CreateView(controllerContext, viewPath.Replace("%1", categoryName), masterPath);
}
protected override bool FileExists(ControllerContext controllerContext, string virtualPath)
{
var categoryName = controllerContext.RouteData.Values["category"].ToString();
return base.FileExists(controllerContext, virtualPath.Replace("%1", categoryName));
}
}
1 ответ
Если я правильно понял ваш вопрос, вы можете создать свой собственный движок представления, который разрешает местоположение представления во время выполнения и подключается к вашему приложению.
Создайте свой собственный механизм просмотра.
public class MyViewEngine : RazorViewEngine
{
public MyViewEngine()
: base()
{
ViewLocationFormats = new[] {
"~/Views/{1}/%1/{0}.cshtml",
"~/Views/{1}/%1/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml"
};
PartialViewLocationFormats = new[] {
"~/Views/%1/{1}/{0}.cshtml",
"~/Views/%1/{1}/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml"
};
}
protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
{
var catagoryName = controllerContext.RouteData.Values["category"].ToString();
return base.CreatePartialView(controllerContext, partialPath.Replace("%1", catagoryName));
}
protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
{
var catagoryName = controllerContext.RouteData.Values["category"].ToString();
return base.CreateView(controllerContext, viewPath.Replace("%1", catagoryName),masterPath);
}
protected override bool FileExists(ControllerContext controllerContext, string virtualPath)
{
var catagoryName = controllerContext.RouteData.Values["category"].ToString();
return base.FileExists(controllerContext, virtualPath.Replace("%1", catagoryName));
}
}
И зарегистрируйся здесь
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
//Register your View Engine Here.
ViewEngines.Engines.Add(new MyViewEngine());
}
Обновление конфигурации маршрута, по умолчанию должно быть
routes.MapRoute(
name: "Default",
url: "{controller}/{category}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", category = "DefaultCategoryName", id = UrlParameter.Optional }
);