ASP.NET/MVC的cshtml和Razor

维基教科书,自由的教学读本

Razor是一种标记语法,把.NET嵌入到网页中。Razor语法包括Razor标记、C#、HTML。文件以.cshtml为扩展名。

cshtml和aspx比较[编辑]

cshtml(使用C#的Razor语法)或vbhtml(使用VB的Razor语法)是MVC3开始新增的视图文件,跟原先的aspx很相似,都是在服务器端运行的动态网页文件。

cshtml和aspx比较
项目 cshtml aspx
解释引擎 Razor Rendering Engine WebForm Engine
在页面中嵌入服务器代码块 @{ test; } <% test; %>
在服务器端解析表达式 @ShowHelloWorld() <%= ShowHelloWorld() %>

Razor语法[编辑]

Razor是服务器端标记语言,有变量,循环,逻辑等,允许向网页中嵌入基于服务器的代码。Razor网页是带有两种内容的HTML页面:HTML内容和Razor代码。在服务器端运行Razor代码,生成静态网页,发往用户的网页浏览器。

Razor关键字[编辑]

Razor关键字有:

  • page
  • namespace
  • functions
  • inherits
  • model
  • section

加上括号可以转义,如@( RazorKeyword )

C# Razor关键字[编辑]

C# Razor关键字有:case、do、default、for、foreach、if、else、lock、switch、try、catch、finally、using、while。使用双重括号转义,如@(@case)。第一个@让Razor parser转义,第2个@让C# parser转义。

@ 转移字符[编辑]

@叫做转移字符(transition character)。连续2个@字符为转义,如razor的<p>@@Username</p>等价于html的<p>@Username</p>。

隐式Razor表达式[编辑]

隐式Razor表达式(Implicit Razor expressions),为@后跟C#表达式,如:

<p>@DateTime.Now</p>
<p>@DateTime.IsLeapYear(2016)</p>
<p>@await DoSomething("hello", "world")</p>

除了C# await关键字外不允许有空格、不能用泛型。角括号(<>)被解释为HTML tag。

显式Razor表达式[编辑]

显式Razor表达式(Explicit Razor expression),为@后跟一对括号。

<p>Last week this time: @(DateTime.Now - TimeSpan.FromDays(7))</p>

<p>@(GenericMethod<int>())</p>正确的使用了泛型

@Html.Raw("<span>Hello World</span>")不编码直接作为html文本。

@("<span>Hello World</span>")编码为html文本&lt;span&gt;Hello World&lt;/span&gt;

@{
    var joe = new Person("Joe", 33);
}
<p>Age@(joe.Age)</p>如果不用显式Razor表达式,则<nowiki><p>Age@joe.Age</p></nowiki>将被解释为email地址。

Razor代码块[编辑]

Razor代码块为@后跟一对花括号{},例如:

@{
    void RenderName(string name)
    {
        <p>Name: <strong>@name</strong></p>
    }

    RenderName("Mahatma Gandhi");
    RenderName("Martin Luther King, Jr.");
}

将绘制html如下:

<p>Name: <strong>Mahatma Gandhi</strong></p>
<p>Name: <strong>Martin Luther King, Jr.</strong></p>

Razor代码块的默认语言是C#,但可以隐式转换为HTML:

@{
    var inCSharp = true;
    <p>Now in HTML, was in C# @inCSharp</p>
}

使用<text>的显式转换为HTML:

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    <text>Name: @person.Name</text>
}

@:显式行转换为HTML:

@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    @:Name: @person.Name
}

控制结构[编辑]

@if (value % 2 == 0)
{
    <p>The value was even.</p>
}
else if (value >= 1337)
{
    <p>The value is large.</p>
}
else
{
    <p>The value is odd and small.</p>
}

@switch (value)
{
    case 1:
        <p>The value is 1!</p>
        break;
    case 1337:
        <p>Your number is 1337!</p>
        break;
    default:
        <p>Your number wasn't 1 or 1337.</p>
        break;
}

@{
    var people = new Person[]
    {
          new Person("Weston", 33),
          new Person("Johnathon", 41),
          ...
    };
}
@for (var i = 0; i < people.Length; i++)
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
}
@foreach (var person in people)
{
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>
}
@{ var i = 0; }
@while (i < people.Length)
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>

    i++;
}
@{ var i = 0; }
@do
{
    var person = people[i];
    <p>Name: @person.Name</p>
    <p>Age: @person.Age</p>

    i++;
} while (i < people.Length);

using复合[编辑]

@using (Html.BeginForm())
{
    <div>
        Email: <input type="email" id="Email" value="">
        <button>Register</button>
    </div>
}

@try, catch, finally[编辑]

@try
{
    throw new InvalidOperationException("You did something invalid.");
}
catch (Exception ex)
{
    <p>The exception message: @ex.Message</p>
}
finally
{
    <p>The finally statement.</p>
}

@lock[编辑]

用于保护临界区:

@lock (SomeLock)
{
    // Do critical section work
}

注释符号[编辑]

@*
    @{
        /* C# comment */
        // Another C# comment
    }
    <!-- HTML comment -->
*@

为一个view生成的Razor C#类[编辑]

Razor SDK把Razor文件编辑为源代码文件并放在目录中:

obj/<build_configuration>/<target_framework_moniker>/Razor

再向下就遵从Razor文件的目录结构。

一个Razor文件:

@{
    var quote = "Getting old ain't for wimps! - Anonymous";
}

<div>Quote of the Day: @quote</div>

会被编译为C#文件:

