dotNET5的MVC页面传值方式总结

本文大致讲解mvc前后端的传值方式,包括control向view、view向control、以及action向action。

一.经典回顾

我们回顾下在ASP.NET WebForms中,页面之间最常用的传值方式,有以下几种:

  • a). QueryString(也叫URL传值)
  • b). Session
  • c). Cookie
  • d). Application
  • e). Server.Transfer

这里不再讲述这几种传值方式的用法和利弊,在本章后面将用MVC的传值方式与之对比,并展开一些探讨。(webform传值请看其他章节)

二、Controller向View传值

可以通过viewbag、viewdata、TempData、model。

1. ViewBag

1.png

用法:
在Controller中书写

ViewBag.Test123 = "Hello World.";

前台接收

@ViewBag.Test123

说明: ViewBag是dynamic动态类型,上面例子中的key => Test123可以指定任何类型

2. ViewData

2.png

用法:

在Controller中书写

ViewData["Test123"] = "Hello World. This is ViewData";

前台接收

@ViewData["Test123"]

说明:ViewData是字典类型,继承自IDictionary<string,object>接口

3. TempData

3.png

用法:

在Controller中书写

TempData["tmpData"] = "I am TempData...";

前台接收

@TempData["tmpData"]

说明:TempData也是字典类型,继承自IDictionary<string,object>接口

4. Model

这是初学者最常使用的传值方式。在上一篇文章中, 我们在Razor视图的页面代码中有这样一句:

@model IEnumerable<MVC5Demo.Models.UserInfoViewModel>

然后我们的信息列表是这样:

<tbody>
    @foreach (var item in Model) { 
    <tr>
        <td>@Html.DisplayFor(p => item.UserName)</td>
        <td>@(item.Sex == 0 ? "女" : "男")</td>
        <td>@Html.DisplayFor(p => item.Age)</td>
        <td>@Html.DisplayFor(p => item.Dept)</td>
        <td>@Html.ActionLink("编辑", "Edit", "UserInfo", new { id=item.UserID.ToString() },null) @Html.ActionLink("删除", "Delete", "UserInfo", new { id = item.UserID.ToString() }, new { onclick="return confirm('确认删除"+item.UserName+"的记录?');" })</td>
    </tr>
    }
</tbody>

如代码所示,因为我们的Model是一个泛型集合,这里就可以很方便的取出集合中的数据。

在后台Controller中,是怎么书写的呢?

public ActionResult Index()
        {
            return View("UserInfo", GetTestData());//GetTestData()返回泛型集合
        }

如代码所示,只需返回视图时,同时指定视图的数据对象。

三、View向Controller传值

1. 使用Html.BeginForm(...)方法提交表单

@using(Html.BeginForm("actionName","controllerName"))
    {
        <div>表单内容</div>
        <div>...</div>
        <input type="submit" value="提交表单" />
    }

说明:将 <form> 开始标记写入响应。在用户提交窗体时,将由某个操作方法(指定Controller的某个Action)处理该请求。

(使用using关闭form,下面不再说明。)

2. 使用Html.BeginRouteForm(...)方法提交表单

@Html.BeginRouteForm("路由名称", new { controller = "userinfo", action="save", userID = Model.UserID, userName = Model.UserName }, FormMethod.Post)
    {
        <div>表单内容</div>
        <div>...</div>
        <input type="submit" value="提交表单" />
    }

说明:同Html.BeginForm(),但使用路由方式提交表单,同时参数也不同。

3. 传统Form表单的Action属性提交

<form id="postForm" action="@Url.Action("Save")" method="post">
            <div>表单内容</div>
            <div>...</div>
            <input type="submit" value="提交表单" />
    </form>

说明:使用传统html form原生标记。

4. 使用Ajax方式提交表单, Ajax.BeginForm(...)

@Ajax.BeginForm("actionName", new AjaxOptions { Url="",OnSuccess="",HttpMethod="get" })
    {
        <div>表单内容</div>
        <div>...</div>
        <input type="submit" value="提交表单" />
    }

说明:使用异步方式提交form表单。

5. Jquery和Ajax提交表单

省略... 不在文章讨论范围。

6. 表单参数传递

6.1 全参数传递

[HttpPost]
public ActionResult Save(string username,int sex,int age,string dept)

说明:html标签name和参数名需相同。

6.2 实体传参

[HttpPost]
public ActionResult Save(UserInfoViewModel item)

说明:页面使用@model绑定类型

6.3 表单集合传参

[HttpPost]
public ActionResult Save(FormCollection fc)

说明:需解析FormCollection,如:

UserInfoViewModel userInfo = new UserInfoViewModel();
TryUpdateModel<UserInfoViewModel>(userInfo, fc);

6.4 传统方式

使用HttpContext,在MVC中我们同样可以使用以下对象:

Application,Server,Session,Request,Response,Cache ...

四、Controller向Controller传值(Action之间传值)

1. RedirectToAction

1.1 传递实体对象

public ActionResult Index()
        {
            return RedirectToAction("Index", "Home", new UserInfoViewModel { UserID = Guid.NewGuid(), UserName = "zhangsan", Sex = 1, Age = 20, Dept = "hr" });
        }

说明:在UserInfoController中,在页面加载时,新建一个实体类型,并跳转至首页。

接收:

