2009-11-27 12 views
54

Nếu tôi tạo một đối tượng trong một bộ lọc Tuỳ chỉnh hành động trong ASP.NET MVC trongASP.NET MVC đèo đối tượng từ Tuỳ chỉnh Action Lọc to Action

public override void OnActionExecuting(ActionExecutingContext filterContext) 
{ 
    DetachedCriteria criteria = DetachedCriteria.For<Person>(); 
    criteria.Add("stuff"); 

    // Now I need to access 'criteria' from the Action..... 

} 

là có cách nào tôi có thể truy cập vào các đối tượng từ các hành động hiện đang thực thi.

Trả lời

43

tôi sẽ khuyên bạn nên đặt nó trong các dữ liệu Route.

protected override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     filterContext.RouteData.Values.Add("test", "TESTING"); 
     base.OnActionExecuting(filterContext); 
    } 

    public ActionResult Index() 
    { 
     ViewData["Message"] = RouteData.Values["test"]; 

     return View(); 
    } 
+2

Khoản mục tồn tại trong RouteData trong bao lâu? Tôi chỉ cần giữ đối tượng trong suốt thời gian thực hiện hành động hiện tại, hoặc nhiều nhất cho yêu cầu hiện tại, nếu đây là cách dữ liệu tuyến đường hoạt động thì đây là câu trả lời nếu không HttpContext.Items có lẽ tốt hơn. – reach4thelasers

+1

RouteData là dữ liệu liên quan đến tuyến đường hiện đang thực hiện (hành động). Hãy coi đó là vùng chứa đại diện cho url yêu cầu được phân tích cú pháp và ánh xạ theo các quy tắc định tuyến của bạn. – Neal

+0

'RouteData' chắc chắn là tuyệt vời để làm điều này như tôi đã học hôm nay nhờ câu trả lời của bạn ở đây. Cuốn sách MVC màu đen và màu vàng tuyệt đẹp của tôi ở đây trước mặt tôi (ấn bản thứ tư) không đề cập gì về nó hoặc làm bất cứ điều gì tương tự như vậy trong toàn bộ chương về bộ lọc (hoặc ít nhất tôi chưa tìm thấy nó?). Dù sao, 1 và cảm ơn bạn! – Funka

30

Bạn có thể sử dụng HttpContext:

filterContext.HttpContext.Items["criteria"] = criteria; 

Và bạn có thể đọc nó trong hành động:

[YourActionFilter] 
public ActionResult SomeAction() 
{ 
    var criteria = HttpContext.Items["criteria"] as DetachedCriteria; 
} 
+1

Tôi đã suy nghĩ về việc sử dụng HttpContext.Items [] và một giải pháp có thể chấp nhận nó vì nó sẽ bị xóa ra vào cuối yêu cầu. Tôi đã không chắc chắn nếu có một nơi tôi có thể lưu trữ các công cụ tồn tại chỉ trong thời gian hành động. – reach4thelasers

3

Set item trong ViewData hoặc của một viewmodel nếu bạn vượt qua nó như một tham số vào của bạn hoạt động. Ở đây tôi thiết lập thuộc tính của một ViewModel

public override void OnActionExecuting(ActionExecutingContext filterContext) 
{ 
    ViewModelBase viewModel = null; 
    foreach (object parameter in filterContext.ActionParameters.Values) 
    { 
     if (parameter is ViewModelBase) 
     { 
      viewModel = (ViewModelBase)parameter; 
      break; 
     } 
    } 
    if(viewModel !=null) 
    { 
     viewModel.SomeProperty = "SomeValue"; 
    } 
} 


    public ActionResult About(ViewModelBase model) 
    { 
     string someProperty= model.SomeProperty; 
} 

Dưới đây là phiên bản untyped Tôi nghĩ rằng bạn thích:

public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     filterContext.Controller.ViewData.Add("TestValue", "test"); 

    } 

     [FilterWhichSetsValue] 
     public ActionResult About() 
     { 
      string test = (string)ViewData["TestValue"]; 
      return View(); 
     } 
+0

Cảm ơn đề xuất của bạn. Hành động của tôi không coi ViewModelBase là một tham số, và tôi không muốn giới thiệu nó chỉ để giải quyết vấn đề của tôi. – reach4thelasers

+0

Xem bài đăng đã chỉnh sửa cho phiên bản chưa được nhập. Tôi vẫn sẽ sử dụng phiên bản đầu tiên. Có lẽ tên người dùng chỉ có vẻ xấu. Nó có thể là bất kỳ lớp nào và không phải là lớp của khung nhìn đã nhập. –

59

better approach được mô tả bởi Phil Haack.

Về cơ bản đây là những gì bạn cần làm:

public class AddActionParameterAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     base.OnActionExecuting(filterContext); 

     // Create integer parameter. 
     filterContext.ActionParameters["number"] = 123; 

     // Create object parameter. 
     filterContext.ActionParameters["person"] = new Person("John", "Smith"); 
    } 
} 

Gotcha duy nhất là nếu bạn đang tạo các thông số đối tượng, sau đó lớp học của bạn (trong trường hợp này Person) phải có một constructor mặc định, nếu không bạn sẽ nhận được một ngoại lệ.

Đây là cách bạn muốn sử dụng bộ lọc trên:

[AddActionParameter] 
public ActionResult Index(int number, Person person) 
{ 
    // Now you can use number and person variables. 
    return View(); 
} 
+1

Cách rất hay để làm điều này, tôi chắc chắn nghĩ rằng đây là cách tốt hơn so với câu trả lời được chấp nhận. Đây sẽ là câu trả lời được chấp nhận! Cảm ơn! – avb

+0

Tại sao điều này tốt hơn câu trả lời được chấp nhận?Dường như không có lý do gì cho việc này và trường hợp bổ sung [AddActionParameter] là công việc bổ sung rõ ràng rằng phương thức khác không yêu cầu chức năng. –

+0

@ChrisBertrand Nó sạch hơn và tránh các lỗi biên dịch trong bộ điều khiển, bằng cách sử dụng kiểu gõ mạnh, tức là - lớp 'Người'. Nó cũng làm cho đơn vị thử nghiệm dễ dàng hơn nhiều. – niaher