APS.NET MVC + EF (04)---路由和数据传递

4.1 视图引擎

ASP.NET MVC 提供两种视图引擎:ASPX(C#)和Razor(CSHTML),推荐使用Razor。

4.1.1 Razor的语法

在Razor视图中,所有的服务器端代码都是围绕@展开的,下面介绍@使用的各种语法形式和应用情况。

  1. @( expression) 或 @ expression

    @是Razor中的一个重要符号,它被定义为Razor服务器代码块的开始符号。例如,我们可以在View中直接写C#代码输出日期


<p> @Datetime.Now.ToStirng()</p>

@(expression)一般可以吧"()"省略,但这只限于@后紧邻变量或对象的情况,如果后面是常数,则必须加"()",如下面的用法。

@("razor视图".ToString() )

如果去掉()则不能正常解析。

  1. 语句块

    在Razor视图引擎中,我们可以使用@{code}来定义一段代码块。并支持与HTML代码混写。如下面代码所示。


@{

var stu = new RazorDemo.Models.Student();

stu.StudentName = "王五";

stu.Gender = "男";

<p>姓名:@stu.StudentName</p>

<p>性别:@stu.Gender</p>

}

@foreach (var stu in students)

{

<p>姓名:@stu.StudentName</p>

<p>性别:@stu.Gender</p>

}

@if (stu.Gender == "男")

{

<p>姓名:@stu.StudentName</p>

<p>性别:@stu.Gender</p>

}

  1. 输出特殊字符

    如果要输出"@"符号,可以使用"@@"进行转义,如:


<p>@@2013 copy right</p>

[email protected]@.com

  1. 引用命名空间

@using RazorDemo.Models

  1. 注释

@* 被注释的内容 *@

4.1.2 布局页

Razor的布局有助于使应用程序中的多个视图保持一致外观。如果熟悉WebForm的话,其中母版页和布局的作用基本上是相同的,但是布局提供了更加简洁的语法和更强大的灵活性。

可以使用布局为网站定义公共模板(或只是其中的一部分)。公共模板包含一个或多个占位符,应用程序中的其他视图为他们提供内容。从某些角度来看,布局很像视图的抽象基类。

下面来看一个简单的布局。这里称这个布局文件为SiteLayout.cshtml


<!DOCTYPE html>

<html>

<head>

<meta name="viewport" content="width=device-width" />

<title>@ViewBag.Title</title>

</head>

<body>

<div id="main-content">

@RenderBody() <!--占位符-->

</div>

</body>

</html>

它看起来很像一个标准的Razor视图,但需要注意的是在视图中由一个@RenderBody调用。这是一个占位符,用来标记使用这个布局的视图将渲染他们的主要内容的位置。多个Razor视图现在可以利用这个布局来显示一致的外观。

接下来看一个使用这个布局的例子Index.cshtml 。


@{

ViewBag.Title = "Index";

Layout = "~/Views/Shared/SiteLayout.cshtml";

}

<h2>这是主页内容</h2>

上面这个视图通过Layout属性来指定布局页面。当渲染这个视图时,它的HTML内容将被放在SiteLayout.cshtml中的id属性为main-content的div元素中,最后生成的html页面如下。


<!DOCTYPE html>

<html>

<head>

<meta name="viewport" content="width=device-width" />

<title>Index</title>

</head>

<body>

<div id="main-content">

<h2>这是主页内容</h2>

</div>

</body>

</html>

注意视图内容,其中标题和内容都是视图提供的,除此以外都是布局提供的。

在一个布局页中只允许有一个@RenderBody()占位符如果需要多个占位符,可以使用@RenderSection( ) 方法来完成例如再SiteLayout.cshtml页面上添加一个页脚占位符。


<!DOCTYPE html>

<html>

<head>

<meta name="viewport" content="width=device-width" />

<title>@ViewBag.Title</title>

</head>

<body>

<div id="main-content">

@RenderBody()

</div>

<footer>

@RenderSection("Footer")

</footer>

</body>

</html>

在不做任何改变的情况下再次运行前面的视图,将会抛出一个异常,提示没有定义Footer。默认情况下,视图必须为布局中定义的每一个占位符section提供相应的内容。

更新后的Index.cshtml 。


@{

ViewBag.Title = "Index";

Layout = "~/Views/Shared/SiteLayout.cshtml";

}

<h2>这是主页内容</h2>

@section Footer

{

this is the <strong>这是底部</strong>

}

@RenderSection( )方法有一个重载,第二个参数是bool类型,指明该Section是否为必须的。所以可以在使用该RenderSection方法的时候直接利用第二个重载,再把bool参数值设为false,即使你在具体的View中没有声明实现@section,运行起来也不会报错了。

在项目中,如果每个页面都使用布局页,那么就必须在每个内容页中都要使用 Layout 进行声明,这就形成了代码冗余。

_ViewStart.cshtml页面可以用来消除这种冗余。这个文件中的代码先于同目录下任何视图代码的执行。这个文件也可以递归地应用到子目录下的任何视图。

当创建一个默认的ASP.NET MVC项目时,你将会注意到Views目录下会自动添加一个_ViewStart.cshtml文件,它指定了一个默认布局。


@{

Layout = "~/Views/Shared/_Layout.cshtml";

}

这样在内容页中就不用再指定 Layout 了。

4.2 路由

4.2.1 为什么需要路由

在前面的内容中,我们已经初步接触了路由的定义代码,示例1所示代码能将"/Home/Index/0"、/Home/Index"、/Home"、"/"多种形式的URL指向同一个页面。

示例1


routes.MapRoute(

"Default", // 路由名称

"{controller}/{action}/{id}", // 带有参数的URL

new { controller = "Home", action = "Index", id = UrlParameter.Optional }

// 参数默认值

);

在系统中使用路由的好处有两点。

  1. 屏蔽物理路径,提高安全性
  2. 有利于搜索引擎的优化

4.2.2 路由规则

示例1中,MapRoute()中URL的参数值是"{controller}/{action}/{id}",称之为URL模式。该模式是一种字符串,包括一些固定的字符字面量和占位符,占位符由一对{}表示,其语法为:

字面量{占位符}字面量{占位符}字面量…{占位符}字面量

在上述语法中字面量可能是一个固定的字符,比较常见的是"/",也可能是一个字符串,如"Users"。占位符也是一个字符或字符串。

表4-1 URL模式匹配示例


序号


URL模式


匹配的URL示例


1


{controller}/{action}/{id}


/books/Edit/1,/Books/Detail/2


2


{first}/{second}/{third}


/books/Edit/1,/Books/Detail/2


3


{table}/Detail.aspx


/Users/Detail.aspx, /Books/Detail.aspx


4


Blog/{action}/{id}


/Blog/Show/1001, /Blog/delete/1001


5


{language}-{country}/{action}


/zh-cn/display, /en-us/list

注意事项:

  • URL模式匹配不区分大小写。
  • 两个占位符之间不能连续。
  • "/"和一般的字面量相比,是比较特殊的。
  • 不能以"/"或"~"字符开头,不能包含"?"。

除了上面一些规则为,还有一些特殊的模式。

(1) * 匹配

* 用来匹配剩余部分。如URL模式"{controller}/{action}/{query}/{*plus}"匹配的URL,产生的部分路由数据如表4-2所示。


序号


路由模式


路由数据


1


/home/index/select/a/b


Key=plus, Value= a/b


2


/home/index/select/a/b/c


Key=plus, Value= a/b/c


3


/home/index/select/


Key=plus, Value=

(2) 贪婪匹配

例如URL模式: {filename}.{ext}

如果匹配"/food.xml.aspx",则会产生路由数据如下:

filename= food.xml, ext=aspx

所谓贪婪匹配就是,在模式匹配过程中,寻找字面量时不是找到第一个后就放弃,而是贪婪的寻找到最有一个为止。

(3) 默认值

路由可以有默认值的,如示例1中指定的默认值。如果没有默认值,只能使用诸如"book/eidt/0"这样的地址去匹配,使用时非常不方便。

在使用路由默认值时要注意以下两点。

  • 只提供中间参数的默认值不起作用。

    如只提供 action="index", 则"/home/0"不匹配,只能是"/home/index/0"

  • 包含字面量时默认值不起作用("/"除外)

    如:对于模式{controller}-{action},提供默认值action="index", 则"/home-"不能匹配,只能使用 /home-index

(4) 路由约束

可以给路由参数增加正则表达式约束,如示例2所示。


routes.MapRoute(

"Default", // 路由名称

"{year}/{month}/{day}", // 带有参数的URL

new { controller = "Home", action = "Index", id =

UrlParameter.Optional } , // 参数默认值

constraints: new { [email protected]"\d{4}", [email protected]"\d{2}",

[email protected]"\d{2}" }

);

(5)多个路由

如果有多组路由时,排在最前面的优先匹配。

4.2.3 路由数据

RouteData对象用来保存URL模式和实际URL匹配产生的路由数据,这些路由数据以键-值对的形式保存。如:

表4-2 URL模式匹配示例


序号


URL模式


匹配的URL示例


路由数据


1


{controller}/{action}/{id}


/books/Edit/1,

/Books/Detail/2


Key=Controller,Value=Books

Key=action,Value=Edit

Key=id,value=1


2


{first}/{second}/{third}


/books/Edit/1,

/Books/Detail/2


Key=first,Value=Books

Key=second,Value=Edit

Key=third,value=1


3


{table}/Detail.aspx


/Users/Detail.aspx,


Key=table, value=Users


4


Blog/{action}/{id}


/Blog/Show/1001


Key=action, value=show

Key=id, value=1001


5


{language}-{country}/{action}


/zh-cn/display,


Key=language, value=zh

Key=country,value=cn

Key=action, value=display

可以使用如下代码在动作方法中读取路由中的值:

string id = RouteData.Values[ "id" ] ;

在视图中可以使用下面的方式:

<span>@RouteData.Values[ "id" ]

在使用时注意验证是否为null。

4.3 数据传递---从控制器到视图

在ASP.NET MVC中,使用RouteData对象可以方便的获取URL中的参数值。同样,也提供了若干对象可以从控制器向视图传递数据。

4.3.1 ViewData对象

ViewData是一种字典集合数据,同时属于视图基类和控制器基类的属性。常见的用法是在控制器中写入数据,在视图中读取数据。如示例2所示。

示例2


//控制器代码

public class HomeController : Controller

{

public ActionResult Index()

{

ViewData["data"] = "Hello,MVC!";

return View();

}

}

//视图代码

<h1>@ViewData["data"]</h1>

注意:ViewData 的 Value 是 Object 类型。

4.3.2 ViewBag对象

ViewBag是 dynamic 类型的对象,同时属于视图基类和控制器基类的属性,用法如示例3所示。

示例3


//控制器代码

public class HomeController : Controller

{

public ActionResult Index()

{

ViewBag.data = "Hello,MVC!";

return View();

}

}

//视图代码

<h1>@ViewBag.data</h1>

本质上,ViewBag是对ViewData数据的包装,也就是说两个对象中的数据是可以相互读取的。

4.3.3 TempData对象

TempData的用法和ViewData用法相似,但和ViewData保存的数据互不干扰。如示例4所示。

示例4


//控制器代码

public class HomeController : Controller

{

public ActionResult Index()

{

TempData["data"] = "Hello,MVC!";

return View();

}

}

//视图代码

<h1>@TempData["data"]</h1>

在实际开发中,TempData主要用来跨请求传递数据,也就是说跨越动作方法传递数据,如示例5所示。

示例5


//控制器代码

public class HomeController : Controller

{

public ActionResult Index()

{

TempData["data"] = "来自Index()的数据";

Response.Redirect("~/Home/Detail");

return View();

}

public ActionResult Detail()

{

return View();

}

<!-- Detail.cshtml 视图代码 -->

<h1>@TempData["data"]</h1>

需要注意的是,如果TempData中的数据被使用过(从视图中输出),就会被清除。如果没有被使用过,那么它保存的时间和Session相同。

4.3.4 强类型视图

在使用ViewBag 向视图传递数据时,有一个明显的缺陷就是在使用时要做数据类型转换。有一种更好的方式就是使用强类型视图。在添加视图的时候,在向导对话框中选择"Empty模板",如图4-1所示,并选择模型类。这样创建完成的视图基类就变成了 System.Web.Mvc.ViewPage<T>。

图4-1 创建强类型视图

如果使用强类型视图,则在控制器中传递数据的方式变成直接使用 View()的一个带"model"的参数的重载方法。在视图中可以直接通过模型类的属性使用传递的数据。如示例6所示。

示例6


//动作方法中的代码

Book book = manager.GetBookById(id);

return View(book);

//视图中的代码

<div>

作者: @Model.Author 著 <br />

出版社:@Model. Publisher.Name

</div>

4.4 案例:实现带搜索条件和分页的列表展示

原文地址:https://www.cnblogs.com/mrfang/p/10770214.html

时间: 2024-08-28 16:11:42

APS.NET MVC + EF (04)---路由和数据传递的相关文章

mvc中的几个数据传递

1.ViewData对象 ViewBagData是一种字典集合数据同时属于视图基类和控制器基类的属性. 实例: //控制器 public class HomeController:Controller { public ActionResult Index() { ViewData["data"]="Hello asp.net"; return View(); } } 视图: <h1><%=ViewData["data"]%&g

spring mvc+ajax 实现json格式数据传递

使用ajax传递JSON对象 下面示例为ajax发送json对象,返回json格式数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 $.ajax({ url: "api/user", type: "POST", timeout: txnTimeOut, async: true, dataType: "json", data: {username : "lucy"}

路由和数据传递

一.请求从路由开始        1.为什么需要路由?            (1).屏蔽物理路径.提高安全性            (2).有利于搜索引擎优化        2.定义路由的规则            (1).基于模式匹配的路由规则                语法:{占位符1}字面量1{占位符2}字面量2...{占位符n}...字面量n                                注:字面量可能是一个固定的字符,比较常见的是"/",也可以是一个字符

Asp.Net Mvc 控制器与视图的数据传递

数据传递也就是控制器和视图之间的交互,比如在视图中提交的数据,在控制器怎么获取,或者控制器从业务层获得一些数据,怎么传递到视图中,让视图显示在客户端呢?带着这些疑问,我们接着看..        下面分别讲解asp.net mvc框架中有三种数据传递方式,分别是:ViewData,TempData,Model         ViewData:只能在一个动作方法中设置,在相关视图页面读取,说得再白一点就是只能在一个页面中使用.         例 在Act ion方法中设置:ViewData["

APS.NET MVC + EF (03)---初始MVC

3.1 MVC简介 MVC(Model-View-Controller,模型—视图—控制器模式)用于表示一种软件架构模式.它把软件系统分为三个基本部分:模型(Model),视图(View)和控制器(Controller).Asp.net MVC是微软提供的MVC开发框架. MVC将UI层分为了三个部分: 模型:一组类,描述了要处理的数据以及修改和操作数据的业务规则. 视图:定义应用程序界面的显示方式. 控制类:一组类,用于处理来自用户.整个应用程序流以及特定应用程序逻辑的通信. 3.2 第一个A

APS.NET MVC + EF (00)---C#基础

命名参数 命名参数是把参数附上参数名称,这样在调用方法的时候不必按照原来的参数顺序填写参数,只需要对应好参数的名称也能完成方法调用. static void Main(string[] args) { Console.WriteLine(ShowComputer("i3 370M","2G","320G")); Console.WriteLine(ShowComputer(disk: "320G", cpu: "i3

APS.NET MVC + EF (06)---模型

在实际开发中,模型往往被划分为视图模型和业务模型两部分,视图模型靠近视图,业务模型靠近业务,但是在具体编码上,它们之间并不是隔离的. 6.1 视图模型和业务模型 模型大多数时候都是用来传递数据的.然而即使在传递数据这一点上,也可以看出,视图需要的模型更加灵活一点,因为视图变化性更大,而处理业务的模型更加稳定一些.因此,在实际开发中,往往有视图模型和业务模型的区分.在实际开发中,为了体现逻辑的分离,往往是视图模型和业务模型分别定义. 例如,在传统三层开发中,我们定义的实体类,可以看作是业务模型的定

APS.NET MVC + EF (01)---Linq和Lambda表达式

1.1 Linq介绍 LINQ全称 Language Integrated Query(语言集成查询).为我们提供一种统一的方式来查询和操作各种数据. LINQ to Object:是针对实现了IEnumerable<T>的对象的LINQ: LINQ to SQL:是针对关系数据库的LINQ: LINQ to XML:是针对XML文档的LINQ. LINQ除了提供一个统一的API来操作各种数据,并且为我们提供了编译时类型检查和动态创建查询表达式的能力. LINQ查询时有两种语法可供选择:查询表

mvc EF 数据保存时,报错:”对一个或多个实体的验证失败……“之解决

在EF5.0添加实体数据到数据库的时候,出现“对一个或多个实体的验证失败.有关详细信息,请参见“EntityValidationErrors”属性这个错误 解决: SaveChanges前先关闭验证实体有效性(ValidateOnSaveEnabled)这个开关 db.Configuration.ValidateOnSaveEnabled = false; int count = db.SaveChanges(); db.Configuration.ValidateOnSaveEnabled =