Asp.net mvc ASP.NET MVC将对象从自定义操作筛选器传递到操作

Asp.net mvc ASP.NET MVC将对象从自定义操作筛选器传递到操作,asp.net-mvc,filter,custom-action,Asp.net Mvc,Filter,Custom Action,如果我在ASP.NET MVC中的自定义操作筛选器中创建对象 public override void OnActionExecuting(ActionExecutingContext filterContext) { DetachedCriteria criteria = DetachedCriteria.For<Person>(); criteria.Add("stuff"); // Now I need to access 'criteria' fro

如果我在ASP.NET MVC中的自定义操作筛选器中创建对象

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

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

}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
DetachedCriteria=DetachedCriteria.For();
标准。添加(“材料”);
//现在我需要从操作中访问“标准”。。。。。
}

是否有任何方法可以从当前正在执行的操作访问对象。

您可以使用
HttpContext

filterContext.HttpContext.Items["criteria"] = criteria;
你可以在行动中读到:

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

在ViewData或viewmodel中设置项(如果将其作为参数传递到操作中)。 这里我设置了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;
}
以下是我认为您更喜欢的非类型版本:

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

    }

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

我建议将其放在路线数据中

    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();
    }
这是由菲尔·哈克描述的

基本上你就是这么做的:

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");
    }
}
唯一的问题是,如果您正在创建对象参数,那么您的类(在本例中为Person)必须有一个默认构造函数,否则您将得到一个异常

以下是如何使用上述过滤器:

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

一件物品在RouteData中可以保存多久?我只需要在当前执行的操作期间保留对象,或者最多在当前请求期间保留对象,如果路由数据是这样工作的,那么这就是答案,否则HttpContext。Items可能更好。RouteData是与当前执行的路由(操作)相关的数据。将其视为一个容器,表示根据您的路由规则解析和映射的请求url。
RouteData
当然非常适合这样做,正如我今天学到的,感谢您的回答。我面前的这本漂亮的黑白MVC书(第四版)在关于过滤器的整个章节中都没有提到它或做任何类似的事情(或者至少我还没有找到它?)。不管怎样,+1,谢谢你<代码>filterContext.ControllerContext.RoutedData.Values.Add(“键”,值)正在为我工作!:)我正在考虑使用HttpContext.Items[],这是一个可以接受的解决方案,因为它将在请求结束时被清除。我不确定是否有一个地方可以储存只在活动期间存在的东西。谢谢你的建议。不过,我的操作并没有将ViewModelBase作为参数,我不希望引入它只是为了解决我的问题。有关非类型化版本,请参阅编辑的文章。我仍然会使用第一个版本。也许参数名听起来很糟糕。它可以是任何类,而不必是类型化视图的类。这样做非常好,我肯定认为这比公认的答案要好得多。这应该是公认的答案!谢谢为什么这比公认的答案更好?似乎没有理由会出现这种情况,而且额外的[AddActionParameter]显然是其他方法不需要的额外工作。@ChrisBertrand它更干净,通过使用强类型,即-
Person
class,避免了控制器中的编译时错误。这种方法的唯一问题是,当你试图做这件事的时候,同时又在写一篇文章。通过将其添加到操作参数中,它将参与模型验证,最终可能出现发布的数据有效,但
ModelState.IsValid
仍然为false的奇怪情况,这不是一个很好的解决方案,因为现在你的api可以接受这些参数作为QueryString,这是一个意外的副作用。更糟糕的是,如果您有像swagger这样的文档库,它会显示这些参数是URL的查询参数,而这些参数完全是供内部使用的。