完整了解asp.net core MVC中的数据传递

在ASP.NET Core MVC应用开发中,数据传递是构建高效、可靠Web应用的核心环节之一。它涵盖了从控制器到视图、不同请求之间以及与外部数据源交互等多个方面。正确掌握各种数据传递方式对于开发出性能优良、用户体验良好的应用程序至关重要。本文将全面深入地探讨ASP.NET Core MVC中常见的数据传递方式,包括通过视图模型(ViewModel)、ViewData、ViewBag、临时数据(TempData)、缓存(Cache)、会话(Session),以及在控制器之间传递数据的方法。同时,会详细说明这些方式与ControllerBase的关系,并通过丰富的代码示例阐述其功能和应用场景。

文章目录

    • 一、视图模型(ViewModel)传递数据
      • 1. 概念与原理
      • 2. 代码示例与应用场景
    • 二、ViewData与ViewBag
      • 1. 概念与特点
      • 2. 两者关系及与`ControllerBase`的关系
      • 3. 代码示例与应用场景
    • 三、TempData
      • 1. 功能与特点
      • 2. 与`ControllerBase`的关系
      • 3. 代码示例与应用场景
    • 四、缓存(Cache)
      • 1. 缓存的概念与配置
      • 2. 代码示例与应用场景
    • 五、会话(Session)
      • 1. 会话的特点与工作原理
      • 2. 代码示例与应用场景
    • 六、在控制器之间传递数据
      • 1. 使用TempData在控制器之间传递数据
      • 2. 通过路由参数传递数据
      • 3. 使用共享服务或单例模式传递数据

一、视图模型(ViewModel)传递数据

1. 概念与原理

视图模型是专为视图设计的数据结构,用于在控制器与视图之间传递数据。它能将与特定视图相关的数据和逻辑进行封装,可包含一个或多个模型对象的属性,还可添加仅用于视图展示的额外属性,如页面标题、控制视图显示的布尔值等。其目的是提供清晰、类型安全的方式来传递数据,确保视图代码更易于理解和维护。

2. 代码示例与应用场景

以博客系统为例,Post是文章模型,Comment是评论模型。在展示文章详情页面时,需要文章信息及相关评论列表,此时可创建PostViewModel视图模型来封装数据。

// 文章模型
public class Post
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
}

// 评论模型
public class Comment
{
    public int Id { get; set; }
    public int PostId { get; set; }
    public string Text { get; set; }
}

// 文章详情视图模型
public class PostViewModel
{
    public Post Post { get; set; }
    public List<Comment> Comments { get; set; }
    public string PageTitle { get; set; }
}

// 控制器中的操作方法
public class PostController : Controller
{
    public IActionResult Details(int postId)
    {
        var post = _postService.GetPostById(postId);
        var comments = _commentService.GetCommentsByPostId(postId);
        var viewModel = new PostViewModel
        {
            Post = post,
            Comments = comments,
            PageTitle = $"文章详情 - {post.Title}"
        };
        return View(viewModel);
    }
}

在视图中,可通过强类型方式访问视图模型属性:

@model PostViewModel

<h1>@Model.PageTitle</h1>
<p>@Model.Post.Content</p>

<ul>
    @foreach (var comment in Model.Comments)
    {
        <li>@comment.Text</li>
    }
</ul>

应用场景:适用于视图需要展示多个相关模型数据或需对数据进行特定组合与处理的情况,提供了类型安全和清晰的结构。

二、ViewData与ViewBag

1. 概念与特点

  • ViewData:是ControllerBase的属性,类型为ViewDataDictionary,即字典结构(IDictionary<string, object>)。用于在控制器向视图传递数据,以键值对形式存储,数据生命周期在当前请求的视图渲染期间。其优点是简单直接,但作为弱类型字典,编译时无法进行类型检查,可能导致视图中使用数据时出现运行时错误。
  • ViewBag:是ViewData的动态包装器,利用动态属性方式访问数据,如ViewBag.PropertyName,使代码在视图中更简洁。不过,和ViewData一样,编译时不进行类型检查,存在运行时类型不匹配风险。

