TryUpdateModel 在 ASP.NET MVC 3 单元测试中抛出 NullReferenceException
由于我从 MVC 2 升级到 MVC 3 RC,因此使用 TryUpdateModel 会导致 NullReferenceException。仅当将我的操作方法作为单元测试的一部分运行时,才会出现此问题。在实际服务器上运行它可以按预期工作。
这是异常的堆栈跟踪:
System.NullReferenceException:对象 未设置对实例的引用 目的。在 System.Web.Mvc.JsonValueProviderFactory.GetValueProvider(ControllerContext 控制器上下文)在 System.Web.Mvc.ValueProviderFactoryCollection.<>c_DisplayClassc.b_7(ValueProviderFactory 工厂)在 System.Linq.Enumerable.WhereSelectEnumerableIterator
2.MoveNext() 在 System.Linq.Enumerable.WhereSelectEnumerableIterator
2.MoveNext() 在 System.Collections.Generic.List1..ctor(IEnumerable
1 集合)在 System.Linq.Enumerable.ToList[TSource](IEnumerable`1 来源)在 System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext 控制器上下文)在 System.Web.Mvc.Controller.TryUpdateModel[TModel](TModel 型号,字符串前缀)
...我自己的代码从这里开始...
万一重要的话,我的控制器具有以下签名:
[AcceptVerbs(HttpVerbs.Post)]
public virtual ActionResult Edit(int id, FormCollection collection)
{
}
我的猜测是这与 MVC3 中 DI 工作的新方式有关,但我不知道是什么我做错了。也许 MVC 3 中需要 DI 设置,但 MVC 2 中不需要?
Since I upgraded from MVC 2 to MVC 3 RC, using TryUpdateModel causes a NullReferenceException. This problem only occurs when running my action method as part of a unit test. Running it on the actual server works as expected.
Here's a stack trace of the exception:
System.NullReferenceException: Object
reference not set to an instance of an
object. at
System.Web.Mvc.JsonValueProviderFactory.GetValueProvider(ControllerContext
controllerContext) at
System.Web.Mvc.ValueProviderFactoryCollection.<>c_DisplayClassc.b_7(ValueProviderFactory
factory) at
System.Linq.Enumerable.WhereSelectEnumerableIterator2.MoveNext()
2.MoveNext()
at
System.Linq.Enumerable.WhereSelectEnumerableIterator
at
System.Collections.Generic.List1..ctor(IEnumerable
1
collection) at
System.Linq.Enumerable.ToList[TSource](IEnumerable`1
source) at
System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext
controllerContext) at
System.Web.Mvc.Controller.TryUpdateModel[TModel](TModel
model, String prefix)
... my own code from here on....
In case it matters, my controller has the following signature:
[AcceptVerbs(HttpVerbs.Post)]
public virtual ActionResult Edit(int id, FormCollection collection)
{
}
My guess is that this has to do with the new way DI works in MVC3, but I can't figure out what I'm doing wrong. Perhaps there is something in terms of DI setup that is required in MVC 3, but wasn't required in MVC 2?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您应该添加此代码:
我有同样的问题,此代码对我有帮助。
You should add this code:
I have the same problem and this code helps me.
如果其他人有同样的问题并找到这篇文章:
我根据 Ivan Kortym 的答案一般性地解决了问题(谢谢!),在我的控制器基类构造函数中使用以下代码:
In case someone else has the same problem and finds this post:
I solved the problem generically based on Ivan Kortym's answer (thanks!), with the following piece of code in my controller base class constructor:
这可能是
System.Web.Mvc.JsonValueProviderFactory.GetValueProvider
的实现发生了变化,导致ControllerContext
中的值为 null。您可能需要在
ControllerContext
中模拟附加值。至少那是我首先看的地方。
编辑
是的,看起来它正在对
controllerContext
进行空检查。从堆栈跟踪中我们可以看到
TryUpdateModel[TModel](TModel model, String prefix)
。使用反射器,它正在访问ControllerBase
ValueProvider
属性。这又会使用当前控制器ControllerContext
属性调用ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext)
。您应该能够创建一个新的
ControllerContext
实例并相应地设置控制器的属性...不过,可能需要一些额外的模拟才能使其完全发挥作用。有关如何完全模拟 ControllerContext 的一些信息:模拟 Asp.net-mvc 控制器上下文
It's probably a change in implementation of
System.Web.Mvc.JsonValueProviderFactory.GetValueProvider
that is hitting a value inControllerContext
that is null.You may need to mock an additional value in
ControllerContext
.At least that's where I'd look first.
EDIT
Yeah, looks like it's doing a null check on
controllerContext
.From the stacktrace we can see that
TryUpdateModel[TModel](TModel model, String prefix)
. Using reflector, it is accessing theControllerBase
ValueProvider
property. This in turn callsValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext)
with the current ControllersControllerContext
property.You should just be able to create a new
ControllerContext
instance and set the controller's property accordingly...Some additional mocking may be required to get it to fully function though. Some info on how to fully mock ControllerContext: Mocking Asp.net-mvc Controller Context