繁体   English   中英

ASP.NET MVC-验证路由的存在

[英]ASP.NET MVC - Verify the Existence of a Route

我的ASP.NET MVC应用程序有一个场景,其中用户输入可以直接影响对RedirectToAction()的调用目标(通过字符串),并且如果输入不正确导致用户有可能创建运行时错误。他们请求不存在的操作。 我想彻底避免此问题,但我想以最省力的方式做到这一点,因为必须对大量请求进行处理。 话虽如此,反射将是一个可行的解决方案,用于确认/ Controller / ActionName实际上存在,但是反射是一项非常繁重的操作。

确认ASP.NET MVC应用程序中的给定URL实际上与控制器操作关联的最佳方法是什么?

一种方法是拥有用户输入数据的允许值列表。 例如,如果用户输入了她喜欢的颜色:

// userColour = the user set colour
var allowableColours = new [] { "Red", "Blue", "Green" };
if (!allowableColours.Contains(userColour))
{
    // Set to a default colour.
    userColour = "Red";
}

return RedirectToAction(userColour, "Colour");

尽管它不像查看路由表那样动态,但它很快,并且您可以确信他们没有输入一些恶意的值来破坏您的路由。

一种快速而粗略的选择是直接点击网址,以下代码可以帮助您快速进行测试,

注意:您实际上是在访问您的网站,并意识到这在您的应用程序中意味着什么。

这有助于我们在某些集成测试中诊断一些环境问题。

var urlToExec = "http://yoursite.com/" + controllerAndAction;

var wr = (HttpWebRequest) WebRequest.Create(urlToExec);

try
{
    var resp = (HttpWebResponse)wr.GetResponse();

    if (resp.StatusCode != HttpStatusCode.OK || resp.StatusCode == HttpStatusCode.NotFound)
        //it was found

}
catch (Exception ex)
{
    //404 or other http error
    //404 and the like result in GetResponse() throwing an exception
    //this was verified by having actions return via:
    //'return new HttpNotFoundResult("This doesn't exist");'
}

我最终在这里采取的路线是反射和包含在Application []中存储的相关Controller中所有有效动作的Dictionary(字典)。 通过检查方法的ReturnType并确认它是ActionResult(或从ActionResult派生)并且它不是Private,可以确定有效的Action。 我可以再做一些检查,但是现在这些已经足够了。

public static bool MethodIsAction(MethodInfo method)
{
    if (method == null)
        throw new ArgumentNullException("Invalid Parameter: method cannot be null.");

    if (method.ReturnType != typeof(ActionResult) && method.ReturnType.BaseType != typeof(ActionResult))
        return false;

    if (method.IsPrivate)
        return false;

    return true;
}

动作字典是通过Application_Start中的以下方法构建的:

public static Dictionary<string, MethodInfo> GetActionDictionary(Type controller)
{
    Dictionary<string, MethodInfo> dict = null;

    var methods = controller.GetMethods().Where(MethodIsAction);
    if (methods.Any())
    {
        dict = new Dictionary<string, MethodInfo>(StringComparer.OrdinalIgnoreCase);
        foreach (var action in methods)
            dict.Add(action.Name, action);
    }
    return dict;
}

当用户请求限定动作时,我只需将动作名称指向“字典”即可,如果该动作名称存在MethodInfo,则将其调用。 尽管它仍然需要反射,但至少已对其进行了优化,以使其仅在应用程序运行时发生一次。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM