ASP.NET MVC自定义视图路由 [英] ASP.NET MVC Custom View Routing
问题描述
我们的解决方案层次结构如下:
控制器\\目录\\查看
例如:
控制器\\ DataAnalysis \\ DataRetrieve
现在我想映射的路由,这样,当用户只需类型的URL视图的名字,它会自动将URL映射到相应的控制器
即:本地主机:1234 \\ DataAnalysis \\ DataRetrieve
应该映射到
查看\\ DataAnalysis \\ DataRetrieve \\ Index.cshtml
同样,任何URL请求,包括动作要获取相应的视图
即:本地主机:1234 \\ DataAnalysis \\ DataRetrieve \\ TestAction
应该映射到
查看\\ DataAnalysis \\ DataRetrieve \\ TestAction.cshtml
目前,我们使用默认的路由
公共静态无效的RegisterRoutes(RouteCollection路线)
{
routes.IgnoreRoute({}资源个.axd / {*} PATHINFO); routes.MapRoute(
名称:默认,
网址:{控制器} / {行动} / {ID}
默认:新{控制器=登录,行动=索引,ID = UrlParameter.Optional}
);
}
这意味着,如果我输入上面显示的URL,它忽略了类别,未能返回的看法。
有没有一种方法可以自定义路由以获得上述的行为?
- 编辑
要基于的评论澄清我的问题,这是我的解决方案资源管理器的截图
现在如果我叫本地主机:12346 / DataAnalysis / DataRetrieve,这应该带我到索引中。路由这不是我可以做一些这样的问题:
routes.MapRoute(
名称:ExampleRouting
网址:{类别} / {控制器} / {行动}
);
但这里的问题。我也想安排我的文件结构是这样的:
在默认情况下,当我尝试检索dataretrieve的指数,它看起来在查看\\ DataRetrieve \\指数不查看\\ DataAnalysis \\ DataRetrieve \\目录。
我怎样才能改变这种行为?
EDIT2 ------------------------
根据答案,我添加了一个自定义视图引擎中的Application_Start其注册,更新了我的路由。仍然有一个相同的问题。
Global.asax中
公共类MvcApplication:System.Web.HttpApplication
{
保护无效的Application_Start()
{
AreaRegistration.RegisterAllAreas(); WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
ViewEngines.Engines.Add(新SPCViewEngine()); BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
}
}
RouteConfig.cs
公共静态无效的RegisterRoutes(RouteCollection路线)
{
routes.IgnoreRoute({}资源个.axd / {*} PATHINFO);
routes.MapRoute(
名称:默认,
网址:{控制器} / {类别} / {行动} / {ID}
默认:新{控制器=登录,行动=索引,类别=登录,ID = UrlParameter.Optional}
);
}
SPCViewEngine(自定义视图引擎)
公共类SPCViewEngine:RazorViewEngine
{
公共SPCViewEngine()
:基地()
{
ViewLocationFormats =新[] {
〜/查看/ {1} /%1 / {0} .cshtml
〜/查看/ {1} /%1 / {0} .vbhtml
〜/查看/共享/ {0} .cshtml
〜/查看/共享/ {0} .vbhtml
}; PartialViewLocationFormats =新[] {
〜/查看/%1 / {1} / {0} .cshtml
〜/查看/%1 / {1} / {0} .vbhtml
〜/查看/共享/ {0} .cshtml
〜/查看/共享/ {0} .vbhtml
};
} 保护覆盖IVIEW CreatePartialView(ControllerContext controllerContext,串partialPath)
{
。VAR类别名称= controllerContext.RouteData.Values [类别]的ToString();
返回base.CreatePartialView(controllerContext,partialPath.Replace(%1,类别名称));
} 保护覆盖IVIEW CreateView的(ControllerContext controllerContext,串viewPath,串masterPath)
{
。VAR类别名称= controllerContext.RouteData.Values [类别]的ToString();
返回base.CreateView(controllerContext,viewPath.Replace(%1,类别名称),masterPath);
} 保护覆盖布尔FILEEXISTS(ControllerContext controllerContext,字符串virtualPath)
{
。VAR类别名称= controllerContext.RouteData.Values [类别]的ToString();
返回base.FileExists(controllerContext,virtualPath.Replace(%1,类别名称));
}
}
如果我正确理解你的问题,你可以创建在运行时解析视图位置你自己的视图引擎,并插入到你的应用程序。
创建自己的自定义视图引擎。
公共类MyViewEngine:RazorViewEngine
{
公共MyViewEngine()
:基地()
{
ViewLocationFormats =新[] {
〜/查看/ {1} /%1 / {0} .cshtml
〜/查看/ {1} /%1 / {0} .vbhtml
〜/查看/共享/ {0} .cshtml
〜/查看/共享/ {0} .vbhtml
}; PartialViewLocationFormats =新[] {
〜/查看/%1 / {1} / {0} .cshtml
〜/查看/%1 / {1} / {0} .vbhtml
〜/查看/共享/ {0} .cshtml
〜/查看/共享/ {0} .vbhtml
};
} 保护覆盖IVIEW CreatePartialView(ControllerContext controllerContext,串partialPath)
{
。VAR catagoryName = controllerContext.RouteData.Values [类别]的ToString();
返回base.CreatePartialView(controllerContext,partialPath.Replace(%1,catagoryName));
} 保护覆盖IVIEW CreateView的(ControllerContext controllerContext,串viewPath,串masterPath)
{
。VAR catagoryName = controllerContext.RouteData.Values [类别]的ToString();
返回base.CreateView(controllerContext,viewPath.Replace(%1,catagoryName),masterPath);
} 保护覆盖布尔FILEEXISTS(ControllerContext controllerContext,字符串virtualPath)
{
。VAR catagoryName = controllerContext.RouteData.Values [类别]的ToString();
返回base.FileExists(controllerContext,virtualPath.Replace(%1,catagoryName));
}}
在这里进行注册。
保护无效的Application_Start()
{
AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters);
的RegisterRoutes(RouteTable.Routes);
//注册您的视图引擎这里。
ViewEngines.Engines.Add(新MyViewEngine());
}
更新的路由配置,默认的应该是
routes.MapRoute(
名称:默认,
网址:{控制器} / {类别} / {行动} / {ID}
默认:新{控制器=家,行动=索引,类别=DefaultCategoryName,ID = UrlParameter.Optional}
);
Our solution hierarchy is as follows:
Controller\Category\View
Ex: Controllers\DataAnalysis\DataRetrieve
Now I'd like to map the routing so that when the user just types the name of the view in the url, it automatically maps the url to the corresponding controller
I.E: localhost:1234\DataAnalysis\DataRetrieve
Should map to
View\DataAnalysis\DataRetrieve\Index.cshtml
Similarly, any url requests including the action should retrieve the corresponding view
I.E: localhost:1234\DataAnalysis\DataRetrieve\TestAction
Should map to
View\DataAnalysis\DataRetrieve\TestAction.cshtml
Currently, we're using the default routing
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 }
);
}
Which means if I type the URL shown above, it ignores the category and fails to return the view.
Is there a way to customize routing to get the behavior above?
--Edit
To clarify my question based on the comments, here's a screenshot of my solution explorer
Now if I call localhost:12346/DataAnalysis/DataRetrieve, this should take me to the index. Routing this isn't a problem as I can do something like this:
routes.MapRoute(
name: "ExampleRouting",
url: "{category}/{controller}/{action}"
);
But here's the issue. I'd also like to organize my file structure like this:
By default, when I try to retrieve the index of dataretrieve, it looks under Views\DataRetrieve\Index not Views\DataAnalysis\DataRetrieve\Index.
How can I change this behavior?
Edit2------------------------
Based on the answer, I've added a custom view engine, registered it in Application_Start, updated my routing. Still having an identical issue.
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 (Custom View Engine)
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));
}
}
If I understood your question correctly, you can create your own view engine which resolves view location at runtime and plug into your application.
Create your own custom view engine.
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));
}
}
And register it here
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
//Register your View Engine Here.
ViewEngines.Engines.Add(new MyViewEngine());
}
Update route config, default should be
routes.MapRoute(
name: "Default",
url: "{controller}/{category}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", category = "DefaultCategoryName", id = UrlParameter.Optional }
);
这篇关于ASP.NET MVC自定义视图路由的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!