现在的位置: 首页 > 综合 > 正文

ASP.NET MVC Razor 视图引擎

2016年09月15日 ⁄ 综合 ⁄ 共 7544字 ⁄ 字号 评论关闭

. 使用 @ 字符将代码添加到页面中。正如传统的aspx视图的<% %>相同。
    下面代码是介绍单语句块、内嵌代码块、多行语句块

复制代码
 1 <!-- 简单块 声明两个变量-->
 2 @{int num = 10;}
 3 @{string str = "hello cnblogs";}
 4 <!-- 内联表达式 输入刚才声明的两个变量-->
 5 <p>刚才声明的整形的值为: @num</p>
 6 <p>刚才声明的字符型的值为: @str</p>
 7 
 8 <!-- 多声明代码块 -->
 9 @{
10     string strHello = "您好,我叫李亮";
11     string now = DateTime.Now.ToString();
12     string sayHello = strHello + "当前时间为:" + now;
13  }
14  <p>问好: @sayHello</p>
复制代码

运行效果如下:

   如果我要是在输出的文本中加入html标记呢?

string sayHello = strHello + "<b>当前时间为:</b>" + now;

     和上面的代码唯一不同的是在“当前时间为:”几个字的首尾加了<b></b>,大家都知道b标记是加粗文本显示的,那么好咱先看下运行结果。

    运行结果为

   “问好:您好,我叫李亮<b>当前时间为</b>:2012-5-25 18:03:21”

     和想象的不一样哎,没关系!到这咱得引入一个新的概念html编码。asp.net为了安全考虑会默认的把诸如<  > . @ 等等特殊的字符编码。为什么要这么干就是为了防止SSH跨站脚本攻击,您感兴趣的话可以搜一下有关跨站脚本攻击的知识,今天本文的重点不是讲它。从浏览器的html源中可以看出,那源是什么呢?

     <p>问好: 您好,我叫李亮&lt;b&gt;当前时间为&lt;/b&gt;2012-5-26 18:25:49</p>

     可以很明显的看出<b>被编码成&lt;b&gt;  <b/>被编码成&lt;/b&gt; 因此呈现在页面中就是刚才那个结果了。

问题来了,结果办法呢??再往下看

 

 <p>问好: @Html.Raw(sayHello)</p>

 

@Html.Raw()  防止自动编码^^^^^^^

2. 代码和标记混合

 

 @for (int i = 0; i <= 10; i++) { 
    <span>第 @i 行<br /></span>
 }

 

运行结果:

      大家有没有发现一个问题:就是在第和数字以及数字和行字之间必须有空格,这是因为@字符前面是空字符的时候编译器才能识别@符号后面的代码是C#代码,同理C#完事后也必须跟的是空字符,否则就本例而言它就默认识别为@i行 既 i行这个变量(因为编译器找不到这个变量所以报错。) O(∩_∩)O~。那如果我非得输出没有空格的字符串怎么办呢?告诉您非常好吧只需要一对括弧就搞定。

 @for (int i = 0; i <= 10; i++) { 
    <span>第@(i)行<br /></span>
 }

     运行结果自己猜吧!如果您这也猜不到的话,(*^__^*) 嘻嘻…… 不说了 - -/

3.代码与纯文本混合

复制代码
 <p>第一种方式</p>
 @if (true) { 
    <text>这里是if语句内部-1</text>
 }
 <p>第二种方式</p>
 @if (true) { 
    @:这里是if语句内部-2
 }
复制代码

3.1 第一种方式是使用了Razor中内置的标签<text></text>注意这不是html标签,他的映射到浏览器上的时候就是纯文本显示没有任何的标记。

3.2 第二种方式是使用@:  他就表示后面的东东就是文本了。

运行效果:

 

另附html源文件:证明text标签额并非html标签

 

 <p>第一种方式</p>
    这里是if语句内部-1
 <p>第二种方式</p>
    这里是if语句内部-2

 

4. 表达式与文本混合

 

 <p>表达式与文本混合</p>
 Hello @strHello .当前时间: @now

 

    此种方式很简单不做太多解释,知识点是确保@字符前面是空字符 然后表单式结尾也是空字符即可。
运行结果

 

5. Email地址和@符号

 

 <p>Email地址</p>
 wlit2011@126.com

 

     Razor视图会自动识别email地址,而不需要进行特殊的处理,但是我就单单的输出一个@字符怎么办呢?您说怎么办啊学这么多年程序了,还能怎么办反转义呗!
     反转义的方法是加前面在加一个@字符既您写两个@字符  @@ 就就识别成一个@字符。

<p>我要输出强大的@@符号</p>

运行结果

 

 

 

6.刚才要输出的实例超出了页面范围所以我想临时把前面的演示代码注释掉,好下面讲怎么注释

      服务器端注释是对代码的注释它不同于客户端注释(<!-- -->),客户端的注释代码会被发送到浏览器虽在界面上看不到,但是查看源文件会看到滴。相反服务器端注释不会被发送到浏览器。起到对代码注释的效果,看下以下的代码也正好回顾下以上将的知识。

 

复制代码
 1 <h2>RazorTest</h2>
 2 @*
 3 <!-- 简单块 声明两个变量-->
 4 @{int num = 10;}
 5 @{string str = "hello cnblogs";}
 6 <!-- 内联表达式 输入刚才声明的两个变量-->
 7 <p>刚才声明的整形的值为: @num</p>
 8 <p>刚才声明的字符型的值为: @str</p>
 9 
10 <!-- 多声明代码块 -->
11 @{
12     string strHello = "您好,我叫李亮";
13     string now = DateTime.Now.ToString();
14     string sayHello = strHello + "<b>当前时间为:</b>" + now;
15  }
16  <p>问好: @Html.Raw(sayHello)</p>
17 
18  @for (int i = 0; i <= 10; i++) { 
19     <span>第@(i)行<br /></span>
20  }
21 
22  <p>第一种方式</p>
23  @if (true) { 
24     <text>这里是if语句内部-1</text>
25  }
26  <p>第二种方式</p>
27  @if (true) { 
28     @:这里是if语句内部-2
29  }
30  <p>表达式与文本混合</p>
31  Hello @strHello .当前时间: @now
32  *@
33  <p>Email地址</p>
34  wlit2011@126.com
35 
36 <p>我要输出强大的@@符号</p>
复制代码

 

     从第2行的@*(服务端注释开始标记)一直到第32行的*@(服务端注释结束标记)中间即为注释内容,输出结果即为第5.Email地址和@符号的输出结果。

     格式:@* 注释内容 *@  非常类似于C#的多行注释方式(/*    */)

7.内容中混合代码

      好好的看下下面这些代码是对以上知识的综合应用

 

复制代码
<p>内容中混合代码</p>
<ul>
 @for (int i = 0; i <= 10; i++) { 
    <li>
        当前循环到第@(i+1)次
        @if (i == 5) { 
            @:哇塞!遍历到数字5了
        }
        else if (i == 9) { 
            @:亲这是循环倒数第二次也就是第@(i+1)次哟!
        }
    </li>
 }
 </ul>
复制代码

 

运行结果

 


上篇博文介绍了一下Razor的基本语法,那今天看下Razor视图怎么布局吧!

Question 网站为啥要布局?

说道布局了那么网站为什么要布局呢?不布局有什么坏处呢?好今天开始咱先说一下为什么要布局?

首先,没有使用布局时,每个页面都存在大量的重复代码比如head top logo menu bottom 等等。

缺点:
1. 代码冗余      ---> 刚才已经提到了,没有使用布局的网站没个页面中必须再把比如logo head menu 等等从新copy一份,有人说我用iframe或者是include标记,我说当然可以,但是从开发规范上来看我觉得要避免使用浮动框架。
2. 不利于管理   ---> 您站点的每个文件都是单独的一个文件而没有统一的管理页面(布局页面)当然不利于管理。
3. 不利于后期修改 ---> 比如说哪天客户需求变了,我logo看着太小我要改大点,这下完蛋了 -- 坑爹啊 每个页面都得改。

