ASP.NET/MVC的cshtml和Razor
Razor是一种标记语法,把.NET嵌入到网页中。Razor语法包括Razor标记、C#、HTML。文件以.cshtml为扩展名。
cshtml和aspx比较
[编辑]cshtml(使用C#的Razor语法)或vbhtml(使用VB的Razor语法)是MVC3开始新增的视图文件,跟原先的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文本<span>Hello World</span>
@{
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>