2010-04-22 26 views
10

Làm cách nào tôi có thể nhận được hành động của bộ điều khiển (phương pháp) và loại bộ điều khiển sẽ được gọi, với số System.Web.Routing.RouteData?Làm cách nào để có được loại bộ điều khiển và thông tin hành động từ url hoặc từ dữ liệu tuyến đường?

Kịch bản của tôi là điều này - Tôi muốn có thể thực hiện một số hành động nhất định (hoặc không) trong phương thức OnActionExecuting cho một hành động.

Tuy nhiên, tôi thường không muốn biết hành động hiện tại, nhưng hành động "gốc" được gọi; bởi điều này tôi có nghĩa là tôi có thể có một cái nhìn gọi là "Đăng nhập", đó là trang đăng nhập của tôi. Chế độ xem này có thể bao gồm một chế độ xem một phần khác "LeftNav". Khi OnActionExecuting được gọi cho LeftNav, tôi muốn có thể xác định rằng nó thực sự được gọi là "gốc" aciton của Đăng nhập.

Tôi nhận thấy rằng bằng cách gọi RouteTable.Routes.GetRouteData(actionExecutingContext.HttpContext), tôi có thể nhận được tuyến đường cho yêu cầu "root", nhưng làm cách nào để biến điều này thành thông tin về phương thức và loại ?

Giải pháp duy nhất tôi có cho đến nay, là một cái gì đó như:

var routeData = RouteTable.Routes.GetRouteData(actionExecutingContext.HttpContext) 
var routeController = (string)routeData.Values["controller"]; 
var routeAction = (string)routeData.Values["action"]; 

Vấn đề với điều này là "routeController" là tên bộ điều khiển với các "điều khiển" hậu tố loại bỏ, và không đủ điều kiện; tức là "Đăng nhập", thay vì "MyCode.Website.LoginController".

Tôi muốn nhận được thực tế TypeMethodInfo nếu có thể hoặc ít nhất là tên loại đủ điều kiện.

Bất kỳ suy nghĩ hoặc phương pháp thay thế nào?

[EDIT - đây là ASP.Net MVC 1.0]

Trả lời

4
protected override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
    var type1 = filterContext.Controller.GetType(); 
    var type2 = filterContext.ActionDescriptor 
        .ControllerDescriptor.ControllerType; 
    } 

OK, xin lỗi, tôi bỏ lỡ "gốc" phần.

Sau đó, một cách khác, bạn có thể lưu loại bộ điều khiển vào bộ nhớ luồng. Mã Pseudocode:

protected override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
    if (!Thread.LocalStorage.Contains("root_controller")) 
     Thread.LocalStorage["root_controller"] = 
      filterContext.ActionDescriptor 
        .ControllerDescriptor.ControllerType; 
    } 

Chỉ là một ý tưởng. Tôi chắc rằng lưu trữ cục bộ luồng có sẵn trong C#. Ý tưởng chính ở đây là bạn chỉ lưu nó cho yêu cầu đầu tiên, do đó nó luôn luôn là bộ điều khiển gốc.

+0

Thật không may, điều này sẽ không hoạt động vì nó trả về loại hành động bộ điều khiển * hiện tại *, chứ không phải hành động của trình điều khiển "gốc" trong ví dụ mà tôi đã đưa ra. Lý do tôi gọi GetRouteData (actionExecutingContext.HttpContext) là bởi vì điều này không thành công cho tôi các tuyến đường cho "root", nhưng tôi không thể sau đó dịch này vào loại điều khiển và phương pháp. –

+0

Đó là một gợi ý rất thú vị - cảm ơn nữ hoàng3 –

+1

Không sử dụng lưu trữ ThreadLocal từ bên trong một ứng dụng ASP.NET. ASP.NET yêu cầu có thể nhảy xung quanh giữa các chủ đề, do đó, lưu trữ ThreadLocal có thể biến mất khi bạn không mong đợi nó. Sử dụng HttpContext.Items thay vào đó nếu bạn cần lưu trữ thông tin chỉ xung quanh yêu cầu hiện tại. – Levi

1
public Type ControllerType(string controllerName) 
{ 
    var fullName = controllerName + "Controller"; 
    var assemblyName = Assembly.GetExecutingAssembly().FullName; 
    return Activator.CreateInstance(assemblyName, fullTypeName).GetType(); 
} 

public MethodInfo ActionMethodInfo(string actionName, Type controllerType) 
{ 
    return controllerType.GetMethod(actionName); 
} 

Bạn đang nghĩ đến việc một thực hiện tương tự như này? Một số Try/Catches yêu cầu !!!

Kindness,

Dan

+0

Cảm ơn Dan - đó là kinda nơi tôi đánh đầu, nhưng thực sự hy vọng có thể tránh. Bên dưới một nơi nào đó, MVC biết chính xác phương thức nào, trên loại nào, nó sẽ gọi.Vấn đề với cách tiếp cận này (và của tôi) là tôi phải gắn thêm hậu tố "Controller", và cũng sẽ phải thêm không gian tên vào kiểu, v.v. Nó có thể hoạt động, nhưng nếu tôi có thể MVC đang làm gì, tôi thích làm theo cách đó. –

4

Đây là giải pháp tôi đã biên soạn từ nhiều nguồn khác nhau. Các url biến nên chứa URL của hành động:

 url = "YOUR URL"; 
     // Original path is stored and will be rewritten in the end 
     var httpContext = new HttpContextWrapper(HttpContext.Current); 
     string originalPath = httpContext.Request.Path; 

     try 
     { 
      // Fake a request to the supplied URL into the routing system 
      httpContext.RewritePath(url); 
      RouteData urlRouteData = RouteTable.Routes.GetRouteData(httpContext); 

      // If the route data was not found (e.g url leads to another site) then authorization is denied. 
      // If you want to have a navigation to a different site, don't use AuthorizationMenu 
      if(urlRouteData != null) 
      { 
       string controllerName = urlRouteData.Values["controller"].ToString(); 
       string actionName = urlRouteData.Values["action"].ToString(); 

       // Get an instance of the controller that would handle this route 
       var requestContext = new RequestContext(httpContext, urlRouteData); 
       var controllerFactory = ControllerBuilder.Current.GetControllerFactory(); 
       var controller = (ControllerBase) controllerFactory.CreateController(requestContext, controllerName); 

       // Find the action descriptor 
       var controllerContext = new ControllerContext(httpContext, new RouteData(), controller); 
       var controllerDescriptor = new ReflectedControllerDescriptor(controller.GetType()); 
       var actionDescriptor = controllerDescriptor.FindAction(controllerContext, actionName); 
      } 
     } 
     finally 
     { 
      // Reset our request path. 
      httpContext.RewritePath(originalPath); 
     } 
Các vấn đề liên quan