ASP.NET MVC生命周期疑问:ActionFilter中Model为何为空?
为什么ActionFilter里的ViewData.Model是null?
嘿,我来帮你理清这个问题——你遇到的ViewData.Model为空的情况,其实是对ASP.NET MVC生命周期的一个常见小误解,咱们一步步拆解:
核心原因:模型绑定的目标不是ViewData.Model
你说得没错,模型绑定确实是在OnActionExecuting之前完成,但模型绑定是把请求数据绑定到Action方法的参数上,而不是直接赋值给ViewData.Model。ViewData.Model的赋值是在Action执行完成、返回ViewResult(比如你代码里的return View();)的时候才会发生的,这一步已经是OnActionExecuting之后的流程了。
在OnActionExecuting阶段,Action还没开始执行,ViewData里自然还没有模型数据,所以你拿到的就是null。
解决方案:从ActionArguments里获取绑定好的模型
既然模型已经绑定到Action的参数上了,咱们直接从ActionExecutingContext的ActionArguments集合里取就好,这才是正确的姿势:
public class CustomPermissionCheckAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext context) { // 从Action参数集合里获取绑定好的MyViewModel if (context.ActionArguments.TryGetValue("myViewModel", out var modelObj) && modelObj is MyViewModel vm) { // 现在vm就有值了,可以正常访问vm.OrganisationId做权限检查 var targetOrgId = vm.OrganisationId; // 你的权限验证逻辑写在这里 } base.OnActionExecuting(context); } }
小提示:
- 这里的
"myViewModel"要和你Action方法里的参数名完全一致(就是UpdateBranch(MyViewModel myViewModel)里的myViewModel)。 - 如果想让过滤器更通用,也可以遍历
ActionArguments找类型为MyViewModel的对象,不用硬写参数名:var vm = context.ActionArguments.Values.OfType<MyViewModel>().FirstOrDefault();
备选方案:用OnActionExecuted(不推荐用于权限检查)
如果一定要用ViewData.Model,可以把逻辑放到OnActionExecuted方法里——这个阶段Action已经执行完毕,模型已经被赋值到ViewResult中了:
public override void OnActionExecuted(ActionExecutedContext context) { // 先判断返回结果是不是ViewResult if (context.Result is ViewResult viewResult) { var vm = viewResult.Model as MyViewModel; if (vm != null) { // 这里可以访问vm,但注意:Action已经执行完了 } } base.OnActionExecuted(context); }
不过这种方法不适合你的权限检查场景,因为权限检查的目的是阻止无权限的Action执行,但OnActionExecuted是在Action执行完才触发的,这时候再拦截已经晚了。
内容的提问来源于stack exchange,提问作者Hooman Bahreini
相关产品推荐
相关产品推荐

