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>