public class _Views_Something_cshtml : RazorPage<dynamic>
{
    public override async Task ExecuteAsync()
    {
        var output = "Getting old ain't for wimps! - Anonymous";

        WriteLiteral("/r/n<div>Quote of the Day: ");
        Write(output);
        WriteLiteral("</div>");
    }
}

这种生成的类,可以有Razor directives来修饰:

  • @attribute
  • @code:向Razor components (.razor)增加 C# members (fields, properties, and methods) 。是 @functions的别名
  • @functions:向生成的类增加C# members (fields, properties, and methods)
  • @implements:生成的类实现一个接口
  • @inherits:当前view继承了一个类
  • @inject:从服务容器向view注入一个服务
  • @layout:一个可路由的Razor components且有一个@page指令,指定一个layout
  • @model:指定传给一个MVC views或Razor Pages (.cshtml)的模型的类型。生成的类是从RazorPage<ModelClass>派生的。通过生成类的Model属性可以访问model传给view的数据。如果没有给出@model指令,那么默认为dynamic
  • @namespace:生成类所在的命名空间。 Sets the root derived namespaces of a pages, views, or components classes from the closest imports file in the directory tree, _ViewImports.cshtml (views or pages) or _Imports.razor (Razor components)。如果每个页面都导入了Pages/_ViewImports.cshtml,且Pages/_ViewImports.cshtml包含@namespace Hello.World,那么每个页面都以Hello.World作为根命名空间。如Pages/Index.cshtml的命名空间为Hello.World;Pages/MorePages/Page.cshtml的命名空间为Hello.World.MorePages。如果多个导入文件都有命名空间,那么在目录树上最接近 page, view, component的导入文件的命名空间作为根命名空间。
  • @page:对于.cshtml文件,指出这是Razor Page;或者指出Razor component应直接处理请求。
  • @preservewhitespace:对于Razor components (.razor),设为false (缺省值)时头尾部空白符被删除。
  • @section:对于MVC views或Razor Pages (.cshtml),与layouts一起可在HTML页面不同位置绘图。
  • @using:即C# using指令
@functions {
    public string GetHello()
    {
        return "Hello";
    }
}
<div>From method: @GetHello()</div>

@using System.IO
@{
    var dir = Directory.GetCurrentDirectory();
}
<p>@dir</p>

Razor模板[编辑]

@符号后跟一对html标记可作为一个模板化的Razor委托。其参数的类型为dynamic。例如:

public class Pet
{
    public string Name { get; set; }
}

    var pets = new List<Pet>
    {
        new Pet { Name = "Rin Tin Tin" },
        new Pet { Name = "Mr. Bigglesworth" },
        new Pet { Name = "K-9" }
    };

用于

@{
    Func<dynamic, object> petTemplate = @<p>You have a pet named <strong>@item.Name</strong>.</p>;

@foreach (var pet in pets)
{
    @petTemplate(pet)
}
}

结果为:

<p>You have a pet named <strong>Rin Tin Tin</strong>.</p>
<p>You have a pet named <strong>Mr. Bigglesworth</strong>.</p>
<p>You have a pet named <strong>K-9</strong>.</p>

内联写法:

@using Microsoft.AspNetCore.Html

@functions {
    public static IHtmlContent Repeat(IEnumerable<dynamic> items, int times,
        Func<dynamic, IHtmlContent> template)
    {
        var html = new HtmlContentBuilder();

        foreach (var item in items)
        {
            for (var i = 0; i < times; i++)
            {
                html.AppendHtml(template(item));
            }
        }

        return html;
    }
}

<ul>
    @Repeat(pets, 3, @<li>@item.Name</li>)
</ul>

结果为:

<ul>
    <li>Rin Tin Tin</li>
    <li>Rin Tin Tin</li>
    <li>Rin Tin Tin</li>
    <li>Mr. Bigglesworth</li>
    <li>Mr. Bigglesworth</li>
    <li>Mr. Bigglesworth</li>
    <li>K-9</li>
    <li>K-9</li>
    <li>K-9</li>
</ul>

Razor语法规则杂项[编辑]

  • 代码语句以分号结尾
  • 字符串由引号包围
  • 变量用关键字var声明
  • C#代码对大小写敏感

Razor类型转换[编辑]

可以用As系列扩展方法和Is系列扩展方法:

  • AsInt(), IsInt()
  • AsBool(),IsBool()
  • AsFloat(),IsFloat()
  • AsDecimal(),IsDecimal()
  • AsDateTime(),IsDateTime()
  • ToString()

示例[编辑]

    <!-- 单行代码块 -->
    @{ var myMessage =	"Hello World"; }
     
    <!-- 行内表达式或变量 -->
    <p>The value of myMessage is: @myMessage</p> 
     
    <!-- 多行语句代码块 -->
    @{
    var greeting = "Welcome to our site!";
    var weekDay = DateTime.Now.DayOfWeek;
    var greetingMessage = greeting + " Here in Huston it is: " + weekDay;
    }
    <p>The greeting is: @greetingMessage</p>


读取用户在动态网页上的输入[编辑]

由Request[] 函数读取输入,并由 IsPost条件进行测试:

    @{
    var totalMessage = "";
    if(IsPost)
        {
        var num1 = Request["text1"];
        var num2 = Request["text2"];
        var total = num1.AsInt() + num2.AsInt();
        totalMessage = "Total = " + total;
        }
    }
    <html>
    <body style="background-color: beige; font-family: Verdana, Arial;">
    <form action="" method="post">
    <p><label for="text1">First Number:</label><br>
    <input type="text" name="text1" /></p>
    <p><label for="text2">Second Number:</label><br>
    <input type="text" name="text2" /></p>
    <p><input type="submit" value=" Add " /></p>
    </form>
    <p>@totalMessage</p>
    </body>
    </html>