谈谈ASP.NET CORE MVC中视图的数据的弱类型绑定(ViewData与ViewBag)

 

前言

本文主要讲解如何正确使用 ViewData与ViewBag,以及他们之间的使用场景。首先需要知道,向视图中传递数据(从控制器中或者模型中)有两种类型:强类型弱类型

  • 强类型数据:viewmodel(安全,官方推荐)
  • 弱类型数据
    • ViewData (ViewDataAttribute)
    • ViewBag

使用 viewmodel 将数据传递给视图可让视图充分利用强类型检查。 强类型化(或强类型)意味着每个变量和常量都有明确定义的类型(例如 stringint 或 DateTime)。 在编译时检查视图中使用的类型是否有效。

Visual Studio 和 Visual Studio Code 列出了使用 IntelliSense 功能的强类型类成员。 如果要查看 viewmodel 的属性,请键入 viewmodel 的变量名称,后跟句点 (.)。 这有助于提高编写代码的速度并降低错误率

可随意对 viewmodel 类型和业务模型类型使用相同的类。 但是,使用单独的模型可使视图独立于应用的业务逻辑和数据访问部分。 模型为用户发送给应用的数据使用模型绑定验证时,模型和 viewmodel 的分离也会提供安全优势

弱类型数据

除了强类型视图,视图还可以访问弱类型(也称为松散类型)的数据集合。 与强类型不同,弱类型(或松散类型)意味着不显式声明要使用的数据类型。 可以使用弱类型数据集合将少量数据传入及传出控制器和视图。

传递数据于...示例
控制器和视图用数据填充下拉列表。
视图和布局视图从视图文件设置布局视图中的 < title>元素内容。
分部视图和视图基于用户请求的网页显示数据的小组件

 

可以通过控制器和视图上的 ViewData 或 ViewBag 属性来引用此集合。 ViewData 属性是弱类型对象的字典。 ViewBag 属性是 ViewData 的包装器,为基础 ViewData 集合提供动态属性。 注意:对于 ViewData 和 ViewBag,键查找都不区分大小写。

ViewData 和 ViewBag 在运行时进行动态解析。 由于它们不提供编译时类型检查,因此使用这两者通常比使用 viewmodel 更容易出错。 出于上述原因,一些开发者希望尽量减少或根本不使用 ViewData 和 ViewBag

ViewData

ViewData 是通过 string 键访问的 ViewDataDictionary 对象。 字符串数据可以直接存储和使用,而不需要强制转换,但是在提取其他 ViewData 对象值时必须将其强制转换为特定类型。 可以使用 ViewData 将数据从控制器传递到视图,以及在视图(包括分部视图布局)内传递数据。

以下是在操作中使用 ViewData 设置问候语和地址值的示例:

public IActionResult SomeAction()
{
    ViewData["Greeting"] = "Hello";
    ViewData["Address"]  = new Address()
    {
        Name = "Steve",
        Street = "123 Main St",
        City = "Hudson",
        State = "OH",
        PostalCode = "44236"
    };

    return View();
}

在视图中处理数据

@{
    // Since Address isn't a string, it requires a cast.
    var address = ViewData["Address"] as Address;
}

@ViewData["Greeting"] World!

<address>
    @address.Name<br>
    @address.Street<br>
    @address.City, @address.State @address.PostalCode
</address>

ViewData 特性

另一种会使用 ViewDataDictionary 的方法是 ViewDataAttribute。 控制器或 Razor 页面模型上使用 [ViewData] 属性的属性将其值存储在字典中并从中进行加载。

在下面的示例中,“主页”控制器包含使用 [ViewData] 标记的 Title 属性。 About 方法设置“关于”视图的标题:

public class HomeController : Controller
{
    [ViewData]
    public string Title { get; set; }

    public IActionResult About()
    {
        Title = "About Us";
        ViewData["Message"] = "Your application description page.";

        return View();
    }
}

在“关于”视图中,以模型属性的形式访问 Title 属性:

<h1>@Model.Title</h1>

在布局中,从 ViewData 字典读取标题:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>@ViewData["Title"] - WebApplication</title>
    ...

ViewBag

ViewBag在 Razor Pages 中不可用。

ViewBag 是 DynamicViewData 对象,可提供对存储在 ViewData 中的对象的动态访问。 ViewBag 不需要强制转换,因此使用起来更加方便。 下例演示如何使用与上述 ViewData 有相同结果的 ViewBag

public IActionResult SomeAction()
{
    ViewBag.Greeting = "Hello";
    ViewBag.Address  = new Address()
    {
        Name = "Steve",
        Street = "123 Main St",
        City = "Hudson",
        State = "OH",
        PostalCode = "44236"
    };

    return View();
}

 

@ViewBag.Greeting World!

<address>
    @ViewBag.Address.Name<br>
    @ViewBag.Address.Street<br>
    @ViewBag.Address.City, @ViewBag.Address.State @ViewBag.Address.PostalCode
</address>

同时使用 ViewData 和 ViewBag

ViewBag在 Razor Pages 中不可用。

由于 ViewData 和 ViewBag 引用相同的基础 ViewData 集合,因此在读取和写入值时,可以同时使用 ViewData 和 ViewBag,并在两者之间进行混合和匹配。

在 About.cshtml 视图顶部,使用 ViewBag 设置标题并使用 ViewData 设置说明

@{
    Layout = "/Views/Shared/_Layout.cshtml";
    ViewBag.Title = "About Contoso";
    ViewData["Description"] = "Let us tell you about Contoso's philosophy and mission.";
}

读取属性,但反向使用 ViewData 和 ViewBag。 在 _Layout.cshtml 文件中,使用 ViewData 获取标题并使用 ViewBag 获取说明

<!DOCTYPE html>
<html lang="en">
<head>
    <title>@ViewData["Title"]</title>
    <meta name="description" content="@ViewBag.Description">
    ...

 

请记住,字符串不需要为 ViewData 进行强制转换。 可以使用 @ViewData["Title"] 而不需要强制转换。

可同时使用 ViewData 和 ViewBag也可混合和匹配读取及写入属性。 呈现以下标记:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>About Contoso</title>
    <meta name="description" content="Let us tell you about Contoso's philosophy and mission.">
    ...

差异

ViewBag 在 Razor 页中不可用。

  • ViewData
    • 派生自 ViewDataDictionary,因此它有可用的字典属性,如 ContainsKeyAddRemove 和 Clear
    • 字典中的键是字符串,因此允许有空格。 예: ViewData["Some Key With Whitespace"]
    • 任何非 string 类型均须在视图中进行强制转换才能使用 ViewData
  • ViewBag
    • 派生自 DynamicViewData,因此它可使用点表示法 (@ViewBag.SomeKey = <value or object>) 创建动态属性,且无需强制转换。 ViewBag 的语法使添加到控制器和视图的速度更快。(其实差不多)
    • 更易于检查 NULL 值。 예: @ViewBag.Person?.Name

何时使用 ViewData 或 ViewBag

ViewData 和 ViewBag 都是在控制器和视图之间传递少量数据的有效方法。 根据偏好选择使用哪种方法。 可以混合和匹配 ViewData 和 ViewBag 对象,但是,使用一致的方法可以更轻松地读取和维护代码。 这两种方法都是在运行时进行动态解析的,因此容易造成运行时错误。 因而,一些开发团队会避免使用它们。

建议

在控制器和视图之间传递少量数据时,比如排序时的排序字符串,可使用ViewData 。一些简单的处理逻辑用弱类型还是方便的

参考文献:https://docs.microsoft.com/zh-cn/aspnet/core/mvc/views/overview?view=aspnetcore-2.2

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值