那问题来了怎么解决呢?
   传统的webfrom中有母板页的概念大家应该都知道吧?如有不知道的,而且至今还用frame做模板布局的快学习.net的母板吧!这比 比如iframe什么的方便多了。因为我以前就是在.net里运用iframe 惭愧惭愧 嘿嘿!!!

今天的重点:Razor 布局 : 用过MVC 2 的应该知道那里面用的是master 母板页布局,那么MVC 3 中的布局是布局页(Layout)其实大同小异换瓶不换药

Razor的布局

1.不需要使用专门的.master文件,而统一使用.cshtml文件(view层中的文件都是.cshtml文件)
   布局文件名一般采用类似于_Layout.cshtml的名字。细心的人看到了是下划线开头,MVC 3会限制以下划线开头的文件直接被用户访问,即此文件只能在程序中调用而不能直接被用户访问到,处于安全的考虑。

2. 布局文件中使用到的特殊标记
   2.1 @RenderBody() 用于标识布局页中科替换内容的主体部分。
   2.2 Layout属性:内容页总通过给页面的Layout属性赋值实现指定布局页的文件路径。

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

  2.3 @RenderSection在布局页中预设一些区域,用于在内容也中使用。
     如:布局时head标签中的东西不能确定,或者说其他的页面中需要一些不是公共的东西,如css文件,js文件等等那么就需要在布局页的head标签中加入如下代码了  @RenderSection("head",false)

     2.3.1 第一个参数是Section的名字。
     2.3.2 第二个参数是用来设定是否为必须填充内容的区域。
     内容也中通过@section head { ... } 的方式向名为head的section中填充内容。

3. _ViewStart 文件


     我们发现在项目的试图文件夹下有个名为_ViewStart.cshtml 的文件那这个文件是干啥的呢?该文件用来定义想要在每次视图呈现开始时执行的通用试图代码,就是你每访问一个试图页面之前先调用这个文件执行这个文件中的代码然后在执行您所访问的视图页面。比如我们可以将上面的每个视图指定Layout属性的代码写在这里面。

      怎么样只需要写一次,每个视图了就不需要在写了,如如某个页面的布局和_ViewStart文件中的布局不一样怎么办呢?好办直接在视图里写对于的布局文件即可它会默认覆盖共有的布局文件。那么如果我有好多页面都需要一个不同的布局页并且它们在同一个文件夹(比如网站后台admin)下那怎么办呢?难不成要每个视图都要知道Layout属性吗?不会滴 。 先说下_ViewStart文件的作用范围:它的同级文件已经同级的子文件。所以针对上面的需求只需要在admin文件中新建一个_ViewStart文件然后在文件中指定Layout属性就OK了。


上两篇文章讲的是View层的Razor视图引擎,那么今天咱就讲另一个玩玩,什么呢 ? Controller

首先看一下ASP.net MVC 的请求过程 看一下客户端向服务器发送一个请求后服务器 做了哪些事情吧!

有些内容图上我已经标的很清楚了,我再这就不再一一描述了,直接看图就OK了。

下面是今天要说的Controller

      从上图可以看出客户端请求通过IIS已经MVC中路由机制的解析后就扔给MVC 的controller处理了,从这点可以看出controller(控制器)在MVC中扮演着处理客户端请求的角色。

对于controller有以下几个注意事项:

> 1. 必须实现System.Web.Mvc.IController 接口 --- 但是正常情况小我们是直接继承System.Web.Mvc.Controller 类 ,这样就避免了我们再完全的实现IController接口了,但是如果您的项目需求现有的controller类不能满足那就自己实现一下IController 接口吧!

> 2. 必须要以Controller结尾, 比如 有这么个url地址:http://www.cnblogs/wlitsoft/blogs/123 路由解析后的结果是找wlitsoftController 类。

> 3. Controller 类中有大量的返回值为ActionResult 的方法,这写方法就是所谓的Action,然后Controller通过不同的Action来处理具体的客户端请求,比如还是上面的那个url地址,就是wlitSoftController 会找  blogs 这个 Action 方法 然后参数为123。

说到ActionResult 那就不能不好好的说说,好下面咱就好好的说下ActionResult

