[英]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.