ASP.NET MVC自定义视图路由

l46*_*kok 3 .net c# url razor asp.net-mvc-4

我们的解决方案层次结构如下:

控制器\目录\查看

例如:Controllers\DataAnalysis\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 }
        );
    }
Run Code Online (Sandbox Code Playgroud)

这意味着如果我键入上面显示的URL,它将忽略该类别并且无法返回视图.

有没有办法自定义路由以获得上述行为?

- 编辑

为了根据评论澄清我的问题,这里是我的解决方案资源管理器的屏幕截图

在此输入图像描述

现在,如果我调用localhost:12346/DataAnalysis/DataRetrieve,这应该将我带到索引.路由这不是问题,因为我可以这样做:

        routes.MapRoute(
            name: "ExampleRouting",
            url: "{category}/{controller}/{action}"
        );
Run Code Online (Sandbox Code Playgroud)

但这是问题所在.我还想像我这样组织我的文件结构:

在此输入图像描述

默认情况下,当我尝试检索dataretrieve的索引时,它会在Views\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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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 }
        );
    }
Run Code Online (Sandbox Code Playgroud)

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));
    }
}
Run Code Online (Sandbox Code Playgroud)

ssi*_*777 12

如果我正确理解了您的问题,您可以创建自己的视图引擎,该引擎在运行时解析视图位置并插入您的应用程序.

创建自己的自定义视图引擎.

    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));
    }

}
Run Code Online (Sandbox Code Playgroud)

并在此处注册

protected void Application_Start()
{   
   AreaRegistration.RegisterAllAreas();

   RegisterGlobalFilters(GlobalFilters.Filters);
   RegisterRoutes(RouteTable.Routes);


   //Register your View Engine Here.
   ViewEngines.Engines.Add(new MyViewEngine());
}
Run Code Online (Sandbox Code Playgroud)

更新路由配置,默认应该是

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{category}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", category = "DefaultCategoryName", id = UrlParameter.Optional }
        );
Run Code Online (Sandbox Code Playgroud)