【问题标题】:ASP.NET MVC Custom View RoutingASP.NET MVC 自定义视图路由
【发布时间】:2014-02-14 20:41:03
【问题描述】:

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

控制器\类别\视图

例如: 控制器\数据分析\数据检索

现在我想映射路由,这样当用户在 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,它会忽略类别并且无法返回视图。

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

--编辑

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

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

        routes.MapRoute(
            name: "ExampleRouting",
            url: "{category}/{controller}/{action}"
        );

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

默认情况下,当我尝试检索 dataretrieve 的索引时,它会查看 Views\DataRetrieve\Index 而不是 Views\DataAnalysis\DataRetrieve\Index。

如何改变这种行为?

编辑2------------

根据答案,我添加了一个自定义视图引擎,在 Application_Start 中注册它,更新了我的路由。仍然有同样的问题。

全球.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));
    }
}

【问题讨论】:

  • 那么 DataAnalysis 是你的 Controller,还是你项目的名字,DataRetrieve 是你的 Controller?
  • 我很困惑,或者你可能是。路由与视图无关。仅路由到控制器操作的路由。
  • 我建议使用区域来组织您的应用程序。请参阅msdn.microsoft.com/en-us/library/ee671793(v=vs.100).aspx
  • @Onots 几乎所有页面都将使用相同的共享布局文件,坦率地说,我们认为在区域下重新配置它们的共享布局设置(包括所有子渲染操作属性)会非常忙碌,除非我们是错误的,有一个简单的方法可以解决这个问题。
  • @l46kok 我希望您可以使用 Area _viewStart 来引用相同的(共享)根布局设置。不过,还不必亲自处理这个问题。这就是我评论而不是回答的原因:D

标签: c# .net asp.net-mvc-4 url razor


【解决方案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 }
        );

【讨论】:

  • 您的回答似乎是正确的方法,但由于某种原因,它仍然无法正常工作。请求 localhost/DataAnalysis/DataRetrieve 会导致 404,并且当我在它们上放置调试点时,不会调用自定义视图引擎中的任何覆盖方法。但是,当我尝试 localhost:12346/DataRetrieve/TestAction 没有前面的类别时,它可以工作。编辑:没关系,后半部分也不起作用。
  • 您是否在应用程序启动时注册了视图引擎并更新了路由配置?我在我的本地主机上试过这个,它对我有用,调试点也应该针对每个请求。
  • 是的。我将立即使用更新的内容编辑我的问题。
  • 哇.. 只需调用 ViewEngines.Engines.Clear() 即可解决问题。我猜它仍在使用默认视图引擎。非常感谢!
猜你喜欢
  • 2011-04-02
  • 2020-04-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-10
  • 1970-01-01
  • 2015-06-22
  • 1970-01-01
相关资源
最近更新 更多