2. 两者关系及与ControllerBase的关系

ViewBag基于ViewData实现,在ControllerBase中,ViewData直接作为属性存在,ViewBag通过动态属性访问方式对ViewData进行包装。当使用ViewBag设置或获取数据时,实际是在操作ViewData字典中的对应键值对。它们是ControllerBase提供给控制器向视图传递数据的机制。
换句话说ViewBag的访问方式比ViewData更优雅一些,更符合对象编程的手法。

3. 代码示例与应用场景

  • 示例代码
    • 控制器中设置数据
public class HomeController : Controller
{
    public IActionResult Index()
    {
        // 使用ViewData传递数据
        ViewData["Message"] = "这是一条消息 using ViewData";
        // 使用ViewBag传递数据
        ViewBag.Title = "首页 using ViewBag";
        return View();
    }
}
- **视图中获取数据(Index.cshtml)**:
@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
</head>
<body>
    <p>Message from ViewData: @ViewData["Message"]</p>
    <p>Title from ViewBag: @ViewBag.Title</p>
</body>
</html>
  • 应用场景:适用于传递少量简单、临时数据,如页面标题、提示信息等,数据类型无需编译时严格检查且数据量小、逻辑简单时使用。

三、TempData

1. 功能与特点

TempData也是ControllerBase的属性,用于不同请求间(特别是重定向场景)传递数据。以键值对形式存储,具有一次性读取特性,数据读取一次后标记为删除(下次请求读取为null),可通过Keep方法保留数据以便后续请求使用。

2. 与ControllerBase的关系

TempDataControllerBase提供的在请求间传递临时数据的方式,在控制器操作方法执行中发挥作用。控制器可利用它在不同请求间传递需后续使用但不长期存储的数据,如表单提交重定向后的操作结果或临时消息。

3. 代码示例与应用场景

  • 示例代码
    • 登录控制器
public class LoginController : Controller
{
    public IActionResult Login(LoginViewModel model)
    {
        if (ModelState.IsValid)
        {
            // 假设登录验证成功
            TempData["SuccessMessage"] = "登录成功!";
            return RedirectToAction("Index", "Home");
        }
        return View(model);
    }
}
- **首页控制器**:
public class HomeController : Controller
{
    public IActionResult Index()
    {
        var message = TempData["SuccessMessage"];
        if (message!= null)
        {
            ViewBag.Message = message;
            // 保留数据以便后续使用(例如在页面刷新时仍然显示消息)
            TempData.Keep("SuccessMessage");
        }
        return View();
    }
}
  • 应用场景:常用于重定向后传递操作结果或临时消息给目标页面,如用户注册、登录、表单提交等操作成功或失败后的提示信息。

四、缓存(Cache)

1. 缓存的概念与配置

缓存用于存储频繁访问但不常变化的数据,以提高应用性能。ASP.NET Core提供多种缓存机制,如内存缓存(IMemoryCache)。在Startup.cs中通过AddMemoryCache方法注册服务,并在需要处通过依赖注入使用。

2. 代码示例与应用场景

以产品列表页面为例,产品数据若相对稳定,可缓存提高性能。

  • 配置缓存服务(在Startup.cs中)
public void ConfigureServices(IServiceCollection services)
{
    services.AddMemoryCache();
    // 其他服务配置...
}
  • 控制器中使用缓存
public class ProductController : Controller
{
    private readonly IMemoryCache _memoryCache;
    private readonly IProductRepository _productRepository;

    public ProductController(IMemoryCache memoryCache, IProductRepository productRepository)
    {
        _memoryCache = memoryCache;
        _productRepository = productRepository;
    }

    public IActionResult Index()
    {
        if (!_memoryCache.TryGetValue("ProductList", out List<Product> products))
        {
            products = _productRepository.GetAllProducts();
            var cacheEntryOptions = new MemoryCacheEntryOptions()
             .SetSlidingExpiration(TimeSpan.FromMinutes(10));
            _memoryCache.Set("ProductList", products, cacheEntryOptions);
        }
        return View(products);
    }
}

应用场景:适用于存储频繁访问但不常变化的数据,如网站配置信息、下拉菜单选项、常用字典数据等,以及计算成本高或查询耗时操作的结果。

