ASP.NET Core 3.x 入门(一)创建项目 和 部署
此入门教程是记录下方参考资料视频的学习过程
开发工具:Visual Studio 2019
参考资料:https://www.bilibili.com/video/BV1c441167KQ
API文档:https://docs.microsoft.com/zh-cn/dotnet/api/?view=aspnetcore-3.1
目录
项目结构
ASP.NET Core 本质是一个控制台项目
Program.cs
主函数调用 CreateHostBuilder
静态方法,返回之后调用 Build
方法,最后调用 Run
方法运行
Startup.cs
调用顺序 ConfigureServices
-> Configure
ConfigureServices
主要是负责配置依赖注入相关的东西
依赖注入(Dependency Injection)
IoC容器(Inversion of Control,控制反转)
1. 注册(Service)
2. 请求实例
3. 实例的生命周期,由容器控制
1. Transient,注册的服务每次被请求都会生成一个新的实例
2. Scoped,一次Web请求产生一个实例,Web请求被处理完,生命周期就截止
3. Singleton,服务的实例一旦被创建,那么以后所有请求这个服务的时候都会只用这一个实例,直到应用程序停止
我们可以在 ASP.NET Core 应用启动的时候,在 Startup 类中的 ConfigureServices
里注册一些服务,注册在IoC容器中
使用 IServiceCollection
来注册服务
比如,我们需要使用MVC
public void ConfigureServices(IServiceCollection services)
{
//注册 MVC 服务
//services.AddMvc();//功能过于强大,本例不使用
//services.AddControllers();//没有视图,做API时使用
services.AddControllersWithViews();
}
如果使用我们自定义的服务
涉及到的方法:
- services.AddTransient<>();
- services.AddScoped<>();
- services.AddSingleton<>();
在项目下新建一个 Services 文件夹,新建一个 IClock 接口,再创建 ChinaClock 和 UtcClock 两个类去实现 IClock 接口
public void ConfigureServices(IServiceCollection services)
{
//注册我们写的服务
//IClock 适合使用 Singleton
services.AddSingleton<IClock, ChinaClock>();
//每当有其它类型请求实现了 IClock 的对象的时候,IoC容器就会返回一个 ChinaClock 对象
}
使用服务
在项目下新建一个 Controllers 文件夹,新建一个 HomeController 类,继承 Controller
public class HomeController : Controller
{
//构造函数注入
//如果参数的类型注册到IoC容器里面,那么我们的 ASP.NET Core 应用就会返回具体的类
public HomeController(IClock clock)
{
}
}
如果需要修改注册的服务类,只需要修改 Startup 中的代码
依赖注入的优点:
- 解耦,没有强依赖
利于单元测试 - 不需要了解具体的服务类
- 也不需要管理服务类的生命周期
Startup.cs
Configure
-
Configure
方法配置了 ASP.NET Core 针对处理 Http 请求的管道(pipeline)
管道会指定整个应用对 Http 请求是如何进行响应当 ASP.NET Core 应用从浏览器接收到 Http 请求之后,这个请求是从管道里出来的,然后处理完之后再从管道回去
如果管道里什么都没有,那么这个请求就什么都不会发生
放在管道中处理请求的东西叫中间件(Middleware),- MVC 其实就是一个中间件
- 通常会在 MVC 之前进行身份认证,所以身份认证的中间件通常放在 MVC 前面
- 而在 ASP.NET Core 中,访问静态文件(js、html、css),也需要一个中间件,StaticFiles
在 Http 请求进来时,我们可以看到请求的数据和 Web Server 相关的东西(特性),我们可以利用中间件对这些进行处理,比如写入
IApplicationBuilder 对应了一个服务,通过依赖注入的方式注入,注入使用的是对应的接口
IWebHostEnvironment 也是同理 -
Configure
方法还有一个动作,路由app.UseDeveloperExceptionPage()
,开发模式中间件
如果我们的程序发生了一些异常,并且这个异常没有被做处理或捕获的话,那么就会把异常和错误信息展示到一个页面里,这个页面会有详细信息
if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); }
常用的环境(在项目属性的调试选项中修改):
env.IsDevelopment()
:开发环境env.IsProduction()
:生产环境env.IsStaging()
:模拟环境env.IsEnvironment()
:自定义环境
-
app.UseRouting()
,路由中间件,如果不是开发模式,那么这就是第一个中间件
在 ASP.NET Core 3.0 之前,路由中间件是 MVC 中间件的一部分,而在 3.0 里可以配合其它中间件使用端点(endpoint)
-
端点就是进来的 Http 请求的 url 的结尾那部分,这部分会被中间件进行处理
-
/{controller}/
-
/home/index
为什么需要把路由中间件从MVC中间件中单独取出来?
答:ASP.NET Core 应用的多样性,都需要路由 -
MVC:/Home/Index
-
Razor Pages:/SomePage
-
SignalR:/Hub/Chat
路由中间件在管道中会检查在应用中已经注册的端点,这些端点有可能是被 MVC 框架注册的,也有可能是 Razor Pages 或 SignalR 注册的,路由中间件就会判断进来的 Http 请求是哪个端点上出现的(这是条重要信息),就可以让后续的中间件知道这条消息
-
-
app.UseEndpoints()
,端点中间件
这个中间件可以注册这个 Http 请求的端点,当请求到达这里时,就会被相应的端点进行处理
app.UseEndpoints(endpoints =>
{
// 以“/”结尾的 url ,映射到lambda表达式里
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
因为我们使用 MVC ,所以可以改成这样
app.UseEndpoints(endpoints =>
{
//如果 controller 不输入就走 Home ,action 不输入就走 Index
//这样相当于注册了一个路由模板,其实可以注册多个路由模板
//在 Controller 或 Action 上写属性标签,也可以进行路由配置,就不需要这里配置,只要使用 endpoints.MapControllers(),没有参数的,就可以了
endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id}");
});
-
app.UseStaticFiles()
,静态文件中间件,不使用这个中间件就不能从客户端访问静态文件
这个中间件可以放在app.UseRouting()
之前,因为它不需要知道路由信息 -
app.UseAuthentication()
,身份认证中间件
这个中间件必须放在app.UseEndpoints
前面,因为我们想在 MVC 或者是 Razor Pages 这些框架之前把身份认证做完 -
app.UseHttpsRedirection()
,可以把 Http 请求转化为 Https 请求
运行 ASP.NET Core 应用
- IIS Express
- 解决方案名称,以 ASP.NET Core 本身(控制台)来运行,内置了 Kestrel,可以看到控制台信息,所以我们使用这个
Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
//使用 Kestrel,可以不写,默认配置里已经调用了
webBuilder.UseKestrel();
});
也可以右键项目 》 属性 》 调试,修改配置(启动浏览器和环境等选项)
还可以在 解决方案 》 项目 》 Properties 》 launchSetting.json 中配置
可以在 Startup.cs 中单独配置环境,命名约定是 Configure+环境名称,就不再通过 Configure
方法,ConfigureServices也可以这样使用
public void ConfigureServicesDevelopment(IServiceCollection services)
{
}
public void ConfigureDevelopment(IApplicationBuilder app, IWebHostEnvironmernt env)
{
}
甚至 Startup 类也可以,但是在 Program.cs 中的 CreateHostBuilder 中也需要对应修改
public class StartupDevelopment
{
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup(typeof(Program));
});
静态文件
静态文件都应该放到项目下的 wwwroot 文件夹下
包管理
- 服务器端(后端):NuGet
- 前端:Npm
安装 bootstrap
- 在项目下新建 npm 文件,就叫 package.json
- 在
devDependencies
编写
{
"version": "1.0.0",
"name": "asp.net",
"private": true,
"devDependencies": {
"bootstrap": "4.3.1"
}
}
保存时就会开始安装,可以在左下角查看进度
安装在项目文件夹 》 node_modules 文件夹下
但是静态文件必须放在 wwwroot 文件夹下,可以复制或者使用 Visual Studio 内置的工具解决,所以我们先把刚才添加的代码删去(这里我们删除 package.json 文件),对应的包也会自动被删去
1,右键项目 》 添加 》 客户端库
提供程序:unpkg
库:bootstrap@4.3.1
选择特定文件:我们选一个完整的 css 文件,文件/dist/css/bootstrap.css
目标位置:wwwroot/lib/bootstrap/
点击安装
此时就添加了两个文件
1. wwwroot/lib/bootstrap/dist/css/bootstrap.css
2. libman.json
- 在 wwwroot 下添加一个 css 文件夹,再添加一个 site.css,随便写点东西
body {
font-size: 16px;
margin: 25px;
}
- 因为我们在运行网站时只想拥有一个 css 文件,所以需要合并和压缩两个css文件
在项目下新建一个 json 文件,命名 bundleconfig.json ,在这个文件里做两个操作,合并和压缩
[
{
"outputFileName": "wwwroot/css/all.min.css",
"inputFiles": [
"wwwroot/lib/bootstrap/dist/css/bootstrap.css",
"wwwroot/css/site.css"
]
},
{
"outputFileName": "wwwroot/css/bootstrap.css",
"inputFiles": [
"wwwroot/lib/bootstrap/dist/css/bootstrap.css"
],
"minify": {
"enabled": true
}
}
]
-
通过 NuGet 安装 BuildBundlerMinifier
-
右键项目 》 生成,可以看到 BuildBundlerMinifier 在工作,wwwroot文件夹下也生成了我们需要 的文件
部署
.NET Core 部署方式/类型
- FDD,Framework-dependent
- SCD,Self-contained
FDD,Framework-dependent
优点:
- 无需配置服务器的操作系统
- 部署的包很小
- .NET Core 是共享的
缺点:
- 只有在预先安装了 .NET Core 的情况下才能运行
- 可能会有兼容性的问题
SCD,Self-contained
优点:
- 可以对你使用的 .NET Core 版本进行单独隔离的控制
- 应用程序 100% 可以在目标系统运行
- 不同 .NET Core 应用可以无干扰共存并运行
缺点:
- 需要配置目标服务器操作系统
- 部署包比较大
FDE,Framework-dependent executables
- 自包含的部署
- 会使用以前安装过的 .NET Core 资源
- 生成系统原生的可执行文件
我觉得没啥可写的,就写在最前面了,还是看视频吧
注意一个坑
我们在直接运行 asp.net core 项目时,是不能以ip访问的,解决方案可以是修改 Properties/launchSettings.json 的一个选项
"applicationUrl": "http://*:5000"
但是实际发布后并不能以ip访问,有两种解决方案
第一种是在 Program.cs 中添加一句,不推荐使用这种方案
webBuilder.UseKestrel().UseUrls("http://*:5000");
在微软的官方文档中有关于 Kestrel 的配置,在 appsettings.json 中添加一个对象
"Kestrel": {
"Endpoints": {
"Http": {
"Url": "http://*:5000"
},
"Https": {
"Url": "https://*:5001",
"Certificate": {
"Path": "<path to .pfx file>",
"Password": "<certificate password>"
}
}
}
}
这样,发布之后依然可以修改配置文件,注意 https 的配置,需要证书,不然会运行报错
Kestrel 详细的可以去看官方文档