当我将一个可为空的整数分配给 ViewBag 时,它会使该值不可为空

本文关键字:ViewBag 整数 一个 分配 | 更新日期: 2023-09-27 17:55:39

考虑 ASP.NET MVC 5控制器:

public class MyController : Controller {
    public ActionResult Index(int? id) {
        ViewBag.MyInt = id;
        return View();
    }
}

而这个观点:

<p>MyInt.HasValue: @MyInt.HasValue</p>

当我调用 URL /my/(使用空 id)时,出现以下异常:

An exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Core.dll but was not handled in user code
Additional information: Cannot perform runtime binding on a null reference

相反,如果我传入一个 ID(例如,/my/1):

An exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Core.dll but was not handled in user code
Additional information: 'int' does not contain a definition for 'HasValue'

这在我看来,ViewBag.MyInt不是Nullable<int>型,而是intnull

这是ViewBag在做这件事吗?或者,像这样装箱 Nullable 类型是否更基本?或者,别的什么?

有没有其他方法可以做到这一点?

(我想我可以将我的支票更改为ViewBag.MyInt == null,但让我们假设我出于某种原因真的需要一个Nullable类型)

当我将一个可为空的整数分配给 ViewBag 时,它会使该值不可为空

我建议您创建一个视图模型,该模型将为您提供完全的灵活性,使"MyInt"成为可为空的类型。

当然,另一种选择是仅在不为空时才设置"MyInt"......

public class MyController : Controller {
    public ActionResult Index(int? id) {
        if (id.HasValue)
        {
            ViewBag.MyInt = id;
        }
        return View();
    }
}

视图:

@if (ViewBag.MyInt != null)
{
    <p>Has an Id</p>
}
else
{
    <p>Has no Id.</p>
}

就个人而言,我会使用视图模型作为最佳实践,我很少使用 ViewBag,除非它用于非常简单的场景。

我不确定原因,但您始终可以在视图中将其转换为可为空。

<p>MyInt.HasValue: @(((int?)MyInt).HasValue)</p>

虽然,这似乎有点矫枉过正。

ViewBag 是一个 DynamicViewDataDictionary 对象(参见 Robert Harvey 的回答和 ASP.NET 源代码)。

Nullable 是一种值类型,当您将其添加到 ViewBag 时,它会被装箱。请参阅有关 MSDN 的这篇文章,尤其是备注。根据同一篇文章,"当可为空的类型被装箱时,CLR 会自动装箱 Nullable 对象的基础值"......

可以安全地测试 ViewBag 属性的空值。如果它不为 null,则实际值是原始 Nullable 对象的基础类型的值。因此,此代码有效:

@if (ViewBag.MyInt != null)
{
    <p>@ViewBag.MyInt</p>
}

甚至这个:

<p>@ViewBag.MyInt</p>

如果未在 ViewBag 中设置 MyInt,则空值将呈现为空白。如果通过分配可为 Null 的值来设置它,则实际值为 int。