尝试读取或写入受保护的内存

时间:2011-01-01 23:09:48

标签: c#-4.0 nunit asp.net-mvc-3 rhino mvccontrib-testhelper

我有一个示例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}}。

2 个答案:

答案 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。它不是强类型的,它会强制你使用魔术引号。