簡體   English   中英

ASP.NET MVC 路由 - Url.Action 發送查詢字符串而不是路由值

[英]ASP.NET MVC Routing - Url.Action sending query string not route values

幾天來,我一直在尋找解決這個問題的方法,但它讓我難住了。

我有一個 ASP.NET MVC 應用程序,我在其中實現了分頁、排序和過濾。 它在第一個視圖中運行良好,然后當我在下一個視圖中實現它時它停止工作。 我正在遵循指南。

在更改之前,如果我使用過濾器,它會回傳並執行正確的操作並過濾結果。 單擊底部的頁碼之一會將我帶到過濾結果集中的頁面。

更改后,我收到一個錯誤,因為與匹配多個的路由發生沖突。 由於這兩個控制器的路由值相同,因此我認為我需要添加控制器名稱作為路由的第一部分。

現在,當我應用過濾器時,它仍然有效,但是單擊另一個頁碼會刪除過濾器,但會使用正確的頁碼(在未過濾的結果集上)。 調試告訴我它將轉到默認的索引操作,而不是將應用過濾和排序的定義路由。

不同之處在於,在更改之前,它發送了以下網址:

https://localhost:44382/Users/Index/UserName/ascending/none/all/2/an

現在它正在發送:

https://localhost:44382/Users/Index?sortKey=UserName&sortDirection=ascending&previousSortKey=none&selectedFbSupplied=all&page=2&selectedNameFilter=an

如果我手動將其更改為路由值而不是查詢字符串,它會按預期工作。

下面代碼的相關部分。

從用戶控制器:

    [HttpGet]
    [Route("Users/Index")]
    public ActionResult Index(int? page)
    {
        ViewBag.SortKey = "UserName";
        ViewBag.SortDirection = "ascending";
        ViewBag.SelectedFbSupplied = string.IsNullOrEmpty(ViewBag.SelectedFbSupplied) ? "all" : ViewBag.SelectedFbSupplied;
        ViewBag.SelectedNameFilter = string.IsNullOrEmpty(ViewBag.SelectedNameFilter) ? "" : ViewBag.SelectedNameFilter;

        ViewBag.FbSupplied = new List<SelectListItem>{
                                                       new SelectListItem { Value="all", Text="All"},
                                                       new SelectListItem { Value="yes", Text="Yes"},
                                                       new SelectListItem { Value="no", Text="No"}
                                                    };

        var users = SortedUserList(FilteredUsers());
        int pageSize = 50;
        int pageNumber = (page ?? 1);
        return View(users.ToPagedList(pageNumber, pageSize));
    }

    [HttpGet]
    [Route("Users/Index/{sortKey}/{sortDirection}/{previousSortKey}/{selectedFbSupplied}/{page:int}/{selectedNameFilter?}")]
    public ActionResult Index(string sortKey, string sortDirection, string previousSortKey, string selectedFbSupplied, int? page, string selectedNameFilter="")
    {
                    
        if (sortKey == previousSortKey)
        {
            //Key is the same, flip the direction
            sortDirection = sortDirection == "ascending" ? "descending" : "ascending";
        }
        ViewBag.SortKey = String.IsNullOrEmpty(sortKey) ? "UserName" : sortKey;
        ViewBag.SortDirection = String.IsNullOrEmpty(sortDirection) ? "ascending" : sortDirection;


        ViewBag.FbSupplied = new List<SelectListItem>{
                                                       new SelectListItem { Value="all", Text="All"},
                                                       new SelectListItem { Value="yes", Text="Yes"},
                                                       new SelectListItem { Value="no", Text="No"}
                                                    };

        var nameFilter = string.IsNullOrEmpty(selectedNameFilter) ? "" : selectedNameFilter;
        ViewBag.SelectedFbSupplied = string.IsNullOrEmpty(selectedFbSupplied) ? "all" : selectedFbSupplied;
        ViewBag.SelectedNameFilter = nameFilter;


        var users = SortedUserList(FilteredUsers(nameFilter, selectedFbSupplied), sortKey, sortDirection);
        int pageSize = 50;
        int pageNumber = (page ?? 1);
        return View(users.ToPagedList(pageNumber, pageSize));
    }

以及視圖中的頁面鏈接:

@Html.PagedListPager(Model, page => Url.Action("Index",  "Users" , new { sortKey = ViewBag.SortKey, sortDirection = ViewBag.SortDirection, previousSortKey = "none", selectedFbSupplied = ViewBag.SelectedFbSupplied, page = page , selectedNameFilter = ViewBag.SelectedNameFilter}))

路由配置(不變):

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.MapMvcAttributeRoutes();

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }

}

任何想法為什么它發送查詢字符串而不是路由值?

簡而言之:如果您指定路線名稱(不僅僅是路線模板),那么您可以通過RouteUrl幫助程序通過它們的名稱來引用它們。

路線模板

  • 它是一種模式,它定義了如何到達給定的動作以及應該如何匹配路由參數。
  • 它們被注冊到一個 RouteTable 中,它基本上是給定 url 模式和相關控制器操作之間的映射。
  • 路線的順序很重要,因為第一個匹配獲勝。

路線名稱

  • 它們與 Url 模式匹配無關。
  • 它們僅在 Url 生成期間使用。 RouteUrlCreatedAtRoute ( 1 ) 等)
  • 它們必須是全局唯一的(因此排序無關緊要)。

可能的錯誤

  • 如果您使用相同的Template注冊兩個路由,那么當您對其中一個路由進行調用時,應用程序將在運行時拋出AmbiguousMatchException
    • 因此,其他路線將完美無缺。
  • 如果您注冊兩個具有相同Name路由,那么當您進行任何調用時,應用程序將在運行時拋出InvalidOperationException
    • 因此,其他路線將不起作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM