65.9K
CodeProject 正在变化。 阅读更多。
Home

MVC 3 Razor 视图引擎入门

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (28投票s)

2013 年 8 月 19 日

CPOL

13分钟阅读

viewsIcon

175730

本文介绍了 MVC 3 中的 Razor 视图引擎。这是一篇入门级文章,通过一个示例描述了 Razor 视图引擎的基础知识。

目录

引言

ASP.NET MVC 一直支持“视图引擎”的概念,这些视图引擎是实现各种模板语法选项的可插入模块。“默认”的 ASP.NET MVC 视图引擎使用与 ASP.NET Web Forms 相同的 .aspx/.ascx/.master 文件模板。在本文中,我将介绍 Razor 视图引擎来创建一个应用程序的视图。Razor 于 2010 年 6 月开始开发,并于 2011 年 1 月发布给 Microsoft Visual Studio。

Razor 本身并不是一种新的编程语言,而是使用 C# 语法在页面中嵌入代码,而无需 ASP.NET 的分隔符:<%= %>。它是一种简单语法的视图引擎,作为 ASP.NET MVC 3 的一部分发布。对于 C# 语言,Razor 文件扩展名为“cshtml”。它支持 TDD(测试驱动开发),因为它不依赖于 System.Web.UI.Page 类。

Razor 语法

要理解 Razor 视图引擎,我们应该学习它的语法,所以让我们从语法开始。

单语句块和内联表达式

每个代码块都以开闭花括号 {..} 开始和结束。语句定义在代码块中,换句话说,在开闭花括号之间,并以分号 (";") 结尾。但当它用作内联表达式时,则不需要使用分号。

@{ var message = "Hello,Razor view engine";}
Message is : @message

这里我们声明 message 是一个变量,并为其分配一个字符串,该变量可通过 @ 字符全局访问。因此,当我们定义一个代码块和一个变量调用时,都会使用 @ 字符,输出如下:

Hello Razor

多语句块

我们也可以将多行语句块定义为单行语句块。在多行语句块中,我们可以定义多个代码语句并处理数据。多行块将存在于开闭花括号之间,但开花括号必须与 "@" 字符在同一行;如果我们定义 "@" 和开花括号在不同的行,则会生成错误。

@{
    var priciple = 100;
    var rate = 12;
    var time = 2;
    var interest = (priciple * rate * time) / 100;
}
//Interest of @priciple rupees is @interest for @time years

在多语句代码块中,每个语句都以分号结尾,最终结果如下:

Razor Multiline

条件语句

在 Razor 视图引擎中,我们可以根据条件创建动态网页。我们可以在代码块内或代码块外定义条件。if 语句的工作方式与在其他编程语言中相同。

@{
var isValid = true;
if(isValid)
{
    It is an if statement in code block
}
else
{
    It is an else statement in code block
}
}
@if(true)
{
    It is a single if block
}

这是一个默认规则,块语句或语句必须存在于花括号内,即使块只有一个语句。在上面的代码块中,我们有两种 if 条件,一种在代码块内,所以 @ 字符与代码块的起始花括号一起使用,另一种在代码块外,所以 @ 字符与 if 一起使用。最后,我们得到这两个 if 语句的输出。

Razor If Block

循环

所有循环的工作方式与在其他编程语言中相同,我们可以在代码块内或代码块外定义循环。我们可以在代码块中定义 fordo whilewhile 循环,并使用相同的语法进行初始化、增量/减量以及检查条件。

@{
    for(var count = 1;count,=3;count++)
    {
        @Count is : @count
    }
           
    string [] nameArray = {"Sandeep","Mandeep","Kuldeep","Pradeep"};
    foreach(var name in nameArray)
    {
        Your Name is : @name
    }
}

我们还可以在代码块中定义 foreach,它可以从任何集合中向前访问数据。上面的代码块包含 forforeach 语句,它们的输出是

Razor If Block

注释

Razor 视图引擎有两种注释:一种是单行注释,另一种是多行注释。Razor 使用 "@* ..*@" 语法作为注释块,但在 C# 代码块中,我们也可以使用 /* *///。HTML 注释与此相同,为 <!-- -->

@{
    @* for(var count = 1;count,=3;count++)
    {
        @Count is : @count
    }*@
           
    //string [] nameArray = {"Sandeep","Mandeep","Kuldeep","Pradeep"};
           
    /*foreach(var name in nameArray)
    {
        Your Name is : @name
    }*/

}

使用对象

我们也可以在代码块和 HTML 中使用对象,使用 Razor 语法。

Date :@System.DateTime.Now.Date.ToString("D")
Hour :@System.DateTime.Now.Hour
Minute :@System.DateTime.Now.Minute
Second :@System.DateTime.Now.Second

因此,我们有一个经验法则:C# 代码用于以 "@{" 开头并以 "}" 结尾的代码块;每当在 HTML 块中使用变量时,变量都带有 "@" 前缀。

这不是 Razor 语法的完整列表,但我认为您现在已经掌握了 Razor 的基本语法,所以我们应该继续进行示例。

使用 Razor 创建用户注册应用程序

步骤 1:创建新项目

首先,我们为我们的示例创建一个新的 MVC 项目。

Create new project

之后,我们安装模板,其中我们选择 MVC 应用程序。现在,根据上述操作,我们看到以下屏幕。

Create new mvc application

如上图所示,我们执行从 1 到 5 的操作,操作号 6 将我们从 MVC 应用程序的模板选择器中移出,我们得到此操作的结果是

Create new empty mvc application

所以最后我们在 Visual Studio 中得到了一个默认的空应用程序。空应用程序并不意味着我们没有文件夹和布局。我们还有一个默认的共享布局(视图)、CSS 和 JavaScript 文件。默认的文件夹结构是

Directory structure mvc application

步骤 2:创建模型

在解决方案资源管理器中右键单击“Models”文件夹,然后转到“Add”,然后单击“Class”。

Create a Model

Model 是一个带有属性的 C# 类。我们在模型中定义属性以适应我们的 UI。换句话说,我们在模型中定义了要在 UI 中显示的内容。模型是根据 UI 模板创建的,而不是根据数据库表创建的。有时我们认为我们的模型应该具有与数据库表对应的属性,换句话说,我们创建模型和数据库表之间的映射。但我们应该根据数据库表创建实体并在此之间进行映射,而模型应该根据我们的 UI 屏幕设计。所以我们的用户注册模型是“UserRegisterModel.cs”。

namespace UserRegistrationApplication.Models
{
    public class UserRegisterModel
    {

        public string Name { get; set; }
        public string Password { get; set; }
        public string Email { get; set; }
    }
}

步骤 3:创建控制器

我们创建一个控制器,该控制器根据请求向浏览器发送响应。我们正在开发一个用户注册 UI,所以创建一个 UserRegisterController。在解决方案资源管理器中右键单击“Controllers”文件夹,然后转到“Add”,然后单击“Controller”。

Create a Controller

之后,我们得到“Add Controller”屏幕,我们在其中提供控制器名称。我们想创建一个空的控制器,换句话说,我们不希望控制器中有默认的创建、更新、删除和详细信息操作方法,所以我们在“Add Controller”屏幕上不勾选复选框。空控制器不意味着没有操作方法的控制器,而是有一个名为“Index”的单个操作方法的控制器。

add a Controller

现在我们有了一个控制器,它有一个 UserRegister 操作方法,该方法返回一个带有空 UserRegister 模型的视图。此方法通过来自浏览器的 HTTP GET 请求调用。

namespace UserRegistrationApplication.Controllers
{
    public class UserRegisterController : Controller
    {
        public ActionResult UserRegister()
        {
            UserRegistrationApplication.Models.UserRegisterModel model = new UserRegistrationApplication.Models.UserRegisterModel();
            return View(model);
        }
    }
}

UserRegister() 操作方法将返回一个空的 UserRegisterModel 模型,该模型将绑定到 UserRegister 视图以及 UserRegister 视图。

步骤 4:创建视图

我们创建一个在浏览器中呈现并显示用户注册表的视图。视图将根据控制器中的操作方法创建,所以首先,在 UserRegisterController 控制器中右键单击 UserRegister( ) 操作方法。

Create a view

当我们单击“Add View..”项时,我们会得到“Add View”屏幕。

Add a view

我们创建一个强类型视图,它与 UserRegisterModel 模型绑定。它对视图没有太大影响;创建时,它只会将模型导入视图(CSHTML 文件)。我们得到默认的 UserRegister 视图。

@model UserRegistrationApplication.Models.UserRegisterModel
@{
    ViewBag.Title = "UserRegister";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

UserRegister

有两个要点:一是 UserRegisterModel 已经绑定,因为我们创建了一个强类型视图;二是主布局已通过代码块中的 Layout 属性在新视图上实现。这里 ViewBag.Title 被赋值为字符串值 UserRegister,即页面标题,所以当我们想修改页面标题时,只需修改 ViewBag.Title 属性的值。

在深入探讨视图设计细节之前,我们需要对 MVC 中的 HTML Helpers 有一点了解。HTML Helpers 非常类似于传统的 ASP.NET Web Form 控件。在大多数情况下,HTML Helper 只是一个返回字符串的方法。我们将使用以下三个 HTML Helper 方法:

LabelFor:它是 System.Web.Mvc.Html 命名空间下 LabelExtensions 类的一个方法,它返回一个 HTML Label 元素。模型属性根据指定表达式显示文本和 for 属性值。它是 HtmlHelper 实例的一个扩展方法。

例如,当模型 Name 属性在 LabelFor() 方法中使用时,它在 HTML 中呈现为:

<label for="Name">Name</label>

TextBoxFor:它是 System.Web.Mvc.Html 命名空间中 InputExtensions 类的一个方法,它返回一个 HTML 文本输入元素。模型属性用于 ID 和 name 属性值。Input 元素类型属性由 TextBoxFor() 方法设置为“text”。它也是 HtmlHelper 实例的一个扩展方法。它还会在 TextBox 中显示模型属性值。例如,当模型 Name 属性在 TextBoxFor() 方法中使用时,它在 HTML 中呈现为:

<input id="Name" name="Name" type="text" value="" />

PasswordFor:它是 System.Web.Mvc.Html 命名空间中 InputExtensions 类的一个方法,它返回一个 HTML 密码输入元素。模型属性用于 ID 和 name 属性值。Input 元素类型属性由 PasswordFor() 方法设置为“password”。它也是 HtmlHelper 实例的一个扩展方法。它还会在 TextBox 中显示模型属性值。例如,模型 Password 属性在 PasswordFor() 方法中使用时,它在 HTML 中呈现为:

<input id="Password" name="Password" type="password" />

为了设计用户注册表单,我们在 Content 文件夹下创建了一个样式表 BaseStyleSheet.css

.formRowContainer
{
  width: 100%;
  padding-top: 10px;
}
.labelContainer
{
    padding-top: 2px;
    float: left;
    min-width: 155px;
}
.valueContainer
{
    float: left;
}
.buttonContainer
{
   padding-top: 5px;
   padding-left :155px;
}
.clearStyle
{
    clear: both;
}

然后我们将此 CSS 放入视图中,并在视图 UserRegister.cshtml 中添加代码以创建用户注册表单。我们正在创建一个注册表单,所以所有表单都将存在于 <form></form> 标签内,但在 MVC 中,我们在 html.BeginForm() 代码块中创建整个表单,该代码块将在 <form> 标签中呈现,该标签的 action 属性值包含一个控制器操作方法,并且将使用一个方法通过 HTTP POST 请求提交数据。

@model UserRegistrationApplication.Models.UserRegisterModel
@{
    ViewBag.Title = "UserRegister";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<link href="@Url.Content("~/Content/BaseStyleSheet.css")" rel="stylesheet" type="text/css" />
<h2>User Register Form</h2>@using(Html.BeginForm())
{
<div>
    <div class="formRowContainer">
        <div class="labelContainer">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="valueContainer">
            @Html.TextBoxFor(model=>model.Name,Model.Name)
        </div>
    </div>
    <div class="clearStyle"></div>
    <div class="formRowContainer">
        <div class="labelContainer">
            @Html.LabelFor(model => model.Password)
       </div>
        <div class="valueContainer">
            @Html.PasswordFor(model => model.Password, Model.Password)
        </div>
    </div>
   <div class="clearStyle"></div>
    <div class="formRowContainer">
        <div class="labelContainer">
            @Html.LabelFor(model => model.Email)
        </div>
        <div class="valueContainer">
            @Html.TextBoxFor(model => model.Email, Model.Email)
        </div>
    </div>
    <div class="clearStyle"></div>
    <div class="buttonContainer">
        <button>Register</button></div></div>
}

我们的视图已准备就绪。按 F5 或运行应用程序以在浏览器屏幕上显示表单。现在屏幕上的结果是:

Page Not Found

哦,我们遇到了 HTTP 404 错误(找不到资源),URL 为 https://:3581/。为这个应用程序做了很多工作却未能成功运行应用程序,这不太好。但别担心,我们应该为从代码中获得的错误感到高兴,因为每个错误都会教会我们更多东西。

现在在 Visual Studio 中从解决方案资源管理器打开 Global.asax.cs 文件,并查看 RegisterRoutes() 方法。此方法定义了应用程序的 URL 路由,并在应用程序启动时调用。根据 RegisterRoutes() 方法,我们的应用程序默认控制器是“Home”,默认控制器操作方法是“Index”,但我们在用户注册应用程序中没有定义这些,所以我们遇到了“找不到资源”的错误。要解决此错误,我们有两种选择:一种是在 RegisterRoutes() 方法的 RouteCollection 实例的 MapRoute() 方法参数中为 UserRgisterController 控制器和操作方法设置一个静态硬编码字符串值;另一种选择是在浏览器中通过 URL 传递控制器和操作方法。我们选择第二种选择,因为每个应用程序都有多个页面,其中 Home 控制器是默认控制器,Index 是控制器默认的操作方法。

public static void RegisterRoutes(RouteCollection routes))
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.MapRoute(
      "Default", // Route name
       "{controller}/{action}/{id}", // URL with parameters
       new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
  );
}

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

现在,在浏览器请求中输入用户注册控制器和操作方法 URL https://:3518/UserRegister/UserRegister。或者,我们可以像下面这样更改 RouteCollection 实例的 RegisterRoutes() 方法中的 MapRoute() 方法参数:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new { controller = "UserRegister", action = "UserRegister", 
              id = UrlParameter.Optional } // Parameter defaults
   );
}

Application result

之后,我单击“Register”按钮以显示我的数据。我的输入数据在哪里?为了显示输入数据,我想澄清几点。当我们通过浏览器访问视图时,浏览器请求会查找控制器中的 HttpGet 操作方法;但当我们通过按钮单击发送请求时,请求会查找控制器中的 HttpPost 操作方法。如果我们没有明确定义操作方法的路径,它会查找与视图名称同名的默认操作方法。为了显示我们的表单数据,我们在控制器中创建一个操作方法,该方法带有一个参数,该参数是视图在回发时传递到控制器的一个模型,我们可以在操作方法中获取该模型的数据。

[HttpPost]
public ActionResult UserRegister(UserRegisterModel model)
{
    System.Text.StringBuilder sbMessage = new System.Text.StringBuilder();
    sbMessage.Append("Your Name is : "+ model.Name + "</br/>");
    sbMessage.Append("Your Password is : " + model.Password + "</br/>");
    sbMessage.Append("Your Email is : " + model.Email + "</br/>");
    return Content(sbMessage.ToString());
}

之后,在单击注册按钮后,我们得到结果。我们的 URL 没有改变,在这种情况下,只有内容会改变。

Application data result

使用数据注解验证属性执行验证

我们使用验证器属性来执行验证。System.ComponentModel.DataAnnotations 命名空间包含以下验证器属性:

  • Range:允许您验证属性的值是否在指定的数值范围内。
  • RegularExpression:允许您验证属性的值是否匹配指定的正则表达式模式。
  • Required:允许您将属性标记为必需。
  • StringLength:允许您为字符串属性指定最大长度。
  • Validation:所有验证器属性的基类。

现在我们在 UserRegisterModel 模型上实现了五个属性中的三个属性(RequiredStringLengthRegularExpression),所以我们需要修改现有的模型如下:

using System.ComponentModel.DataAnnotations;
using System.ComponentModel;

namespace UserRegistrationApplication.Models
{
    public class UserRegisterModel
    {
        [DisplayName("User Name")]
        [Required(ErrorMessage="Name can not be blank")]
        public string Name { get; set; }

