我的ASP.NET MVC应用程序有一个场景,用户输入可以直接影响对RedirectToAction()的调用目标(通过字符串),如果用户有可能创建运行时错误,不正确的输入导致他们请求不存在的动作。我想彻底防止这个问题,但我想以最少的方式这样做,因为它必须在大量的请求上完成。话虽这么说,反射将是一个可行的解决方案,用于确认/ Controller / ActionName实际存在,但反射是一个非常繁重的操作。
确认ASP.NET MVC应用程序中的给定Url实际连接到控制器操作的最佳方法是什么?
答案 0 :(得分:2)
一种方法是获得用户输入数据的允许值列表。例如,如果用户输入了她最喜欢的颜色:
// 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");
虽然没有像查看路由表那样动态,但速度很快,您可以确信用户没有输入一些与您的路由相关的恶意值。
答案 1 :(得分:1)
快速而粗略的选择就是点击网址,以下代码可以帮助您快速测试一些内容,
注意:您实际上已经访问了自己的网站并了解了解您的应用程序的含义。
这有助于我们在某些集成测试中诊断某些环境问题。
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");'
}
答案 2 :(得分:0)
我最终选择的路线是反射和包含相关控制器中存储在Application []中的所有有效操作的字典。通过检查方法的ReturnType并验证它是(或派生自)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,则调用它。虽然它仍然需要反射,但它至少是经过优化的,因此在应用程序运行时它只会发生一次。