类名 抽象类 父类 功能
ContentResult     根据内容的类型和编码,数据内容.
EmptyResult     空方法.
FileResult abstract   写入文件内容,具体的写入方式在派生类中.
FileContentResult   FileResult 通过 文件byte[] 写入文件.
FilePathResult   FileResult 通过 文件路径 写入文件.
FileStreamResult   FileResult 通过 文件Stream 写入文件.
HttpUnauthorizedResult     抛出401错误
JavaScriptResult     返回javascript文件
JsonResult     返回Json格式的数据
RedirectResult     使用Response.Redirect重定向页面
RedirectToRouteResult     根据Route规则重定向页面
ViewResultBase abstract   调用IView.Render()
PartialViewResult   ViewResultBase 调用父类ViewResultBase 的ExecuteResult方法. 重写了父类的FindView方法. 寻找用户控件.ascx文件
ViewResult   ViewResultBase 调用父类ViewResultBase 的ExecuteResult方法. 重写了父类的FindView方法. 寻找页面.aspx文件

下面咱就同代码的方式依次证明验证一下这些ActionResult
首先,建一个MVC 3 项目 这里就不再演示了,不会的的可以看下我以前写的文章。

第二步 新建一个Controller

添加一个名为CtextController 的 Controller

第三步 写代码呗

复制代码
  1 namespace Mvc3App1.Controllers
  2 {
  3     public class CTestController : Controller
  4     {
  5         //
  6         // GET: /CTest/
  7 
  8         public ActionResult Index()
  9         {
 10             return View();
 11         }
 12 
 13         public ActionResult ContentResult()
 14         {
 15             return Content("Hi, 我是ContentResult结果");
 16             //return Content("<script>alert('abc')</script>");
 17         }
 18 
 19         public ActionResult EmptyResult()
 20         {
 21             //就是一个空白页面 真的是一个什么都没有的页面
 22             return new EmptyResult();
 23         }
 24 
 25         public ActionResult FileResult()
 26         {
 27             var imgPath = Server.MapPath("~/images/1.jpg");
 28             return File(imgPath, "application/x-jpg", "1.jpg");
 29         }
 30 
 31         public ActionResult HttpNotFoundResult()
 32         {
 33             return HttpNotFound("Page Not Found");
 34         }
 35 
 36         public ActionResult HttpUnauthorizedResult()
 37         {
 38             //未验证时,跳转到Logon
 39             return new HttpUnauthorizedResult();
 40         }
 41 
 42         public ActionResult JavaScriptResult()
 43         {
 44             //string js = "alert(\"Hi, I'm JavaScript.\");";
 45             //return JavaScript(js);
 46             string s = "$('#divResultText').html('JavaScript Passed')";
 47             return JavaScript(s);
 48         }
 49 
 50         public ActionResult JsonResult()
 51         {
 52             var jsonObj = new
 53             {
 54 
 55                 Id = 1,
 56 
 57                 Name = "小铭",
 58 
 59                 Sex = "",
 60 
 61                 Like = "足球"
 62 
 63             };
 64             return Json(jsonObj, JsonRequestBehavior.AllowGet);
 65         }
 66 
 67         public ActionResult RedirectResult()
 68         {
 69             return Redirect("~/images/1.jpg");
 70         }
 71 
 72         public ActionResult RedirectToRouteResult()
 73         {
 74             return RedirectToRoute(new
 75             {
 76                 controller = "Hello",
 77                 action = ""
 78             });
 79         }
 80 
 81         public ActionResult ViewResult()
 82         {
 83             return View();
 84         }
 85 
 86         public ActionResult PartialViewResult()
 87         {
 88             return PartialView();
 89         }
 90         //禁止直接访问的ChildAction
 91         [ChildActionOnly]
 92         public ActionResult ChildAction()
 93         {
 94 
 95             return PartialView();
 96 
 97         }
 98 
 99         //正确使用ChildAction
100         public ActionResult UsingChildAction()
101         {
102 
103             return View();
104 
105         }
106     }
复制代码

 部分运行结果:

  index 运行结果

contentResult运行结果

 

HttpUnauthorizedResult运行结果

 

FIleResult运行结果


 

抱歉!评论已关闭.