五、会话(Session)

1. 会话的特点与工作原理

会话用于在用户多个请求间存储和共享数据。数据存储在服务器端,会话标识(通常通过Cookie)存于客户端识别用户会话。每个用户有独立会话数据,在整个用户会话期间有效。

2. 代码示例与应用场景

如购物车应用,可使用会话存储用户购物车商品信息。

  • 配置会话服务(在Startup.cs中)
public void ConfigureServices(IServiceCollection services)
{
    services.AddSession(options =>
    {
        options.IdleTimeout = TimeSpan.FromMinutes(30);
        options.Cookie.HttpOnly = true;
        options.Cookie.IsEssential = true;
    });
    // 其他服务配置...
}
  • 启用会话中间件(在Configure方法中)
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // 其他中间件配置...
    app.UseSession();
    // 更多中间件配置...
}
  • 控制器中使用会话
public class CartController : Controller
{
    private readonly ISession _session;

    public CartController(ISession session)
    {
        _session = session;
    }

    public IActionResult AddToCart(int productId)
    {
        var cart = _session.GetObjectFromJson<List<int>>("Cart")?? new List<int>();
        cart.Add(productId);
        _session.SetObjectAsJson("Cart", cart);
        return RedirectToAction("Index");
    }

    public IActionResult Index()
    {
        var cart = _session.GetObjectFromJson<List<int>>("Cart");
        var productsInCart = _productRepository.GetProductsByIds(cart);
        return View(productsInCart);
    }
}

应用场景:常用于存储用户相关状态信息,如登录状态、购物车内容、用户偏好设置等,跨页面共享和维护的数据。

六、在控制器之间传递数据

1. 使用TempData在控制器之间传递数据

TempData可用于控制器间传递数据,尤其在重定向场景。例如,注册成功后将消息传递给另一个控制器显示。

  • 注册控制器
public class RegistrationController : Controller
{
    public IActionResult Register(RegistrationViewModel model)
    {
        if (ModelState.IsValid)
        {
            // 假设注册成功
            TempData["RegistrationSuccessMessage"] = "注册成功!";
            return RedirectToAction("Welcome", "WelcomeController");
        }
        return View(model);
    }
}
  • 欢迎控制器
public class WelcomeController : Controller
{
    public IActionResult Welcome()
    {
        var message = TempData["RegistrationSuccessMessage"];
        if (message!= null)
        {
            ViewBag.Message = message;
        }
        return View();
    }
}

2. 通过路由参数传递数据

在重定向或链接到其他控制器操作时,可将数据作为路由参数传递。如订单完成后,将订单ID传递给订单详情控制器。

  • 订单控制器
public class OrderController : Controller
{
    public IActionResult CompleteOrder(int orderId)
    {
        // 假设订单处理完成
        return RedirectToAction("Details", "OrderDetailsController", new { orderId = orderId });
    }
}
  • 订单详情控制器
public class OrderDetailsController : Controller
{
    public IActionResult Details(int orderId)
    {
        var order = _orderService.GetOrderById(orderId);
        return View(order);
    }
}

3. 使用共享服务或单例模式传递数据

创建共享服务(如DataService)或使用单例模式可在控制器间共享数据。例如:

  • 定义共享服务
public class DataService
{
    private List<string> _dataList = new List<string>();

    public void AddData(string data)
    {
        _dataList.Add(data);
    }

    public List<string> GetData()
    {
        return _dataList;
    }
}
  • 注册服务为单例(在Startup.cs中)
public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<DataService>();
    // 其他服务配置...
}
  • 控制器使用共享服务
public class ControllerA : Controller
{
    private readonly DataService _dataService;

    public ControllerA(DataService dataService)
    {
        _dataService = dataService;
    }

    public IActionResult AddData(string data)
    {
        _dataService.AddData(data);
        return RedirectToAction("GetData", "ControllerB");
    }
}

public class ControllerB : Controller
{
    private readonly DataService _dataService;

    public ControllerB(DataService dataService)
    {
        _dataService = dataService;
    }

