【问题标题】:ASP.NET MVC Routing for a Single Controller Site单个控制器站点的 ASP.NET MVC 路由
【发布时间】:2009-10-21 14:30:58
【问题描述】:

我正在尝试创建一个简单的网站。基本上它有一个控制器Home控制器。

这个控制器有一个动作Indexstring 作为参数(它是一个目录)并使用那个“目录”来完成它的工作。

我不知道如何创建一个通用的 catch all 路由,它将每个 URL 发送到这个 Action。

任何 URL 组合都可以存在,并且域名以外的任何内容都应该是字符串。

http://<domain>/2008
http://<domain>/2008/09
http://<domain>/2008/09/Fred

有人知道怎么做吗?如果所有值都作为列表传递也可以。

有更好的方法吗?

【问题讨论】:

    标签: asp.net-mvc routing


    【解决方案1】:

    试试这个:

    routes.MapRoute(
            "Default", "{*path}",
            new { controller = "Home", action = "Index" } 
        );
    

    还有控制器:

    public class HomeController : Controller {
        public ActionResult Index(string path) {
            return View();
        }
    }
    

    【讨论】:

    • 如果您尝试使用 '/' 传递目录,这将不起作用
    • @Yuriy Faktorovich,你能举个例子吗?你的意思是像site.com/foo/bar?如果是这样,它适用于这样的路线。
    • site.com/C:/test,给我弄坏了,你还需要一个逗号在第 2 行(路径后)
    • site.com/C:/testHTTP 400,而不是 404(我认为是因为 : 字符)。我想知道我们是否应该尝试解决这个问题。
    • 我认为你是对的,这是唯一的问题。所以他的解决方案是使用你的没有:,我会给你一个赞成票。
    【解决方案2】:

    我的第一个想法是这是一个“坏主意”。如果您可以获取他们可以向您扔的任何东西,那么您将不得不拥有一个黑名单(或白名单)。有这么多的开口。更好的方法是明确说明这些路由以及您如何允许参数,然后执行处理这些已接受路由的操作。然后,您将拥有一个通用捕获所有路由,该路由将重定向到错误页面。

    感觉就像你在尝试混合苹果和橙子。 ASP.NET MVC 故意取消了“页面”的想法。除非您正在执行某种文件 I/O,否则实际上没有理由为各种用户提供目录,如果是这种情况,那么可以将其抽象为在 ASP.NET MVC 范例中工作比您想象的要容易得多。

    在 ASP.NET MVC 中,如果你想根据传递的字符串(很像你传递的字符串)改变你正在寻找的信息,这里有一个“安全”的方法:

    方法 #1 - 三个路线、三个动作、不同的名称

    routes.MapRoute(
      "YearOnly",
      "{year}",
      new { controller = "Index", action = "ShowByYear" },
      new { year = @"\d{4}" }
    );
    
    routes.MapRoute(
      "YearAndMonth",
      "{year}/{month}",
      new { controller = "Index", action = "ShowByYearAndMonth" },
      new { year = @"\d{4}", month = @"\d{2}" }
    );
    
    routes.MapRoute(
      "YearMonthAndName",
      "{year}/{month}/{name}",
      new { controller = "Index", action = "ShowByYearMonthAndName" },
      new { year = @"\d{4}", month = @"\d{2}" }
    );
    

    然后您将使用控制器操作中传递的路由值来确定它们如何查看数据:

    ShowByYear(string year)
    {
        //Return appropriate View here
    }
    
    ShowByYearAndMonth(string year, string month)
    { 
        //Return appropriate View here
    }
    
    ShowByYearMonthAndName(string year, string month, string name)
    { 
        //Return appropriate View here
    }
    

    方法 #2 - 建议方法

    routes.MapRoute(
      "YearOnly",
      "{year}",
      new { controller = "Index", action = "Show" },
      new { year = @"\d{4}" }
    );
    
    routes.MapRoute(
      "YearAndMonth",
      "{year}/{month}",
      new { controller = "Index", action = "Show" },
      new { year = @"\d{4}", month = @"\d{2}" }
    );
    
    routes.MapRoute(
      "YearMonthAndName",
      "{year}/{month}/{name}",
      new { controller = "Index", action = "Show" },
      new { year = @"\d{4}", month = @"\d{2}", name = "" }
    );
    
    Show(string year)
    {
        //
    }
    
    Show(string year, string month)
    {
        //Return appropriate View here
    }
    
    Show(string year, string month, string name)
    {
        //Return appropriate View here
    }
    

    这种方法的美妙之处在于MapRoute 处理URL 解析;并阻止即兴演奏。然后,您可以设置一个只会引发错误的包罗万象的路线。你宁愿在路由端使用regex 完成一些解析,而不是在你的控制器中(在我看来)。

    这使它减少到三个重载的操作,并允许更清洁和更“MVC”的代码。

    【讨论】:

    • 我也想过。但后来意识到他说“基本上它有一页”,这将是做他在问题中解释的有效点。
    • 我倾向于同意。但经过多年的拖延,我正在重建我的照片网站。我希望它尽可能简单。真的只需要一页。我不想要数据库,我希望它是自我发现的。 IE。我 FTP 目录结构中的照片目录,然后完成工作。由于文件夹目录中不能有 /,所以我需要处理的唯一情况是,如果由 URl 表示的目录不存在。很简单。
    • 我已经编辑了我的答案几次;但我想指出,您仍然想检查传递给您的字符串,并使用 Linq-To-SQL 或某种安全的方式来处理这些字符串,以防止 SQL 注入之类的事情。并非“所有”解析都应该在路由中完成,而是应该在那里确定到达您的应用程序的内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-29
    • 1970-01-01
    • 1970-01-01
    • 2010-12-22
    • 1970-01-01
    相关资源
    最近更新 更多