说明:在ASP.NET core WebApi的基础上,加一个View,重点在TagHelper。
|
和WebApi相比,就多一个Views文件夹。 另:Startup.ConfigureServices()中: services.AddControllersWithViews()多一个WithViews。
|
也可以使用特性[Route],但推荐在Startup.Configure()的app.UseEndpoints()中配置:
app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "category", pattern: "/Article/Category{id:int}", defaults: new { Controller = "Article", Action = "Category" });
对比Framework,就约束不一样(演示),不再使用:
当路由规则出现冲突时,以下规则进行:
//URL: /Article/Category-New/12 endpoints.MapControllerRoute( name: "category-id", pattern: "/Article/Category-{id}", defaults: new { Controller = "Article", Action = "Category" }); endpoints.MapControllerRoute( name: "category-action", pattern: "/Article/Category-{action}/{id?}", defaults: new { Controller = "Article" });
优先级从高到底:
/Article/Category/{id} /Article/Category /Article/Category-{id} /* complex segement*/ /Article/{category:int} /Article/{category} /{article}/{category}
演示:(智能提示)
<img asp-append-version="true" src="~/images/banner1.svg" />
生成如下HTML内容:(@想一想@:添加的url参数v和它的值,这是干嘛的呢?复习:浏览器缓存)
<img src="/images/banner1.svg?v=GaE_EmkeBf-yBbrJ26lpkGd4jkOSh1eVKJaNOw9I4uk" />
这种被高亮加粗显示(演示:智能提示),可以使用 “asp-” 开头属性的标签,会在服务器端“转换”后发送到客户端,被称之为TagHelper —— 类似于Framework中的HtmlHelper(复习:@Html.XXX()),而且在core中HtmlHelper是一样可以使用的!
注意:
相较于HtmlHelper,使用Tag Helper更好看(HTML-friendly)一些。
牢记:Tag Helper只负责在服务器端生成HTML代码!浏览器不会接收到包含 asp-append-version等属性的HTML内容
PS:超链接(Anchor Tag Helper)价值不大,略。
复习:ASP.NET响应的不是.cshtml文件,而是ASP.NET(根据.cshtml内容)生成对象的方法返回值……
演示:位于obj/<build_configuration>/<target_framework_moniker>/Views文件夹
为什么@{}和@functions{}有不同的作用域
<form asp-action="Index" asp-controller="Register" asp-route-id="12" asp-route-name="fg">从2.0版本开始,当form元素中:
TagHelper可以根据属性类型和DataAnnotations自动推断:
public class UserModel { public string Name { get;set; } [DataType(DataType.Password)] public string Password { get;set; } public bool IsMale { get;set; }
当属性类型为string类型时,默认生成文本输入框:
<input asp-for="Name" />
还可以生成密码框:
<input asp-for="Password" />
使用textarea生成多行文本输入。
<textarea asp-for="SelfDescription"></textarea>生成的HTML标签上添加id、name和model验证属性……
checkbox:当属性类型为bool值时,默认生成的就是checkbox
radio:需要在标签中声明type="radio"
<select asp-for="BirthMonth" asp-items="Model.AvailableMonths"></select>
@for (int i = 0; i < Model.Messages.Count; i++) { <label>@i <input type="checkbox" asp-for="Messages[i].Seleted" /></label> <input asp-for="Messages[i].Id" type="hidden" /> <br /> }
<span asp-validation-for="PhoneNumber"></span>
<label asp-for="SelfDescription"></label>生成的HTML标签上会有一个 for="SelfDescription" 的属性。有趣的是,还可以同时生成文本:
<label for="SelfDescription">自我介绍</label>这其实是因为我们在PageModel的SelfDescription属性上声明了特性:(没有声明的话直接使用属性名)
[Display(Name = "自我介绍")]
<button asp-controller="Log" asp-action="On" type="submit" >提交</button>生成:
<button type="submit" formaction="/Log/On">提交</button>
参考:
创建过程,和之前Framework一样……
在父页面使用Partial Tag Helper:
<partial name="_Keywords.cshtml"/>
name后面指定viewName即可,一样可以使用“相对(名称)/绝对(路径)”两种方式……
注意这里的partial是异步呈现的,core中如果使用@Html.Partial()也应该异步:
@await Html.PartialAsync("_Keyword")
因为core中整个view的呈现都是异步的。抛异常演示:
AspNetCore.Views_Home_Index.ExecuteAsync() in Index.cshtml
这两种写法是等价的:
<partial name="_Keyword" model="Model.Keywords"/> <partial name="_Keyword" for="Keywords" />
for和model的作用一样,都是向PartialPage传递一个model数据。
类似于@Html.Action(),但差别比较大……
最大的好处就是:不受Filter影响,这样ContextPerRequest等技术就便于实施了……
声明一个类,让这个类继承ViewComponent,然后在类中添加一个Invoke()方法
public class LogonStatus : ViewComponent { public IViewComponentResult Invoke(int? id) { //HttpContext.Session //Request.Query return View("_Keyword", "大飞哥"+id);
所以,Invoke()前面不要加override之类的,另外注意:
Invoke()方法当中,可以使用ViewComponent的大量属性方法,添加各种逻辑等。
但没有Response.XXX,因为ViewComponent不能独立的响应HTTP请求(和Framework不一样!)所以Filter对ViewComponent也不起作用。
@想一想@:这样好不好?
#体会#:单一职责
除了继承,还有另外两种方式可以定义一个ViewComponent类
[ViewComponent] public class _LogOnStatus
public class _LogOnStatusViewComponent
但一般我们并不推荐,因为这样不能方便的使用ViewComponent基类的属性(如HttpContext)和方法(如:View())
首先,要在_ViewImports.cshtml中添加一行代码:
@addTagHelper *, Yz17bangMVC
Yz17bangMVC是当前程序集的名称,这行代码的意思是:把Yz17bangMVC中所有TagHelper引入(import)到view。
PS:_ViewImports.cshtml中还可以进行其他设置……
然后就可以在父页面使用vc:调用:
<vc:logon-status id="2"></vc:logon-status>
logon-status是LogonStatus的“异形”,razor会自动在两者之间转换。
将需要缓存的页面内容直接包裹在cache标签中:(同Framework的[OutputCache])
<cache expires-sliding="TimeSpan.FromSeconds(100)" vary-by-route="id" vary-by-query="name" priority="CacheItemPriority.NeverRemove" > <h2> @DateTime.Now</h2> </cache>常用属性:
其他参考:Cache Tag Helper
参考MVC Framework完成
多快好省!前端后端,线上线下,名师精讲
更多了解 加: