一.创建View
Razor View文件是为action方法提供视图,可以在Views->ControllerName文件夹下创建这个文件,在我们应用程序中创建一个CityController.cs文件,这个控制器中有一个Tokyo的方法
using Microsoft.AspNetCore.Mvc; namespace AspNetCore.Views.Controllers { public class CityController : Controller { public IActionResult Tokyo() { // 堆代码 duidaima.com return View(); } } }针对这个action方法,我们创建一个他自己的视图在Views->City文件夹下,注意文件夹的名字没有Controller后缀,是City而不是CityController,因此在应用程序的Views文件夹内创建一个新的文件夹叫City,选择Add->New Item, 在弹出的对话框中选择Razor View -Empty 并且将其命名为Tokyo.cshtml 。
<h1>Welcome to Tokyo</h1>运行应用程序进入URL-https://localhost:7019/City/Tokyo,我们会看到View呈现在浏览器中
using Microsoft.AspNetCore.Mvc; namespace AspNetCore.Views.Controllers { public class CityController : Controller { public IActionResult Tokyo() { return View(); } public IActionResult Nagoya() { return View(); } } }现在我们将创建一个Nagoya.cshtml视图文件在Views->City文件夹,我们简单的显示消息
<h1>Welcome to Nagoya</h1>在应用程序中,下列图片显示了2个View的位置
@if (DateTime.Now.DayOfWeek == DayOfWeek.Monday) { <p>It's a Boring Day</p> } else { <p>It's a Party Day</p> }也可以在视图中添加下面代码
@{ string[] countries = new string[] { "England", "France", "Germany", "China" }; <ul> @foreach (string country in countries) { <li>@countries</li> } </ul> }四. 如何在ASP.NET Core View中调用Action方法
<h1>Welcome to Tokyo</h1> <form asp-controller="City" asp-action="Tokyo" method="post"> <div class="mb-3 row"> <label class="col-sm-1 control-label">名称</label> <div class="col-sm-11"> <input class="form-control" name="name" /> </div> </div> <div class="mb-3 row"> <label class="col-sm-1 control-label">性别</label> <div class="col-sm-11"> <select class="form-control" name="sex"> <option value="F">Female</option> <option value="M">Male</option> </select> </div> </div> <div class="mb-3 row"> <div class="col-sm-11 offset-sm-1"> <button class="btn btn-primary" type="submit">保存</button> </div> </div> </form>注意使用asp-controller="City"和asp-action="Tokyo"这两个帮助标签创建URL,当表单提交时CityController控制器中的Tokyo方法将被调用,method="post"特性告诉action以post方式调用
<form asp-controller="City" asp-action="Tokyo" method="post">这个表单有2个html控件能够输入用户和性别,提交这个表单时,action方法会接收到对应的值
<input class="form-control" name="name" /> <select class="form-control" name="sex"> <option value="F">Female</option> <option value="M">Male</option> </select>现在在CityController中添加一个POST版本的Tokyo方法,代码如下
[HttpPost] public IActionResult Tokyo(string name,string sex) { return View(); }为了获取到这2个值我们需要在控制器中添加2个参数,现在运行应用并且进入URL-https://localhost:7019/City/Tokyo,在表单中输入值并提交你将会在控制器的action方法中获取到该值
public IActionResult CallSharedView() { return View(); }我们把CallSharedView方法代码复制到另外一个控制器中ExampleController.cs 。现在Home和Example控制器中分别有叫CallSharedView方法, 针对这两个action方法我们创建一个共享视图,因此添加一个视图文件在Views->Shared文件夹并且命名为CallSharedView.cshtml , 这个视图的名字和这两个控制器中action方法的名字相同。
<h1>Displaying from Shared View</h1>ASP.NET Core 保证所有的共享视图可用并且确保他们可用,运行应用程序并且在浏览器中打开下面两个连接,这两个连接使用了我们之前创建的2个方法
/Views/<ControllerName>/<ViewName>.cshtml /Views/Shared/<ViewName>.cshtml例如下面AdminController中的List方法,最后一行调用View()方法
public IActionResult List() { return View(); }ASP.NET Core会在下面两个位置查找视图:
/Areas/<AreaName>/Views/<ControllerName>/<ViewName>.cshtml /Areas/<AreaName>/Views/Shared/<ViewName>.cshtml /Views/Shared/<ViewName>.cshtml让我们通过一个例子来了解一下,首先在应用程序的根目录下添加一个新的Areas文件夹,接下来在Areas文件加内添加一个Sales文件夹。在Areas->Sales文件加下添加一个新的AdminController, 在这个控制器中添加一个List方法。
using Microsoft.AspNetCore.Mvc; namespace AspNetCore.Views.Areas.Sales { public class AdminController : Controller { public IActionResult List() { return View(); } } }在Program.cs类中添加区域路由
app.MapControllerRoute( name:"myArea", pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}" );运行应用程序并且在浏览器中打开url-https://localhost:7019/Sales/Admin/List ,我们会看到一个视图文件没有呈现的错误, ASP.NET Core 从下面三个位置搜索视图:
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title> </head> <body> <div> @RenderBody() </div> </body> </html>
正如你清楚的看到它包含了HTML代码块使用了一小部分Razor代码像 @ViewBag.Title 用来设置页面的title,@RenderBody()呈现所有的子视图,不包含Section,让我们先了解Layout是如何工作的。
@{ Layout = "_Layout"; }如果没有_ViewStart.cshtml这个文件,那么我们需要通过在每个视图上添加以下Razor代码来告诉它们默认布局。
@{ Layout = Layout; }因此有这个文件能够移除大量的重复代码,类似的,如果一个应用程序有ViewStart文件,但是不想在视图中应用它,这种情况下在View中添加@{ Layout = null; }
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>@ViewData["Title"]</title> <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" /> </head> <body> <header> <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3"> <div class="container-fluid"> <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">UnderstandingControllersViews</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between"> <ul class="navbar-nav flex-grow-1"> <li class="nav-item"> <a class="nav-link text-dark" asp-controller="Home" asp-action="Index">Home</a> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-controller="City" asp-action="Tokyo">Tokyo</a> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-controller="City" asp-action="Nagoya">Nagoya</a> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-controller="Home" asp-action="CallSharedView">Shared View</a> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-controller="Example" asp-action="CallSharedView">Shared View</a> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-controller="Admin" asp-action="List">Search View</a> </li> <li class="nav-item"> <a class="nav-link text-dark" asp-area="Sales" asp-controller="Admin" asp-action="List">Area View</a> </li> </ul> </div> </div> </nav> </header> <div class="container"> <main role="main" class="pb-3"> @RenderBody() </main> </div> <footer class="border-top footer text-muted"> <div class="container"> ASP.NET Core Site </div> </footer> </body> </html>现在我们为我们应用程序创建一个通用页面,现在我们创建一个新的action方法测试TestLayout页面
public IActionResult TestLayout() { ViewBag.Title = "Welcome to TestLayout"; return View(); }我们设置ViewBag.Title变量,layout将读取这个值并显示当前页面title。
@section Top { <div class="p-3 mb-2 bg-primary text-white">This is Top</div> } @section Bottom { <div class="p-3 mb-2 bg-info text-white">This is Bottom</div> } @section Script { <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> } <h2 class="text-primary">TestLayout starts here</h2> <p class="text-success">This text is coming from child view</p>这些sections可以包含html和razor代码,在这里我们在顶部和底部添加一些简单的DIV,并且引入了脚本段,接下来在应用程序的_Layout.cshtml文件中添加代码呈现这些段落,我们更新一下_Layout.cshmtl文件代码如下:
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>@ViewData["Title"]</title> <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" /> </head> <body> <header> </header> @RenderSection("Top"); <div class="container"> <main role="main" class="pb-3"> @RenderBody() </main> </div> @RenderSection("Bottom") @RenderSection("Script") <footer class="border-top footer text-muted"> <div class="container"> ASP.NET Core Site </div> </footer> </body> </html>运行应用程序并测试:
@section Ads { }我们也可以通过另外一种方式解决这个错误,确保这个段落在layout页面是可选的,使用这个可选段落dotnet会忽略它如果这个段落没有在子视图中定义。
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>堆代码 duidaima.com</title> <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" /> </head> <body> <header> </header> @RenderSection("Top"); <div class="container"> <main role="main" class="pb-3"> @RenderBody() </main> </div> @RenderSection("Bottom") @RenderSection("Ads",false); @RenderSection("Script") <footer class="border-top footer text-muted"> <div class="container"> ASP.NET Core Site </div> </footer> </body> </html>