0
点赞
收藏
分享

微信扫一扫

ASP.NET Core入门级教程_上篇


ASP.NET Core

  • ​​运行 ASP.Net Core项目的两种方式​​
  • ​​托管设置​​
  • ​​中间件​​
  • ​​静态文件支持​​
  • ​​首先​​
  • ​​DirectoryBrowser 中间件​​
  • ​​FileServer 中间件​​
  • ​​开发者异常页面​​
  • ​​开发环境变量​​
  • ​​引入MVC框架​​
  • ​​首先添加 MVC 服务​​
  • ​​添加中间件​​
  • ​​初步了解模型和依赖注入​​
  • ​​定义模型​​
  • ​​定义接口​​
  • ​​实现接口​​
  • ​​注册依赖注入​​
  • ​​在模型中使用依赖注入​​
  • ​​控制器​​
  • ​​内容格式协商​​
  • ​​视图​​
  • ​​将数据从控制器传递到视图的方法​​
  • ​​ViewData​​
  • ​​ViewBag​​
  • ​​强类型视图​​
  • ​​ViewModel 视图模型​​
  • ​​定义ViewModel​​
  • ​​修改控制器​​
  • ​​在View中使用​​
  • ​​View中使用循环​​
  • ​​布局视图 LayoutView​​
  • ​​创建布局视图​​
  • ​​渲染视图​​
  • ​​视图节点 Section​​
  • ​​视图开始 ViewStart​​
  • ​​视图导入 ViewImports​​
  • ​​路由​​
  • ​​常规路由​​
  • ​​属性路由​​
  • ​​TagHelper​​
  • ​​环境 TagHelper​​
  • ​​表单 Tag Helper​​

运行 ASP.Net Core项目的两种方式

  • 使用 visual studio IED启动运行
  • 命令行方式:
  • 在 Web 项目所在的文件夹中运行:​​dotnet run​

托管设置

设置项目文件的​​AspNetCoreHostingModel​​属性

<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>

  • InProcess:使用IIS服务器托管
  • OutOfProcess:使用自带Kestrel服务器托管

中间件

  • 可同时被访问和请求
  • 可以处理请求后,将请求传递给下一个中间件
  • 可以处理请求后,使管道短路
  • 可以传出响应
  • 中间件是按照添加顺序执行的

通过在​​Configure​​​中添加参数​​ILogger<Startup> logger​​引入Asp.Net Core自带的日志组件。

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILogger<Startup> logger)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseStaticFiles();

app.Use(async (context, next) =>
{
context.Response.ContentType = "text/plain;charset=utf-8";

//await context.Response.WriteAsync("Hello!");

logger.LogDebug("M1: 传入请求");
await next();
logger.LogDebug("M1: 传出响应");
});


app.Use(async (context, next) =>
{
context.Response.ContentType = "text/plain;charset=utf-8";

logger.LogDebug("M2: 传入请求");
await next();
logger.LogDebug("M2: 传出响应");
});

app.Run(async (context) =>
{
//await context.Response.WriteAsync("你好!");
await context.Response.WriteAsync("M3: 处理请求,生成响应");
logger.LogDebug("M3: 处理请求,生成响应");
});
}

静态文件支持

  • 所有静态文件都在目录​​wwwroot​​下

首先

// 设置默认文件
// 不设置的话,默认就是index.html/default.html这几个
var defaultFileOpinions = new DefaultFilesOptions();
defaultFileOpinions.DefaultFileNames.Clear();
defaultFileOpinions.DefaultFileNames.Add("test.html");

// 添加默认文件中间件,必须在UseStaticFiles之前注册
app.UseDefaultFiles(defaultFileOpinions);

// 添加静态文件中间件
app.UseStaticFiles();

DirectoryBrowser 中间件

可以在浏览器浏览 ​​wwwroot​​​ 下的内容。不推荐在生产环境中使用
​​​app.UseDirectoryBrowser();​

FileServer 中间件

集成了​​UseDefaultFiles​​​, ​​UseStaticFiles​​​, ​​UseDirectoryBrowser​​三个中间件的功能。同样不推荐在生产环境中使用

var fileServerOpinions = new FileServerOptions();
fileServerOpinions.DefaultFilesOptions.DefaultFileNames.Clear();
fileServerOpinions.DefaultFilesOptions.DefaultFileNames.Add("test.html");

app.UseFileServer(fileServerOpinions);

开发者异常页面

if (env.IsDevelopment())
{
var developerExceptionPageOptions = new DeveloperExceptionPageOptions();
// 显示代码行数
developerExceptionPageOptions.SourceCodeLineCount = 10;
app.UseDeveloperExceptionPage();
}

app.Run(async (context) =>
{
throw new Exception("自己抛出的异常");
});

开发环境变量

  • Development:开发环境
  • Staging:演示(模拟、临时)环境
  • Production:正式(生产)环境

ps:

  • 使用​​ASPNETCORE_ENVIRONMENT​​环境变量设置开发环境。
  • 在开发机上,在​​launchSettings.json​​文件中设置环境变量。
  • 在Staging和Production环境时,尽量在操作系统设置环境变量。
  • 使用​​IHostEnvironment​​服务访问运行时环境
  • 除了标准环境之外还支持自定义环境(UAT、QA等)

引入MVC框架

首先添加 MVC 服务

public void ConfigureServices(IServiceCollection services)
{
// 单纯引入核心MVC服务,只有核心功能
services.AddMvcCore();
// 一般用这个,功能多
services.AddMvc();
}

添加中间件

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILogger<Startup> logger)
{
if (env.IsDevelopment())
{
var developerExceptionPageOptions = new DeveloperExceptionPageOptions();
// 显示代码行数
developerExceptionPageOptions.SourceCodeLineCount = 10;
app.UseDeveloperExceptionPage();
}

app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
}

MVC路由规则:/控制器名/方法名(不区分大小写)

初步了解模型和依赖注入

定义模型

public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public string ClassName { get; set; }
public string Email { get; set; }
}

定义接口

public interface IStudentRepository
{
Student GetById(int id);
void Save(Student student);
}

实现接口

模拟数据

public class MockStudentRepository : IStudentRepository
{
private List<Student> _students;

public MockStudentRepository()
{
_students = new List<Student>
{
new Students(){Id=1,Name="张三",ClassName="一年级",Email="Tony-Zhang@52abp.com"},
new Students(){Id=2,Name="李四",ClassName="二年级",Email="Lisi@52abp.com"},
new Students(){Id=3,Name="王二",ClassName="二年级",Email="Wang@52abp.com"},
};
}

public Student GetById(int id)
{
return _students.FirstOrDefault(a => a.Id == id);
}

public void Save(Student student) => throw new NotImplementedException();
}

注册依赖注入

​​http://Asp.Net​​ Core依赖注入容器注册服务有三种

  • AddSingleton
  • AddTransient
  • AddScoped

依赖注入的优点

  • 低耦合
  • 高测试性,更加方便进行单元测试

public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
// 注册依赖注入,将实现类与接口绑定
services.AddSingleton<IStudentRepository, MockStudentRepository>();
}

在模型中使用依赖注入

public class StudentController : Controller
{
private readonly IStudentRepository _studentRepository;

// 通过构造函数注入的方式注入 IStudentRepository
public StudentController(IStudentRepository studentRepository)
{
_studentRepository = studentRepository;

}

public JsonResult Index(int id)
{
return Json(_studentRepository.GetById(id));
}
}

控制器

内容格式协商

在控制器方法中使用 ​​ObjectResult​​ 返回类型,支持内容协商,根据请求头参数返回数据,

// 支持内容格式协商
public ObjectResult Details(int id)
{
return new ObjectResult(_studentRepository.GetById(id));
}

如:​​Accept: application/xml​

将返回xml格式 注:还要添加xml序列化器

public void ConfigureServices(IServiceCollection services)
{
// 注册XML序列化器
services.AddMvc().AddXmlSerializerFormatters();
}

视图

将数据从控制器传递到视图的方法

前两种都是弱类型的

  • ViewData
  • ViewBag
  • 强类型视图

ViewData

  • 弱类型字典对象
  • 使用string类型的键值,存储和chaxun
  • 运行时动态解析
  • 没有智能感知,编译时也没有类型检查

使用方法:

ViewData["Title"] = "学生视图";
ViewData["Model"] = model;

.cshtml代码:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<h1>@ViewData["Title"]</h1>
@{
var student = ViewData["model"] as StudyManagement.Models.Student;
}
<div>姓名:@student.Name</div>
<div>班级:@student.ClassName</div>
</body>
</html>

ViewBag

// 直接给动态属性赋值
ViewBag.PageTitle = "ViewBag标题";
ViewBag.Student = model;

.cshtml使用:

<h1>@ViewBag.PageTitle</h1>
<div>姓名:@ViewBag.Student.Name</div>
<div>班级:@ViewBag.Student.ClassName</div>

强类型视图

在控制器中传给View()模型

public IActionResult GetView()
{
var model = _studentRepository.GetById(1);
return View(model);
}

在.cshtml中指定模型类型

@model StudyManagement.Models.Student
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<h1>强类型模型</h1>
<ul>
<li>@Model.Id</li>
<li>@Model.Name</li>
<li>@Model.ClassName</li>
<li>@Model.Email</li>
</ul>

</body>
</html>

ViewModel 视图模型

类似于DTO(数据传输对象)

定义ViewModel

public class StudentDetailsViewModel
{
public Student Student { get; set; }
public string PageTitle { get; set; }
}

