我有一个示例ASP.NET MVC 3 Web应用程序,它遵循Jonathan McCracken的Test-Drive Asp.NET MVC(顺便说一句好书),我偶然发现了一个问题。请注意,我正在使用MVCContrib,Rhino和NUnit。
[Test]
public void ShouldSetLoggedInUserToViewBag() {
var todoController = new TodoController();
var builder = new TestControllerBuilder();
builder.InitializeController(todoController);
builder.HttpContext.User = new GenericPrincipal(new GenericIdentity("John Doe"), null);
Assert.That(todoController.Index().AssertViewRendered().ViewData["UserName"], Is.EqualTo("John Doe"));
}
上面的代码总是抛出这个错误:
System.AccessViolationException:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。
控制器操作代码如下:
[HttpGet]
public ActionResult Index() {
ViewData.Model = Todo.ThingsToBeDone;
ViewBag.UserName = HttpContext.User.Identity.Name;
return View();
}
根据我的想法,由于控制器操作中的两个分配,应用程序似乎崩溃了。但是,我看不出有什么问题!?
任何人都可以帮我找出解决这个问题的方法。
谢谢。
修改1
我做了一些实验,看看问题是什么。
删除问题超出ViewData,Model
Expected result to be of type ViewResult. It is actually of type ViewResult.
分配时ViewData
。 [Test]
public void ShouldDisplayAListOfTodoItems() {
Assert.That(((ViewResult)new TodoController().Index()).ViewData.Model, Is.EqualTo(Todo.ThingsToBeDone));
}
赋值是如此基本以至于我认为不是问题因此我认为Rhino或MVCcontrib与MVC 3一起出现了问题。
我之前为同一控制器操作编写了以下测试:
System.NullReferenceException : Object reference not set to an instance of an object
这个问题现在失败了ViewBag
可能因为没有为此特定测试设置HttpContext。删除ViewData.Model
作业时,一切正常。
希望能让问题更加清晰。
修改2
在删除System.NullReferenceException : Object reference not set to an instance of an object.
分配后调试代码时,会在ViewBag
分配上引发其他错误:{{1}}。
答案 0 :(得分:5)
好吧,我把这个打倒了。正如我所怀疑的那样,这是因为MVCContrib。请注意,我使用的MVC 3 Beta尚未得到MVCContrib的正式支持。考虑到这一点,我已经下载了MVC 3分支的最新MVCContrib源。
转到MVCContrib Sources,切换到 mvc3 分支,下载并使用附加的bat构建二进制文件。然后,将所需文件包含在您的解决方案中。
嗯,这可能会在未来的稳定版本中修复,但我想这可能对其他人有用。感谢Darin的兴趣。
答案 1 :(得分:1)
这个怎么样:
[Test]
public void ShouldSetLoggedInUserToViewBag()
{
// arrange
var todoController = new TodoController();
var builder = new TestControllerBuilder();
builder.InitializeController(todoController);
builder.HttpContext
.Stub(x => x.User)
.Return(new GenericPrincipal(new GenericIdentity("John Doe"), null));
// act
var actual = todoController.Index();
// assert
actual.AssertViewRendered();
Assert.That(todoController.ViewData["UserName"], Is.EqualTo("John Doe"));
}
和控制器操作:
[HttpGet]
public ActionResult Index()
{
ViewBag.UserName = HttpContext.User.Identity.Name;
return View(Todo.ThingsToBeDone);
}
备注:我会将信息包含在视图模型中,并避免使用ViewData/ViewBag
。它不是强类型的,它会强制你使用魔术引号。