2009-11-04 37 views
6

Tôi có một ứng dụng web bằng cách sử dụng MVC 2 Preview 2 và sau khi tất cả các tuyến đường được đăng ký, tôi cần phải bọc mỗi tuyến đường trong một trang trí tiếp tục xuống chuỗi. Vấn đề là, làm như vậy phá vỡ định tuyến. Những gì kết thúc lên xảy ra là phương pháp GetVirtualPath sẽ phù hợp sai cho các khu vực khác trong ứng dụng (Tôi đang sử dụng các khu vực đơn dự án). Nó không quan trọng nếu trang trí làm bất cứ điều gì hữu ích hay không. Sử dụng passthrough sau đây là tất cả những gì bạn cần để phá vỡ nó.Tại sao tuyến đường trang trí phá vỡ định tuyến trong ASP.NET MVC 2?

public class RouteDecorator: RouteBase 
{ 
    readonly RouteBase _route; 

    public RouteDecorator(RouteBase route) 
    { 
     _route = route; 
    } 

    public override RouteData GetRouteData(HttpContextBase context) 
    { 
     return _route.GetRouteData(context); 
    } 

    public override VirtualPathData GetVirtualPath(RequestContext context, RouteValueDictionary values) 
    { 
     return _route.GetVirtualPath(context, values); 
    } 
} 

Tôi chỉ định trang trí theo một vòng lặp đơn giản sau khi tất cả các tuyến đường được đăng ký.

var routes = RouteTable.Routes; 
for (var i = 0; i < routes.Count; i++) 
{ 
    routes[i] = new RouteDecorator(routes[i]); 
} 

Làm cách nào để chèn trang trí một cách an toàn mà không phá vỡ các tuyến đường và khu vực?

Tôi có giải pháp sinh sản có sẵn to download here. Trong bản tái tạo, trang trí tuyến đường được nhận xét. Nhận xét nó trở lại sẽ phá vỡ định tuyến và dữ liệu định tuyến của vùng giả đầu tiên sẽ khớp với các liên kết thông thường sẽ khớp chính xác với vùng tên tương ứng.

Trả lời

5

Tôi nghĩ rằng đó là cách các khu vực sử dụng từ điển DataTokens để lưu trữ thông tin vùng/không gian tên. Vì bạn đang kế thừa từ RouteBase, bạn có thể cần phải triển khai giao diện IRouteWithArea vì bạn không có DataTokens mà Route có.

Các ActionLink helper dường như gián tiếp gọi này do đó nhu cầu về giao diện mới này:

public static string GetAreaName(RouteBase route) 
{ 
    IRouteWithArea area = route as IRouteWithArea; 
    if (area != null) 
    { 
     return area.Area; 
    } 
    Route route2 = route as Route; 
    if ((route2 != null) && (route2.DataTokens != null)) 
    { 
     return (route2.DataTokens["area"] as string); 
    } 
    return null; 
} 

[Edit - 2009/11/12] Tôi tin rằng sau đây sẽ khắc phục vấn đề, như trang trí dường như kết thúc gói các tuyến đường nhiều hơn một lần:

tài sản khác liên quan đến trang trí:

public RouteBase InnerRoute 
     { 
      get 
      { 
       return _route; 
      } 
     } 

Triển khai giao diện:

public string Area 
     { 
      get 
      { 

       RouteBase r = _route; 
       while (r is RouteDecorator) 
        r = ((RouteDecorator) r).InnerRoute; 
       string s = GetAreaToken(r); 
       if (s!= null) return s; 
       return null; 
      } 
     } 

     private string GetAreaToken(RouteBase r) 
     { 
      var route = r as Route; 
      if (route != null && route.DataTokens !=null && route.DataTokens.ContainsKey("area")) 
      { 
       return (route.DataTokens["area"] as string); 
      } 
      return null; 
     } 
    } 
+0

Cảm ơn bạn đã nỗ lực. Việc triển khai IRouteWithArea không sửa lỗi blanche của vấn đề nhưng nó có thể đưa tôi theo một hướng mới. Cảm ơn bạn. –

+0

Trình trang trí xuất hiện để kết thúc gói tuyến đường nhiều lần. Tôi đã chỉnh sửa câu trả lời của tôi cung cấp mã để thực hiện một giải pháp làm việc, mặc dù tôi lý tưởng muốn tìm hiểu lý do tại sao điều này xảy ra vì nó khá lạ. –

+0

Điều này chắc chắn là câu trả lời cho vấn đề. Tôi không bắt được vấn đề trang trí sinh sản. Đây là một số hành vi kỳ lạ, hoặc, hành vi mong đợi với một sự thiếu hiểu biết tại sao nó xảy ra. –

0

Điều gì sẽ xảy ra nếu bạn trang trí lớp Tuyến đường thay vì RouteBase?

Hãy suy nghĩ về một cái gì đó như thế này:

public class RouteDecorator: Route 
{ 
    readonly Route _route; 

    public RouteDecorator(Route route) 
    { 
     _route = route; 
    } 

    public override RouteData GetRouteData(HttpContextBase context) 
    { 
     return _route.GetRouteData(context); 
    } 

    public override VirtualPathData GetVirtualPath(RequestContext context, RouteValueDictionary values) 
    { 
     return _route.GetVirtualPath(context, values); 
    } 
} 

tôi cũng khuyên bạn nên kiểm tra ra System.Web.Routing.dll với Reflector, nó có thể cung cấp cho bạn một cái nhìn sâu sắc về những gì đang xảy ra.

Và cũng có thể, những gì xảy ra, nếu bạn làm điều này:

var routes = RouteTable.Routes.ToList(); 
RouteTable.Routes.Clear(); 
//or, alternatively, if the above doesn't work: 
//RouteTable.Routes = new RouteCollection(); 
foreach (var r in routes) 
{ 
    RouteTable.Routes.Add(new RouteDecorator(r)); 
} 

Tôi hy vọng rất nhiều rằng nó giúp.

+0

Tôi không thể sử dụng Route thay vì RouteBase vì RouteCollection là một tập hợp của RouteBase. Tôi đã sử dụng Reflector và mã nguồn MVC 2 để cố gắng suy luận vấn đề trước khi đăng nó ở đây. Đề xuất khác của bạn (về việc xóa bộ sưu tập?) Không có hiệu lực. –

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