这是《完全透彻了解一个asp.net core MVC项目模板》的第二篇,如果你直接进入了本篇博文而不知道上下文,请先阅读《完全透彻了解一个asp.net core MVC项目模板》的第一篇。
文章目录
原文出处:
https://haigear.blog.csdn.net/article/details/143316084
一、补充几个问题
1、有关导航链接和Tag Helper
我们在views/share文件夹下看到有两个文件_ViewStart.cshtml、_ViewImports.cshtml和,貌似什么都没有写,就几行引用库文件的代码,尤其第二个文件中有这么一句话:
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
这句话相当的有作用,否则你的导航就不灵了。原因是TagHelper起到了特别的作用,下面我们来介绍一下它的作用。
- Tag Helper的基本原理
- Tag Helpers是ASP.NET Core中的一个强大特性,它允许你在HTML元素上使用自定义属性来生成服务器端代码。
addTagHelper
是在服务配置中用于注册Tag Helper的方法,它使得相关的HTML元素能够被“增强”。 - 以
asp - controller
和asp - action
属性为例,当你在HTML<a>
标签上使用这些属性(如<a asp - controller="Home" asp - action="Index">Home</a>
),如果没有注册相应的Tag Helper,这些属性就只是普通的自定义属性,浏览器不会理解它们的特殊用途。
- Tag Helpers是ASP.NET Core中的一个强大特性,它允许你在HTML元素上使用自定义属性来生成服务器端代码。
- Tag Helper对路由的利用
- 当
addTagHelper
注册了相关的Tag Helper(例如Microsoft.AspNetCore.Mvc.TagHelpers.AnchorTagHelper
用于<a>
标签)后,在服务器端渲染视图时,Tag Helper会介入。它会读取<a>
标签上的asp - controller
和asp - action
属性。 - 然后,根据ASP.NET Core的路由系统,它会将这些属性值转换为一个有效的URL路径。路由系统会查找
Program.cs
(或Startup.cs
)中定义的路由规则(如app.MapControllerRoute
),根据asp - controller
(控制器名称)和asp - action
(动作名称)来生成一个指向正确控制器动作的链接。
- 当
- 与HTML的对比
- 如果没有Tag Helper,
<a>
标签就会按照HTML的标准行为进行处理。HTML标准规定,<a>
标签的href
属性用于指定链接的目标URL。当没有href
属性,只有文本内容时,浏览器会将其视为普通文本,而不会将其识别为一个可以点击的链接。 - Tag Helper实际上是在服务器端为
<a>
标签动态地生成了一个合适的href
属性(或者以其他符合HTML标准的方式来创建链接),从而使得在浏览器中呈现的<a>
标签能够正确地作为一个链接,引导用户访问指定的控制器和动作。
- 如果没有Tag Helper,
2、_ViewStart.cshtml与视图引擎加载过程
这个文件更简单了,其实它的作用就是调用layout文件。开始渲染,代码如下:
@{
Layout = "_Layout";
}
没有什么可讲解的。倒是视图引擎的加载过程有必要在这里说一说:
程序页面开始时视图引擎控制首先加载viewstart文件(从名字上就可以看出来,老版本的dotnet core 项目有一个startup.cs的文件,现在合并到program中去了,这个viewstart文件还留着,估计下次升级也会被合并掉)。在_ViewStart.cshtml文件(通常位于Views文件夹下)中有对布局文件的引用,如@{Layout = “~/Views/Shared/_layout.cshtml”;}。这告诉视图引擎在渲染任何视图时,都要使用这个布局文件作为模板。
当Index.cshtml被请求时,视图引擎首先加载_layout.cshtml,然后将Index.cshtml的内容插入到_layout.cshtml中定义的@RenderBody()位置。@RenderBody()是一个占位符,用于放置具体视图的内容。所以,导航栏部分(包含标签)是布局文件本身的一部分,会在每次渲染视图时一起显示在页面顶部,为用户提供导航链接。
二、model的建立和使用
1、Error.cshtml
在上一篇博文中,我们说过views\share文件夹下的Error.cshtmlh和_ValidationScriptsPartial.cshtml需要配合models来讲解。那么我们现在来看看,为什么,首先我们来看看Error.cshtml的代码:
@model ErrorViewModel
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>
它的第一行就开始引入了模型,在下面还是用到了模型的ShowRequestID属性:
if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
2、ErrorViewModel.cs
这个文件是models文件夹下面唯一的文件,我们来看看代码
namespace WebApplicationDemo.Models
{
public class ErrorViewModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
}
}
其实,这个model文件普通得再普通不过了,就定义了一个属性和一个方法。很基础的C#知识,这里就不逐句讲解了。
原文出处:
https://haigear.blog.csdn.net/article/details/143316084
三、来一个自己的页面
1、建立模型文件
模型文件我们还是用前面博文《
一步一步从微信小程序获取asp.net Core API的数据中》使用过的Personalinfo的模型,可以直接拷贝过来
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
namespace WebApplicationDemo.Models
{
public class PersonalInfo
{
[Required]
[StringLength(50)]
[DefaultValue("张三")]
public string? Name { get; set; }
[Required]
[Range(0, 150)]
[DefaultValue(24)]
public int? Age { get; set; }
[Required]
[StringLength(10)]
[DefaultValue("男")]
public string? Gender { get; set; }
[Required]
[EmailAddress]
[DefaultValue("[email protected]")]
public string? Email { get; set; }
[Required]
[Phone]
[DefaultValue("13788888888")]
public string? PhoneNumber { get; set; }
[Required]
[DataType(DataType.Date)]
[DefaultValue("2000-01-01")]
public DateTime BirthDate { get; set; }
[Required]
[StringLength(100)]
[DefaultValue("张家口市张家镇张家村张家冲21号")]
public string? Address { get; set; }
[StringLength(50)]
[DefaultValue("码农")]
public string? Occupation { get; set; }
[Required]
[StringLength(30)]
[DefaultValue("China")]
public string? Nationality { get; set; }
}
}
2、建立视图页面
有了模型了,我们就可以利用VS的向导来直接建立一个视图页面,在Views文件夹上右键菜单,选择添加“视图”:
添加视图时,选在模板Details,省得自己写代码,同时别忘记选择我们刚刚前面建立的模型类Personalinfo,选择好后一键生成即可得到视图文件了:
生成的页面代码自己如下:
@model WebApplicationDemo.Models.PersonalInfo
@{
ViewData["Title"] = "View";
}
<h1>View</h1>
<div>
<h4>PersonalInfo</h4>
<hr />
<dl class="row">
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Name)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Name)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Age)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Age)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Gender)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Gender)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Email)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Email)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.PhoneNumber)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.PhoneNumber)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.BirthDate)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.BirthDate)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Address)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Address)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Occupation)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Occupation)
</dd>
<dt class = "col-sm-2">
@Html.DisplayNameFor(model => model.Nationality)
</dt>
<dd class = "col-sm-10">
@Html.DisplayFor(model => model.Nationality)
</dd>
</dl>
</div>
<div>
@Html.ActionLink("Edit", "Edit", new { /* id = Model.PrimaryKey */ }) |
<a asp-action="Index">Back to List</a>
</div>
我们发现,其实这个页面与前面我们介绍的index.cshtml页面没有什么差别,差别在@后面,大量的使用了Html关键字而不是MOdel,最后个div中包含了一个@Html.ActionLink(“Edit”, “Edit”, new { /* id = Model.PrimaryKey */ }) 我们来一起看看这些是什么意思?
关于Html.DisplayFor
a、DisplayFor方法简介
- @Html.DisplayFor是ASP.NET MVC 和ASP.NET Core MVC 中常用的一个 HTML 辅助方法(HTML Helper)。它主要用于在视图中显示模型(model)的某个属性(在这个例子中是Nationality属性)的值。
- 表达式语法(model => model.Nationality)的作用
这里的model => model.Nationality是一个 Lambda 表达式。它指定了要显示的模型属性。前面的model.Nationality,model.Occupation,model.Name,model.Age都采用的这样方法来显示。
具体来说,model代表视图中的模型对象(这个对象是由控制器传递给视图的)。=>是 Lambda 表达式的操作符,model.Nationality表示要获取模型对象的Nationality属性。这个 Lambda 表达式告诉DisplayFor方法具体要显示模型中的哪个属性。
b、工作原理
当视图被渲染时,DisplayFor方法会根据模型对象的类型和Nationality属性的类型来决定如何显示这个属性的值。
例如,如果Nationality是一个简单的字符串类型(如 “Chinese”),它可能会直接将这个字符串显示在页面上。如果Nationality是一个复杂的对象,DisplayFor可能会根据对象的ToString方法或者其他自定义的显示逻辑来呈现它的值。
另外,DisplayFor方法还会考虑数据注解(Data Annotations)等因素。如果在模型类的Nationality属性上有[DisplayFormat]或其他相关的数据注解,DisplayFor会按照注解的要求来显示属性值,例如按照指定的日期格式显示日期属性,或者按照指定的文本格式显示数值属性等。。
关于Html.ActionLink
a. @Html.ActionLink
的作用
- 和前面的Html.Dispplayfor一样
@Html.ActionLink
也是一个HTML辅助方法(HTML Helper),它的主要作用是生成一个HTML超链接(<a>
标签)。 - 在这个例子中,
@Html.ActionLink("Edit", "Edit", new { /* id = Model.PrimaryKey */ })
会生成一个链接,链接的文本是“Edit”。它会将用户引导到名为“Edit”的操作(通常是控制器中的一个方法),并且在理想情况下,会将与当前模型相关的主键(这里代码被注释掉了,假设是Model.PrimaryKey
)作为参数传递过去。
b. 为什么是@Html.ActionLink
而不是@Model.ActionLink
- 首先,
Model
通常代表视图模型对象,它的主要目的是在视图和控制器之间传递数据,如业务逻辑相关的数据、状态信息等。它一般不包含用于生成HTML链接的方法。 - 而
@Html.ActionLink
是由ASP.NET提供的HTML辅助方法,它属于System.Web.Mvc.Html
命名空间(在旧版本的MVC中)或者相关的ASP.NET Core命名空间。这些HTML辅助方法是为了方便在视图中生成各种HTML元素,利用了ASP.NET的路由系统和内部逻辑来构建正确的链接,这是一种与视图渲染和路由相关的功能,不是视图模型本身应该承担的职责。
如果我们此时调整好homecontroller中的路由访问的话(具体如何调整,可以参本章的4小节“看看效果”),得到的是一个没有任何信息的浏览页
所以,我们需要给它配上一个控制器来显示数据。
3、建立控制器
与建立视图文件一样,在controllers文件件上右键菜单,选择添加“控制器”,选择
打开文件,修改代码为
using Microsoft.AspNetCore.Mvc;
using WebApplicationDemo.Models;
namespace WebApplicationDemo.Controllers
{
public class PersonalInfoController : Controller
{
public IActionResult Index()
{
var personalInfo = new PersonalInfo
{
Name = "张三",
Age = 24,
Gender = "男",
Email = "[email protected]",
PhoneNumber = "13788888888",
BirthDate = new DateTime(2000, 1, 1),
Address = "张家口市张家镇张家村张家冲21号",
Occupation = "码农",
Nationality = "China"
};
return View(personalInfo);
}
}
}
如果,我们此时运行程序观察效果,一定还是与原来一样,根本没任何改变,那么问题出在哪里呢??
有可能遇到的问题
按照ASP.NET Core MVC 的约定,视图文件的名称通常应该与控制器方法的名称相同。并且视图文件应该位于Views文件夹下的与控制器名称对应的子文件夹中
1、如果控制器是PersonalInfoController,视图文件应该在Views/PersonalInfo文件夹中,不能随便乱丢在其他文件件中。
2、控制器方法是Index,视图文件应该是Index.cshtml。我们这个项目的PersonalinfoController中的方法是Index,所以视图文件名称就是index.cshtml。不用怀疑,我们每个文件夹中都可以拥有一个index.cshtml,而不是以前我们写网站时一个网站只有一个index.asp/index.jsp/index.html。
保证上述问题后,基本就可以得到正确的浏览结果了。
看效果之前,我们也在导航中把我们的页面给挂上去,这样才能和现在的项目融为一体。那么我们需要干两件事:
a、在layout文件中增加一个链接
参照第一篇博文,找到layout中的nav标签,然后在其中增加下面的内容即可:
<li class="nav-item">
<a class="nav-link text-dark" asp-area="" asp-controller="PersonalInfo" asp-action="index">PersonalInfo</a>
</li>
看看效果
好了,到这里,我们的《完全透彻了解一个asp.net core MVC项目模板》算是完整了,感兴趣的同学可以继续关注我的博客。
原文出处:
https://haigear.blog.csdn.net/article/details/143316084