    public IActionResult GetData()
    {
        var dataList = _dataService.GetData();
        return View(dataList);
    }
}

通过以上多种方式,在ASP.NET Core MVC中可实现灵活的数据传递。在实际应用中,需根据数据性质、安全性、性能需求等因素综合选择合适方式,确保数据在控制器、视图及不同请求间有效传递和共享,构建出功能强大、性能优化的Web应用程序。

希望我这篇博文对你理解ASP.NET Core MVC中的数据传递有所帮助,如感兴趣请继续关注博客。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/905025.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Couldn‘t apply path mapping to the remote file.

Couldn’t apply path mapping to the remote file. /s6home2/zjw524/projects/seq2seq/code/deepnmtpycharm/deepNmt/code/deepNmtPycharm/deepNmt/model/Deep_NMT_Model.py can’t be found in project. You can continue debugging, but without the source. To fix that yo…

4.2-6 使用Hadoop WebUI

文章目录 1. 查看HDFS集群状态1.1 端口号说明1.2 用主机名访问1.3 主节点状态1.4 用IP地址访问1.5 查看数据节点 2. 操作HDFS文件系统2.1 查看HDFS文件系统2.2 在HDFS上创建目录2.3 上传文件到HDFS2.4 删除HDFS文件和目录 3. 查看YARN集群状态4. 实战总结 1. 查看HDFS集群状态 …

嵌入式硬件电子电路设计(一)开关电源Buck电路

目录 Buck电路基本结构 1. 开关闭合&#xff08;SW 闭合&#xff09; 2. 开关断开&#xff08;SW 断开&#xff09; 3. 开关控制和占空比 MP1584电路分析 其他Buck芯片的电路参考 Buck电路基本结构 下图是简化之后的BUCK电路主回路。下面分析输出电压的产生K闭合后&…

医院信息化与智能化系统(14)

医院信息化与智能化系统(14) 这里只描述对应过程&#xff0c;和可能遇到的问题及解决办法以及对应的参考链接&#xff0c;并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图&#xff0c;可以试试PlantUML&#xff0c;告诉GPT你的文件结构&#xff0c;让他给你对应…

Unity 使用Netcode实现用户登录和登出

Unity之NetCode for GameObjets 基本使用 说明思路相关API代码实现Tips 说明 最近项目需要联机&#xff0c;项目方案选用Unity提供的NetCode for GameObjets&#xff08;以下简称NGO&#xff09;&#xff0c;踩了不少坑&#xff0c;本文不介绍基础使用&#xff0c;围绕双端&am…

【单机游戏】红色警戒游戏介绍和玩法

平地一声惊雷&#xff0c;金将军居然发射了洲际导弹&#xff0c;虽然我们不能亲自体验&#xff0c;但是我们可以自己在游戏中体验一把&#xff0c;今天就介绍一个很多80 90都玩过的即时战略游戏-红色警戒 https://pan.quark.cn/s/7aca45fa3dd7 红色警戒&#xff08;Red Alert …

【Python各个击破】matplotlib

导入 import matplotlib.pyplot as plt import numpy as np用法 # 根据x,y数组作图 fig, ax plt.subplots() ax.plot([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,…

JavaEE初阶---网络原理之TCP篇(二)

文章目录 1.断开连接--四次挥手1.1 TCP状态1.2四次挥手的过程1.3time_wait等待1.4三次四次的总结 2.前段时间总结3.滑动窗口---传输效率机制3.1原理分析3.2丢包的处理3.3快速重传 4.流量控制---接收方安全机制4.1流量控制思路4.2剩余空间大小4.3探测包的机制 5.拥塞控制---考虑…