修改控制器

public IActionResult Details()
{
var model = _studentRepository.GetById(1);
var viewModel = new StudentDetailsViewModel
{
Student = model,
PageTitle = "viewmodel里的页面标题"
};
return View(viewModel);
}

在View中使用

<!-- 这里注册的模型改成了ViewModel了 -->
@model StudyManagement.ViewModels.StudentDetailsViewModel
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<h1>强类型模型</h1>
<h2>@Model.PageTitle</h2>
<ul>
<li>@Model.Student.Id</li>
<li>@Model.Student.Name</li>
<li>@Model.Student.ClassName</li>
<li>@Model.Student.Email</li>
</ul>
</body>
</html>

View中使用循环

@model IEnumerable<StudyManagement.Models.Student>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<table border="1">
<tr>
<td>Id</td>
<td>姓名</td>
<td>班级</td>
<td>邮箱</td>
</tr>
@foreach (var student in Model)
{
<tr>
<td>@student.Id</td>
<td>@student.Name</td>
<td>@student.ClassName</td>
<td>@student.Email</td>
</tr>
}
</table>
</body>
</html>

布局视图 LayoutView

创建布局视图

<!DOCTYPE html>

<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
</head>
<body>
<div>
@RenderBody()
</div>

@RenderSection("Scripts", required: false)
</body>
</html>

渲染视图

@model IEnumerable<StudyManagement.Models.Student>
@{
Layout = "~/Views/Shared/_Layout.cshtml";
ViewBag.Title = "首页 学生列表";
}
<div></div>

视图节点 Section

在布局视图里渲染节点

​@RenderSection("Scripts", required: false)​

在普通视图里定义节点

@section Scripts{ 
<script>
document.write("hello");
</script>
}

视图开始 ViewStart

一般直接放在​​Views​​​目录下,全局生效,支持分层,可以放在各个子文件夹下,这样可以覆盖全局的​​_ViewStart.cshtml​

@{
Layout = "_Layout";
}

视图导入 ViewImports

用来导入命名空间、注册模型等等n多种操作
生效机制和ViewStart差不多

路由

  • 常规路由(传统路由)
  • 属性路由

常规路由

MapRoute方法中传入

// 自定义路由
app.UseMvc(route =>route.MapRoute("default","{controller=Home}/{action=Index}/{id?}"));

属性路由

  • 比传统路由更加灵活,可以搭配传统路由使用
  • 即在控制器方法上添加路由注解,一个方法可以同时映射多个路由

[Route("Home/Index")]
public IActionResult Index()
{
return View(_studentRepository.GetAll());
}

路由中也可以指定参数

[Route("test/{id?}")]
public IActionResult Details(int id = 1)
{
var model = _studentRepository.GetById(id);
var viewModel = new StudentDetailsViewModel
{
Student = model,
PageTitle = "viewmodel里的页面标题"
};
return View(viewModel);
}

可以直接在控制器类上加注解:​​[controller]/[action]​

实际开发项目中多采用 常规路由 + 属性路由 结合使用

TagHelper

优点:根据参数自动生成,不需要手写超链接,类似Django模板里面的url命令

在ViewImport中添加TagHelper

@addTagHelper *,Microsoft.AspNetCore.Mvc.TagHelpers

比如,链接TagHelper使用

<a class="btn btn-outline-primary" asp-controller="student" asp-action="get" asp-route-id="@student.Id">查看</a>

缓存破坏的TagHelper

<img src="~/images/banner.jpg" alt="Alternate Text" asp-append-version="true" />

环境 TagHelper

在开发环境中使用本地.css文件,在非开发环境下使用的是CDN的.css文件

integrity是用来做完整性检查的,保证CDN提供文件的完整和安全

<environment include="Development">
<link href="~/lib/twitter-bootstrap/css/bootstrap.css" rel="stylesheet" />
</environment>

<environment exclude="Development">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</environment>

为了防止CDN加载失败页面无法显示,可以加上fallback相关属性,第一个是失败时加载的文件,第二个是不检查这个文件的完整性

asp-fallback-href="~/lib/twitter-bootstrap/css/bootstrap.css"
asp-suppress-fallback-integrity="true"

表单 Tag Helper

直接贴上一个布局的代码,把class样式都去掉了,保留最基本代码。

确实是很方便的,和Django、jinja2之类的模板比完全不输。

@model Student

<form asp-controller="student" asp-action="create">
<label asp-for="Name"></label>
<input asp-for="Name" />

<label asp-for="Email"></label>
<input asp-for="Email" />

<label asp-for="ClassName"></label>
<select asp-for="ClassName" asp-items="Html.GetEnumSelectList<ClassNameEnum>()"></select>

<button type="submit">提交</button>
</form>


举报

相关推荐

0 条评论