2008-12-18 15 views
31

這是我的場景。例如,假設我需要根據搜索條件返回汽車列表。我希望有一個視圖來顯示結果,因爲輸出結果是相同的,但我需要幾種方法來實現。例如,我可能會有一個帶有文本框的表單按年進行搜索。我可能有另一個單獨的頁面,其中包含所有紅色豐田汽車的超鏈接。如何在同一視圖和控制器中處理這些多個場景。我的困境是,搜索可能包含幾個選項......年,製作,模型等,但我不知道把它們放在哪裏。用於搜索的ASP.NET MVC自定義路由

這是最好的方法是什麼?我應該在路由中定義參數還是使用查詢字符串等?

回答

78

選項1

當然,你總是可以選擇/汽車/搜索/?供應商=豐田&的color = red &模型=的Corola,我認爲這將有利於你的方式。

routes.MapRoute(
    "CarSearch", 
    "car/search", 
    new { controller = "car", action = "search" } 
); 

在這種情況下,您可以在Request.Params中使用Request.Params。

選項2

,也可以定義在路由表中PARAMS,但據我所知它會被要求作出了一套所有可能的組合規則,因爲PARAMS的順序事,例如:

 routes.MapRoute(
      "CarSearch1", 
      "car/search/vendor/{vendor}/color/{color}/model/{model}", 
      new {controller = "car", action = "search"} 
     ); 

     routes.MapRoute(
      "CarSearch2", 
      "car/search/color/{color}/vendor/{vendor}/model/{model}", 
      new {controller = "car", action = "search"} 
     ); 

     routes.MapRoute(
      "CarSearch3", 
      "car/search/model/{model}/color/{color}/vendor/{vendor}", 
      new {controller = "car", action = "search"} 
     ); 

...以此類推。如果你使用標準的MvcRouteHandler,這是真的。

但它是一個簡單的方法:)

選項3

的辛苦,但是,我認爲,最優雅的方式,就是讓自己的IRouteHandler實現 - 它會給你更多靈活的參數順序。但是,再次,它是一個艱難的方式,如果你有一個簡單的應用程序,不要去用它。 所以,僅僅例如如何使這種方式(很簡單的例子):

添加新路線路由列表:

routes.Add 
    (
     new Route 
      (
       "car/search/{*data}", 
       new RouteValueDictionary(new {controller = "car", action = "search", data = ""}), 
       new MyRouteHandler() 
      ) 
    ); 

添加將調整標準的請求處理鏈類:

class MyRouteHandler : IRouteHandler 
{ 
    public IHttpHandler GetHttpHandler(RequestContext requestContext) 
    { 
     return new MyHttpHandler(requestContext); 
    } 
} 

class MyHttpHandler : MvcHandler 
{ 
    public MyHttpHandler(RequestContext requestContext) : base(requestContext) 
    { 
    } 

    protected override void ProcessRequest(HttpContextBase httpContext) 
    { 
     IController controller = new CarController(); 
     (controller as Controller).ActionInvoker = new MyActionInvoker(); 
     controller.Execute(RequestContext); 
    } 
} 

class MyActionInvoker : ControllerActionInvoker 
{ 
    protected override ActionResult InvokeActionMethod(MethodInfo methodInfo, IDictionary<string, object> parameters) 
    { 
     // if form of model/{model}/color/{color}/vendor/{vendor} 
     var data = ControllerContext.RouteData.GetRequiredString("data"); 
     var tokens = data.Split('/'); 

     var searchParams = new Dictionary<string, string>(); 
     for (var i = 0; i < tokens.Length; i++) 
     { 
      searchParams.Add(tokens[i], tokens[++i]); 
     } 

     parameters["searchParams"] = searchParams; 

     return base.InvokeActionMethod(methodInfo, parameters); 
    } 
} 

在控制器:

public ActionResult Search(IDictionary<string, string> searchParams) 
{ 
    ViewData.Add 
     (
      // output 'model = Corola, color = red, vendor = Toyota' 
      "SearchParams", 
      string.Join(", ", searchParams.Select(pair => pair.Key + " = " + pair.Value).ToArray()) 
     ); 
    return View(); 
} 

,它會與任何搜索參數工單:

/car/search/vendor/Toyota/color/red/model/Corola 
/car/search/color/red/model/Corola/vendor/Toyota 
/car/search/model/Corola/color/red/vendor/Toyota 

但也不要忘了做一個鏈接生成邏輯,因爲Html.ActionLink和Html.RenderLink不會給你/汽車/搜索/模型/ Corola漂亮的形式網址/ color/red/vendor/Toyota,所以你需要製作一個自定義鏈接生成器。

所以,如果你需要一個非常靈活的路由 - 你最好去這個難題:)

+0

我認爲我目前的最佳行動方案將是選項1.選項2是我最初的方式,但似乎沒有效率必須放置所有可能的路由組合。如果我想重構,選項3看起來不錯,但作爲一個MVC NOOB,我會堅持簡單的路線。 – 2008-12-19 16:36:50

0

控制器上的每個方法(操作)都會採用不同的參數,但創建相同的搜索結果集合。然後,每個都會

return View("SearchResult", searchResultCollection); 

它們都使用相同的視圖SearchResult.aspx。

0

沿着這些線條的東西應該做你以後的事情。請注意,有兩種不同的操作方法,但它們都會返回DisplayResults()的調用 - 因此它們最終會使用相同的視圖並使用不同的ViewData。

public class SearchController : Controller { 

    public ActionResult ByColor(Color[] colors) { 
     List<Car> results = carRepository.FindByColor(colors); 
     return(DisplayResults(result)); 
    } 

    public ActionResult ByMake(string make) { 
     List<Car> results = carRepository.FindByMake(make); 
     return(DisplayResults(results)); 
    } 

    private ActionResult DisplayResults(IList<Car> results) { 

     // Here we explicitly return the view /Views/Search/Results.aspx 
     // by specifying the view name in the call to View(); 
     return(View("Results", results)); 
    } 
} 
+0

謝謝。你的例子是我的想法是如何開始的,但我認爲我對MVC路由的理解不夠,導致我陷入困境。我只看了幾天。你如何將一個顏色數組傳遞給ActionResult。我的理解是,這些參數來自URL – 2008-12-19 16:42:26