我想将自定义过滤器传递给控制器中的操作方法。 我试着像那样定义它。
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的System.RuntimeTypeHandle.CreateInstance(RuntimeType类型,Boolean publicOnly,Boolean noCheck,Boolean&amp; canBeCached,RuntimeMethodHandleInternal&amp; ctor,Boolean&amp; bNeedSecurityCheck)中(布尔值publicOnly,布尔值skipCheckThis,布尔fillCache,StackCrawlMark&amp; stackMark )System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly,Boolean skipCheckThis,Boolean fillCache,StackCrawlMark&amp; stackMark)System.Activator.CreateInstance(Type type,Boolean nonPublic)at System.Activator.CreateInstance(Type type)at System.Web.Mvc系统中System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext,ModelBindingContext bindingContext)的System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext,ModelBindingContext bindingContext)中的.DefaultModelBinder.CreateModel(ControllerContext controllerContext,ModelBindingContext bindingContext,Type modelType) .Web.Mvc.Contr System.Web.Mvc上System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext,String actionName)的System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext,ActionDescriptor actionDescriptor)中的ollerActionInvoker.GetParameterValue(ControllerContext controllerContext,ParameterDescriptor parameterDescriptor) System.Web.Mvc.MvcHandler上System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)的System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)中的.Controller.ExecuteCore() 。&lt;&gt; c_ DisplayClass6。&lt;&gt; c _DisplayClassb.b_ 5()在System.Web.Mvc.Async.AsyncResultWrapper。&lt;&gt; c _DisplayClass1 .b_ 0()在System.Web.Mvc.Async.AsyncResultWrapper。&lt;&gt; c _DisplayClass8
1.b__7(IAsyncResult _) at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult
1.End()在System.Web.Mvc.MvcHandler。&lt; System.Web.Mvc.SecurityUtil.ProcessInA上的System.Web.Mvc.SecurityUtil.b__0(操作f)中的&gt; c_ DisplayClasse.b _d() System.Web.HttpApplication.CallHandlerExecutionStep.System上的System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult结果)中的System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)中的pplicationTrust(Action action)。 System.Web.HttpApplication.ExecuteStep中的Web.HttpApplication.IExecutionStep.Execute()(IExecutionStep step,Boolean&amp; completedSynchronously)
事件是否可以做这样的事情?
如果没有通过委托,你能建议另一种方式吗?
答案 0 :(得分:2)
当我理解你的问题时,我会说这是不可能的。
ASP中的ASP.NET MVC操作方法是一种阻止映射http请求(url路由)的入口点,其中在接收到http请求后触发了Action方法。因此,该方法的输入参数实际上是将http或请求参数从http请求反序列化(或映射)到强类型对象的结果。当MVC框架创建对象时,它会查找无参数构造函数。它涉及参考类型的数据容器。
另一件事是通过http请求发送功能(逻辑)并将其映射到NET委托。由于NET是编译框架 - 而不是解释器 - 没有办法将.NET代码作为文本(例如C#代码)发送并将其映射到委托(例如,我们可以从Action方法返回javascript代码)。
如果即使可以在运行时编译.NET代码(有一些方法),最后还是可能会向Action方法注入.NET代码,这会导致安全问题。
答案 1 :(得分:0)
我不知道是否可以将一个委托传递给一个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() : "--") );
}
}
答案 2 :(得分:0)
绝对可以通过代表。 假设你有一个如下命令类
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);
}
}
我相信上面的代码为您提供了一个示例,您可以继续前进。
答案 3 :(得分:0)
虽然您尝试做的事情并非严格可行,但仍有办法做类似的事情。
我没有在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));
}
...
}