        [Required(ErrorMessage = "Password can not be blank")]
        [StringLength(6,ErrorMessage="Password should be equal or less than 6 character")]
        public string Password { get; set; }

        [Required(ErrorMessage = "Email can not be blank")]
        [RegularExpression(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*",ErrorMessage="Email is not Valid")]
        public string Email { get; set; }
    }
}

在这里,我们还使用 DisplayName 为 Name 字段显示自定义名称,换句话说,在 UI 屏幕上,模型 Name 属性标签将具有“User Name”作为文本值。在这里,我们为字符串长度和正则表达式定义了自定义消息,以便在应用验证时 UI 屏幕显示我们的自定义消息,否则我们将收到数据注解验证器属性的默认错误消息。

我们在模型属性上应用了数据注解验证器属性,该属性会在 UI 屏幕上显示消息,所以我们需要为每个字段添加 HtmlHelper 类的 ValidationMessage() 方法,并且我们还像下面一样修改了我们的视图:

@model UserRegistrationApplication.Models.UserRegisterModel
@{
    ViewBag.Title = "UserRegister";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<link href="@Url.Content("~/Content/BaseStyleSheet.css")" rel="stylesheet" type="text/css" />
<h2>User Register Form</h2>@using(Html.BeginForm())
{
<div>
    <div class="formRowContainer">
        <div class="labelContainer">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="valueContainer">
            @Html.TextBoxFor(model=>model.Name,Model.Name)
            @Html.ValidationMessage("Name")
        </div>
    </div>
    <div class="clearStyle"></div>
    <div class="formRowContainer">
        <div class="labelContainer">
            @Html.LabelFor(model => model.Password)
       </div>
        <div class="valueContainer">
            @Html.PasswordFor(model => model.Password, Model.Password)
            @Html.ValidationMessage("Password")
        </div>
    </div>
    <div class="clearStyle"></div>
    <div class="formRowContainer">
        <div class="labelContainer">
            @Html.LabelFor(model => model.Email)           
        </div>
        <div class="valueContainer">
            @Html.TextBoxFor(model => model.Email, Model.Email)
            @Html.ValidationMessage("Email")
        </div>
    </div>
    <div class="clearStyle"></div>
    <div class="buttonContainer">
        <button>Register</button></div></div>}

我们使用 HtmlHelper 类的 ValidationMessage(),它接受一个字符串形式的参数,即模型中的属性名称,并在提交表单时模型无效时显示模型属性中定义的错误消息。我们需要在控制器中的操作方法中检查模型是否有效,所以我们更新了 UserRegisterController 控制器中现有的 post 操作方法。

[HttpPost]
public ActionResult UserRegister(UserRegisterModel model)
{
    if (ModelState.IsValid)
    {
        System.Text.StringBuilder sbMessage = new System.Text.StringBuilder();
        sbMessage.Append("Your Name is : " + model.Name + "
");
        sbMessage.Append("Your Password is : " + model.Password + "
");
        sbMessage.Append("Your Email is : " + model.Email + "
");
        return Content(sbMessage.ToString());
    }
    else
    {
        return View(model);
    }       
}

在这里,我们使用 If 条件来确定 UserRegisterModel 模型是否有效。如果模型根据验证规则有效,则 if 块将被执行,否则不会。现在我们运行我们的 MVC UserRegistrationApplication 来测试验证。我们执行两个测试,一个用于必需字段消息,另一个用于自定义验证消息。首先,我们将表单上的所有文本框留空,并通过单击注册按钮提交表单。我们得到的结果如下。

Application data validation

现在我们通过在输入字段中插入错误的值并单击注册按钮提交表单来执行另一个测试。

Application data validation

希望我们已经了解了 MVC 3 中 Razor 视图引擎的基础知识。

结论

本文介绍了 ASP.Net MVC 3,但相同的概念也用于 MVC 4。如果您有任何疑问,请在评论中发布或直接通过 https://twitter.com/ss_shekhawat 联系。如果您想学习使用 Entity Framework 和 Code First 方法进行 MVC 学习,这里有一个系列  使用 Entity Framework Code First 方法的 MVC 学习系列  供您参考。

© . All rights reserved.