【问题标题】:Is it possible to pass a delegate to a controller action?是否可以将委托传递给控制器​​操作?
【发布时间】:2013-03-28 05:35:11
【问题描述】:

我想将自定义过滤器传递给控制器​​中的操作方法。 我试着这样定义它。

public ActionResult GetResult(Func<Fault,bool> filter)
{
    List<Fault> faultList;
    using (var _context = new myDB())
    {
        faultList = 
            from f in _context.Faults
            where filter(f)
            select f;
    }
    return Json(faultList);
}

但是当我运行该操作时,我得到一个错误

没有为此对象定义无参数构造函数。

在 System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark & stackMark) at System.RuntimeType. RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) at System.Activator.CreateInstance(Type type, Boolean nonPublic) at System.Activator.CreateInstance(Type type) at System.Web.Mvc.DefaultModelBinder.CreateModel(在 System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 在 System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 在 System.Web.Mvc 的 ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)。 ControllerActionInvoker.G etParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) 在 System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) 在 System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) 在 System.Web.Mvc.Controller .ExecuteCore() 在 System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) 在 System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) 在 System.Web.Mvc.MvcHandler。c_DisplayClass6.c_DisplayClassb.b_5() 在 System.Web.Mvc.Async.AsyncResultWrapper.c_DisplayClass1.b_0()在 System.Web.Mvc.Async.AsyncResultWrapper.c_DisplayClass81.b__7(IAsyncResult _) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult1.End() 在 System.Web.Mvc.MvcHandler.c_DisplayClasse.b_d () 在 System.Web.Mvc.SecurityUtil.b__0(Action f) 在 System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) 在 System.We b.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) 在 System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult 结果) 在 System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute( ) 在 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

有没有可能做这样的事情?

如果不是通过委托,你能建议另一种方式吗?

【问题讨论】:

  • 您向此操作发送什么数据?您如何期望Func&lt;Fault,bool&gt; filter 创建的表格中的数据?
  • 我在想@Html.Action("GetResults",new {filter = (f=> f.TypeID == 1) }) 之类的东西...

标签: c# asp.net-mvc linq delegates controller


【解决方案1】:

据我了解你的问题,我想说这是不可能的。

Controller 中的 ASP NET MVC Action 方法是一种针对映射 http 请求(url 路由)的入口点,其中 Action 方法在收到 http 请求后被触发。因此,该方法的输入参数实际上是将 http 请求中的 Post 或 Get 参数反序列化(或映射)到强类型对象的结果。当 MVC 框架创建对象时,它会寻找无参数构造函数。它与引用类型的数据容器有关。

另一件事是通过 http 请求发送功能(逻辑)并将其映射到 NET 委托。由于 NET 是编译框架而不是解释器,因此无法将 NET 代码作为文本发送(例如 C# 代码)并将其映射到委托(例如,我们可以从 Action 方法返回 javascript 代码)。

最后一件事,即使可以在运行时编译 NET 代码(有一些方法),将 NET 代码注入 Action 方法的可能性也会导致安全问题。

【讨论】:

    【解决方案2】:

    我不知道是否可以将委托传递给 Action,但我有一个替代方案的建议。您可以将参数传递给操作,并根据该值将适当的函数分配给 filter 委托。

    这是一个示例控制台应用程序来说明我的想法:

    public enum Cases { Case1, Case2, Case3 };
    
    class Program
    {
        private static bool Test1(int test) { return test == 1; }
    
        private static bool Test2(int test) { return test == 2; }
    
        private static bool Test3(int test) { return test == 3; }
    
        public static void Main()
        {
            RunTest(Cases.Case1);
            RunTest(Cases.Case2);
            RunTest(Cases.Case3);
    
            Console.ReadLine();
        }
    
    
        private static void RunTest(Cases testCase)
        {
            var list = new List<int> {1, 2, 3};
            Func<int, bool> del;
    
            switch (testCase)
            {
                case Cases.Case1:
                    del = Test1;
                    break;
                case Cases.Case2:
                    del = Test2;
                    break;
                case Cases.Case3:
                    del = Test3;
                    break;
                default:
                    throw new InvalidDataException();
            }
    
            list.ForEach( i => Console.WriteLine(del(i) ? i.ToString() : "--")  );
        }
    }
    

    【讨论】:

    • 这不会削减它,因为我必须将过滤策略传递给我的控制器,而且您的回答没有解释错误消息。
    【解决方案3】:

    绝对可以通过委托。 假设您有一个如下所示的命令类

    public class MyCommand<T>{
    
    Action myAction;
    Func<T, bool> canExecute;
    
    public MyCommand(Action<T> actionToBeExecuted, Func<T, bool> canExecute)
    {
    this.myAction = actionToBeExecuted;
    this.canExecute = canExecute;
    }
    
    public void ExecuteMyCommand<T>(T param)
    {
    if(this.canExecute(param))
       this.myAction(param);
    }
    }
    

    我相信上面的代码给了你一个例子,你可以朝着这个方向前进。

    【讨论】:

    • 对不起,但这并不能帮助我解决我在 MVC 中遇到的困难我知道可以通过委托我只是不明白为什么 MVC 会给我一个错误。
    【解决方案4】:

    虽然您尝试做的事情在严格意义上是不可能的,但有一些方法可以做类似的事情。

    我不是在 HTTP 请求中从用户那里传递 Func,而是在我的代码中将 Func 用作测试和其他目的的接缝。我遇到了同样的问题,但通过重载具有不同参数的方法来解决它。

    这是我所拥有的:

    public class SomeController : Controller
    {
        [HttpGet]
        public ActionResult SomeAction(string q, Func<string, SomeResultType> fn = null) 
        {
            fn = fn ?? SomeDefaultFn;
            ...
    
            return View(...);
        }
    }
    

    由于@Bronek 在他的回答中所说的原因,这不起作用。但是,由于无论如何我都想提供一个默认值,所以只需重载我的方法签名即可。

    public class SomeController : Controller
    {
       [HttpGet]
       public Action SomeAction(string q)
       {
           // mvc will execute this action and pass
           // my default off to the next method
           return SomeAction(q, SomeDefaultFn);
       }
    
       public ActionResult SomeAction(string q, Func<string, SomeResultType> fn)
       {
            ...
            return View(...);
       }
    }
    

    在另一个地方,我有类似以下内容:

    public class SomeController : Controller
    { 
        [HttpGet]
        public ActionResult SomeAction(string q, string filterType)
        {
            return SomeAction(q, FilterFactory.Build(filterType));
        }
    
        ...
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-27
      • 2018-05-07
      • 1970-01-01
      相关资源
      最近更新 更多