public class HomeController : Controller
    {
        public ActionResult Index(UserInfoViewModel model)
        {
            //处理model的值
            //...

1.2 传递普通参数

public ActionResult Index()
        {
            return RedirectToAction("Index", "Home", new { UserID = Guid.NewGuid(), UserName = "zhangsan"});
        }

接收:

public class HomeController : Controller
    {
        public ActionResult Index(string userID,string userName)
        {
            //处理userID, userName的值
            //...
  1. TempData
TempData["userName"] = "zhangsan";
            return RedirectToAction("Index2");

在Index2中接收:

string userName = TempData["userName"].ToString();

说明:TempData可以在同Controller中不同Action之间传递,并且具有‘一次访问’的特质。使用时要特别注意。

五、与WebForms传值的对比

  1. 后台不能通过非提交方式获取某个页面元素的值,因为没有‘服务器控件’;MVC使用原生Http,是【无状态】的。

  2. 不能使用(也没有)ViewState。

  3. 使用特有的机制传值(ViewData,ViewBag...等等)。

六、MVC 向页面传值方式总结

总结发现ASP.NET MVC中Controller向View传值的方式共有6种,分别是:

  • ViewBag
  • ViewData
  • TempData
  • 向普通View页面传一个Model对象
  • 向强类型页面传传一个Model对象
  • 用一个ViewModel对象解决所有问题

首先我们需要明确的是我们从controller向view传值的时候,这些方式分别处于什么样的地位:

我们一般会向页面传递一个主要的类型的数据,一般是情况下是一个List<Model>,如果只有这个,很好办,一个model对象就解决了,但是往往除此之外还会有一些额外的零散的数据需要传递,比如分页的pageIndex,或者pageCount等等,这样的数据用原有的model就无能为力了,这时候,我们就可以用ViewBag、ViewData、TempData来传递这些额外的数据。

视图数据可以通过ViewBag属性访问,它主要是为了从Controller到view进行传值用的,类似有所使用的ViewData[] 字典类。对于ViewBag是如此的强大,意味着你能动态的set/get 值,增加任何数量的的额外字段而不需要强类型的检测。如:

control控制器

public 
ActionResult Index()

{

List<string>
 colors = new 
List<string>();

colors.Add("red");

colors.Add("green");

colors.Add("blue");




ViewData["listColors"]
 = colors;

ViewData["dateNow"]
 = DateTime.Now;

ViewData["name"]
 = "Hajan";

ViewData["age"]
 = 25;



return 
View();

control 控制器

public 
ActionResult Index()

{

List<string>
 colors = new 
List<string>();

colors.Add("red");

colors.Add("green");

colors.Add("blue");



ViewBag.ListColors = colors;
//colors
 is List

ViewBag.DateNow
 = DateTime.Now;

ViewBag.Name
 = "Hajan";

ViewBag.Age
 = 25;

return 
View(); 

}

你和上面的对比 你看见了不同吗?

View
对应前台视图:

1.使用ViewData

<p>
My name is <b>@ViewData["name"] </b>,
<b>
<br />
I like the following colors:
</p>
<ul id="colors">
@foreach (var color in ViewData["listColors"] as List<string>)
{
<li><font color="@color">@color </font></li>
}
</ul>
<p>
@ViewData["dateNow"]
</p>

2.使用ViewBag

<p>
My name is < b>@ViewBag.Name</b>, <b>@ViewBag.Age</b> years old.
<br />
I like the following colors:
</p>
<ul id="colors">
@foreach (var color in ViewBag.ListColors)
{
<li><font color="@color">@color</font> </li>
}
</ul>
<p>
@ViewBag.DateNow
</p>

ViewBag、ViewData 和 TempData 的区别:

ViewData 和 TempData 都可以传递弱类型数据,区别如下:

  • ViewData 只在当前 Action 中有效,生命周期和 View 相同;
  • TempData 的数据至多只能经过一次Controller传递,并且每个元素至多只能被访问一次,访问以后,自动被删除。
    -TempData 一般用于临时的缓存内容或抛出错误页面时传递错误信息,可以将TempData 在使用之前存储到相应的 ViewData 中以备循环使用。

ViewBag

我们可以认为 ViewBag=ViewData+Dynamic wrapper around the ViewData ,接下来你就可以体会到这个公式的含义了。

1、conroller向view传值


4.png

2、view向view传值:

5.png

3、利用ViewBag传递一个对象:

6.png

ViewData

1、ViewData的基本用法

111.png

2、ViewData 转换成 ViewBag:

222.png

3、ViewBag 转换成 ViewData:

333.png

TempData

TempData用于在Redirect的时候保存数据,ViewData、ViewBag在跳转后就会变成null,但是TempData不会,下面是TempData的用法示例:

public ActionResult Index()
{
  var model = new Review()
            {
                Body = "Start",
                Rating=5
            };
    TempData["ModelName"] = model;
    return RedirectToAction("About");
}
<pre><pre lang="cs">public ActionResult About()
{
    var model= TempData["ModelName"];
    return View(model);
}

普通页面传递model:

//Action代码
public ActionResult Index()
{
  Product p = new Product();
  p.Name = "Toy";
  return View(p);
}

在View中调用的代码:

Product : <%: ((Product)Model).Name %>

向强类型试图传递model

1、WebForm Engine的试图的实现:

//Aciton的代码
public ActionResult Index()
{
  Product p = new Product();
  p.Name = "Toy";
  return View(p);
}

View中的代码
声明类型

<%@ Page Inherits="System.Web.Mvc.ViewPage<Product>" %>

直接用Model调用该对象

<h2> Product Name: <%: Model.Name %> </h2>

2、Razor Engine的实现:

在Razor中声明类型的方式:

@model Mvc3App.Models.Product

在Razor中调用对象的方式:

<h2> Product: @Model.Name </h2>
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,723评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,003评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,512评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,825评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,874评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,841评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,812评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,582评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,033评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,309评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,450评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,158评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,789评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,409评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,609评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,440评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,357评论 2 352

推荐阅读更多精彩内容