在APS.NET MVC5及其之前,我们可以在控制器的构造函数里设置​​ViewBag.Test="test text"​​。然后在对应Action的View里使用就行了。

public class HomeController : Controller
{
public HomeController()
{
ViewBag.Test = "this is test";
}
public ActionResult Index()
{

return View();
}
}

Index.cshtml:

@{
ViewBag.Title = "Home Page";
}

<div class="jumbotron">
<h1>@ViewBag.Test</h1>

</div>

但是在ASP.NET MVC Core(MVC6)里有些区别,当仍然这么用的时候,会抛出一个空引用的异常:

NullReferenceException: Object reference not set to an instance of an object.。调试的时候你会发现在View里ViewBag.Test为null。看下Controller的源码(​​这里​​)我们知道,ViewBag实际依赖的是ViewData,而ViewData在Controller构造结束才是真正可用的。

对于ViewData微软是这么说的:


By default, this property is initialized when IControllerActivator activates controllers.
This property can be accessed after the controller has been activated, for example, in a controller action or by overriding Microsoft.AspNetCore.Mvc.Controller.OnActionExecuting(Microsoft.AspNetCore.Mvc.Filters.ActionExecutingContext).
This property can be also accessed from within a unit test where it is initialized with Microsoft.AspNetCore.Mvc.ModelBinding.EmptyModelMetadataProvider.


虽然在构造函数中设置ViewData不会返回空引用异常,但是构造结束之后,新创建的ViewData会将旧ViewData对象给替换到,所以就拿不到之前设置的值了。另外在控制器的构造函数中,不应出现任何与修改状态或者当前请求有关的逻辑。

如果你在Controller构造时确实需要做些操作的话,可以尝试下是否可以迁移到Filter的OnActionExecuting方法中。