2008-12-18 37 views
31

Đây là kịch bản của tôi. Ví dụ cho phép nói rằng tôi cần trả lại một danh sách các xe dựa trên tiêu chí tìm kiếm. Tôi muốn có một cái nhìn duy nhất để hiển thị kết quả vì đầu ra sẽ giống nhau, nhưng tôi cần một số cách để đến đó. Ví dụ: tôi có thể có Biểu mẫu có hộp văn bản để tìm kiếm theo năm. Tôi có thể có một trang riêng biệt có chứa một siêu liên kết cho tất cả các xe ô tô màu đỏ, Toyota. Làm cách nào để xử lý nhiều trường hợp này trong cùng một Chế độ xem và Bộ điều khiển. Sự tiến thoái lưỡng nan của tôi là tìm kiếm có thể chứa nhiều tùy chọn… năm, tạo, mô hình, v.v. nhưng tôi không biết phải đặt chúng ở đâu.Định tuyến tùy chỉnh ASP.NET MVC cho tìm kiếm

Cách tiếp cận tốt nhất cho việc này là gì? Tôi có nên xác định các tham số trong định tuyến hoặc đi với chuỗi truy vấn, v.v.

Trả lời

78

Lựa chọn 1

Tất nhiên bạn luôn có thể chọn con đường/xe/search /? Nhà cung cấp = Toyota & color = Red & mô hình = Corola và tôi nghĩ rằng nó sẽ tốt cho bạn .

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

Bạn có thể nhận thông số từ Yêu cầu.Params đang hoạt động trong trường hợp này.

Lựa chọn 2

Hoặc bạn có thể xác định params trong bảng định tuyến, nhưng AFAIK nó sẽ được yêu cầu để thực hiện một bộ quy tắc cho tất cả các kết hợp có thể, bởi vì một trật tự của params vấn đề, ví dụ:

 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"} 
     ); 

... tương tự. Đó là sự thật nếu bạn đang đi với MvcRouteHandler tiêu chuẩn.

Nhưng đó là một cách dễ dàng :)

Lựa chọn 3

Các khó khăn, nhưng, tôi nghĩ, cách thanh lịch nhất, là làm cho thực hiện IRouteHandler của riêng bạn - nó sẽ cho bạn nhiều hơn nữa linh hoạt trong thứ tự params. Nhưng một lần nữa, nó là một cách khó khăn, không đi với nó nếu bạn có một ứng dụng đơn giản. Vì vậy, chỉ cần cho ví dụ về làm thế nào để làm cho nó theo cách này (ví dụ rất đơn giản):

Thêm tuyến đường mới vào danh sách các tuyến đường:

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

Thêm lớp mà sẽ tinh chỉnh các dây chuyền xử lý yêu cầu tiêu chuẩn:

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); 
    } 
} 

Trong điều khiển:

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(); 
} 

Và nó sẽ làm việc với bất kỳ thông số tìm kiếm đặt hàng:

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

Nhưng cũng không quên làm một logic hệ liên kết, vì Html.ActionLink và Html.RenderLink sẽ không cung cấp cho bạn URL trong hình thức xinh đẹp của/xe/tìm kiếm/mô hình/Corola/color/red/vendor/Toyota, vì vậy bạn sẽ cần tạo một trình tạo liên kết tùy chỉnh.

Vì vậy, nếu bạn cần định tuyến thực sự linh hoạt - bạn nên làm theo cách này một cách khó khăn :)

+0

Tôi nghĩ rằng hành động tốt nhất của tôi vào lúc này sẽ là Lựa chọn 1. Lựa chọn 2 là cách tôi bước đầu, nhưng có vẻ không hiệu quả khi phải đặt tất cả các kết hợp định tuyến có thể. Tùy chọn 3 có vẻ tốt cho sau này nếu tôi muốn refactor, nhưng là một MVC NOOB tôi sẽ dính với các tuyến đường dễ dàng. –

+0

Câu trả lời tuyệt vời! @Eric đừng quên để upvote – AnthonyWJones

+0

Cảm ơn bạn, Anthony :) – maxnk

0

Mỗi phương pháp (hành động) trên bộ điều khiển sẽ có các tham số khác nhau, nhưng tạo cùng một bộ sưu tập kết quả tìm kiếm. Sau đó, mỗi số sẽ là

return View("SearchResult", searchResultCollection); 

Tất cả đều sử dụng cùng một chế độ xem, SearchResult.aspx.

0

Điều gì đó dọc theo những dòng này sẽ làm những gì bạn đang theo dõi. Lưu ý rằng có hai phương thức hành động khác nhau, nhưng cả hai đều trả về một cuộc gọi đến DisplayResults() - vì vậy chúng kết thúc bằng cách sử dụng cùng một khung nhìn, với các ViewData khác nhau.

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

Cảm ơn. Ví dụ của bạn là cách suy nghĩ của tôi bắt đầu, nhưng tôi nghĩ rằng sự thiếu hiểu biết của tôi về định tuyến MVC khiến tôi bị bối rối. Tôi chỉ nhìn nó trong vài ngày. Làm thế nào bạn sẽ vượt qua một mảng màu sắc cho ActionResult. Sự hiểu biết của tôi là các tham số này đến từ URL –

Các vấn đề liên quan