ssm022房屋租售网站的设计与实现+jsp(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;房屋租售网站的设计与实现 摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为…

Knife4j配置 ▎使用 ▎教程 ▎实例

knife4j简介 支持 API 自动生成同步的在线文档:使用 Swagger 后可以直接通过代码生成文档,不再需要自己手动编写接口文档了,对程序员来说非常方便,可以节约写文档的时间去学习新技术。 提供 Web 页面在线测试 API:光有文档还不够,Swagger 生成的文档还支持在线测试.参数和格式都…

CSS flex布局- 最后一个元素占满剩余可用高度转载

效果图 技术要点 height父元素必须有一个设定的高度flex-grow: 1 flex 盒子模型内的该元素将会占据父容器中剩余的空间F12检查最后一行的元素&#xff0c;高度就已经改变了&#xff1b;

虚拟环境设置成kernel来解决一些jupyter报错问题

1. 下面提到的问题应该是不同环境&#xff08;base、虚拟环境&#xff09;的区别&#xff0c;而不是python版本的区别。 2. 这个方法起到了比较好的效果&#xff0c;但是底层的逻辑还没太明白&#xff0c;有时间继续研究下。 3. 最终的结果好像是pycharm、anaconda用的python…

(五)Web前端开发进阶2——AJAX

目录 1.Ajax概述 2.Axios库 3.认识URL 4.Axios常用请求方法 5.HTTP协议——请求报文/响应报文 6.前后端分离开发 7.Element组件库 1.Ajax概述 AJAX 是异步的 JavaScript和XML(Asynchronous JavaScript And XML)。简单点说&#xff0c;就是使用XMLHttpRequest 对象与服务…

揭秘PyInstaller:Python应用打包的瑞士军刀

文章目录 **揭秘PyInstaller&#xff1a;Python应用打包的瑞士军刀**1. 背景介绍&#xff1a;为何选择PyInstaller&#xff1f;2. PyInstaller究竟是什么&#xff1f;3. 如何安装PyInstaller&#xff1f;4. PyInstaller的简单使用方法4.1 打包单个Python脚本4.2 生成单个可执行…

Spring Boot 创建项目详细介绍

上篇文章简单介绍了 Spring Boot&#xff08;Spring Boot 详细简介&#xff01;&#xff09;&#xff0c;还没看到的读者&#xff0c;建议看看。 下面&#xff0c;介绍一下如何创建一个 Spring Boot 项目&#xff0c;以及自动生成的目录文件作用。 Maven 构建项目 访问 http…

机器学习——解释性AI(Explainable AI)

机器学习——解释性AI&#xff08;Explainable AI&#xff09; 解释性AI&#xff08;Explainable AI&#xff09;——让机器学习模型更加透明与可信什么是解释性AI&#xff1f;解释性AI的常见方法示例代码&#xff1a;使用SHAP解释随机森林模型示例代码&#xff1a;使用LIME解释…

开源一款基于 JAVA 的仓库管理系统,支持三方物流和厂内物流,包含 PDA 和 WEB 端的源码

大家好&#xff0c;我是一颗甜苞谷&#xff0c;今天分享一款基于 JAVA 的仓库管理系统,支持三方物流和厂内物流,包含 PDA 和 WEB 端的源码。 前言 在当前的物流仓储行业&#xff0c;企业面临着信息化升级的迫切需求&#xff0c;但往往受限于高昂的软件采购和维护成本。现有的…

Tomcat servlet response关于中文乱码的经验

前言 最近修改老项目项目&#xff0c;使用zuul网关返回的中文内容乱码了&#xff0c;如果使用GBK或者GB2312编码确正常显示&#xff0c;稍微实验了一下&#xff0c;发现里面很多细节&#xff0c;毕竟Springboot对我们做了很多事情&#xff0c;而且当我们使用不同的模式会出现很…

【原创分享】详述中间件的前世今生

中间件是一种软件组件&#xff0c;位于应用程序和操作系统之间&#xff0c;通过提供统一的接口和功能来简化开发和管理应用程序、提高应用程序的可靠性和性能。 中间件的前世可以追溯到20世纪80年代的分布式系统和网络技术的发展。在那个时候&#xff0c;随着计算机网络的普及…

JAVA力扣每日一题:P198. 打家劫舍

本题来自&#xff1a;力扣-每日一题 力扣 (LeetCode) 全球极客挚爱的技术成长平台https://leetcode.cn/ 题解&#xff1a; class Solution {public int rob(int[] nums) {int len nums.length;if(len 0)return 0;if(len 1)return nums[0];int first nums[0];int second …