簡體   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