【问题标题】:ASP.Net MVC - handling bad URL parametersASP.Net MVC - 处理错误的 URL 参数
【发布时间】:2010-09-19 04:16:28
【问题描述】:

处理构建自己的 URL 并用他们喜欢的任何内容替换我们期望的 ID 的访问者的最佳方式是什么?

例如:

ASP.Net MVC - handling bad URL parameters

但用户可以轻松地将 URL 替换为:

https://stackoverflow.com/questions/foo

我考虑过将每个控制器功能参数设为String,并在它们上使用Integer.TryParse() - 如果通过了,那么我有一个 ID 并且可以继续,否则我可以将用户重定向到一个未知/不-找到或索引视图。

Stack Overflow 处理得很好,我也想这样做 - 你是怎么做的,或者你有什么建议?

【问题讨论】:

    标签: asp.net-mvc url error-handling


    【解决方案1】:

    这是一个像你这样的路线示例,但对数量有限制:

    routes.MapRoute(
        "Question",
        "questions/{questionID}",
        new { controller = "StackOverflow", action = "Question" },
        new { questionID = @"\d+" } //Regex constraint specifying that it must be a number.
    );
    

    这里我们设置 questionID 至少有一个数字。这也将阻止任何包含除整数以外的任何 url,并且还可以防止需要可为空的 int。

    注意:这不考虑大于 Int32 范围的数字 (-2147483647 - +2147483647)。我将此作为练习留给用户解决。 :)

    如果用户输入 url “questions/foo”,他们将不会点击 Question 操作,并通过它,因为它没有通过参数约束。如果需要,您可以在包罗万象/默认路线中进一步处理它:

    routes.MapRoute(
        "Catchall",
        "{*catchall}", // This is a wildcard routes
        new { controller = "Home", action = "Lost" }
    );
    

    这会将用户发送到 Home 控制器中的 Lost 操作。更多关于通配符的信息可以在here找到。

    注意:Catchall 应该作为 LAST 路由。 考虑到 ASP.NET MVC 中路由的惰性特性,将它放在链的更上方意味着它将处理它下面的所有其他路由。

    【讨论】:

    • 而不是最后一行:'new { questionID = @"\d{1,}" }',Scott Hanselman 使用稍短的语法:'new { questionID = @"\d+" }' 表示相同的意思。来源:asp.net/learn/mvc-videos/video-7093.aspx
    • 是的,两者几乎是一回事。我倾向于把我的放在这样的花括号中,因为我从数据库动态创建我的路由,当我想明确指定最大位数时,它为我节省了一些逻辑。
    • 为什么你的网址是“{catchall}”? '' 是什么意思?
    • @Ragepotato:这是一个通配符。
    • regex 的问题是"\d+" 允许大于 Int32.MaxValue 的数字。因此,我编写了自己的 Int32Constraint 来检查它。虽然我不确定这是否是最佳做法。
    【解决方案2】:

    这里有一些有用的信息可能会有所帮助。 如果你有一个动作方法

    public ActionResult Edit(int? id)
    {}
    

    如果有人输入

    /Home/Edit/23
    

    参数 id 将为 23。 但是,如果有人输入

    /Home/Edit/Junk
    

    然后 id 将是 null 这很酷。我认为它会抛出一个演员错误或什么的。这意味着如果 id 不是空值,那么它是一个有效的整数,可以传递给您的服务等以进行数据库交互。

    希望这能为您提供一些我在测试时发现的信息。

    【讨论】:

    • 此外,ModelState 中会出现模型错误,反映参数“id”的问题。
    【解决方案3】:

    在 ASP.NET MVC 中,您可以定义一个实现 IActionFilter 接口的过滤器。您将能够使用此属性装饰您的操作,以便在您的操作之前、之前或之后执行它。

    在您的情况下,您将定义它在您的操作“之前”执行。因此,如果传递的参数中有错误,您将能够取消它。这里的主要好处是您只需编写检查传递参数一次的代码(即您在过滤器中定义它)并在控制器操作中的任何位置使用它。

    在此处阅读有关 MVC 过滤器的更多信息:http://haacked.com/archive/2008/08/14/aspnetmvc-filters.aspx

    【讨论】:

      【解决方案4】:

      您可以将约束指定为正则表达式或定义自定义约束。请查看此博客文章了解更多信息:

      http://weblogs.asp.net/stephenwalther/archive/2008/08/06/asp-net-mvc-tip-30-create-custom-route-constraints.aspx

      您仍然需要处理 id 43243 没有映射到任何可以作为 IActionFilter 或直接在您的控制器中处理的情况。

      【讨论】:

        【解决方案5】:

        这种方法的问题是它们仍然可能传递一个不映射到页面的整数。如果他们这样做,只需返回 404,就像使用“foo”一样。除非您有明确的安全隐患,否则无需担心。

        【讨论】:

        • 当然,我必须检查 Integer 是否有效,但是使用 String 作为 Function 参数类型是否可行? - TaskList 示例 (asp.net/learn/mvc/tutorial-01-cs.aspx ~35min 43s) 将 ID 强类型为 Integer,这会在传入 'foo' 时导致错误:o/
        猜你喜欢
        • 1970-01-01
        • 2012-02-06
        • 2010-09-16
        • 2018-02-27
        • 2018-08-05
        • 2019-08-09
        • 2011-06-10
        • 2014-03-26
        • 2012-10-04
        相关资源
        最近更新 更多