-
Overview
- About ASP.NET Core
- 关键词:cross-platform, high-performance, open-source, modern, cloud-enabled, internet-connected apps
-
Why choose ASP.NET Core?
- ASP.NET Core 是 https://learn.microsoft.com/en-us/aspnet/overview的重新设计,提供以下特性:
- 归一化的方式,建构web UI和web APIs
- 架构面向可测试性
- 支持Razor Pages
- 支持Blazor
- 整合现代的,客户端框架和开发流程
- 支持gPRC宿寄
- 云原生,基于环境的配置系统
- 内置的依赖注入
- 轻量级,高性能,模块化的HTTP请求排线
- 可宿寄于Kestrl, IIS, HTTP.sys, Nginx, Apache, Doce
- Side-by-side versioning
- 面向现代web开发的工具集
- ASP.NET Core 是 https://learn.microsoft.com/en-us/aspnet/overview的重新设计,提供以下特性:
-
Build web APIs and web UI using ASP.NET Core MVC
- 主要用于构建web APIs以及web apps
- MVC模式有助于增强web API和web APP可测试性
- Razor Pages有助于提高制作web UI的生产力
- Razor markup为Razor Pages和MVC试图提供高生产力的措辞
- Tag Helper可使服务端代码参与Razor文件中的HTML元素的创建和呈现
- 内置支持给多种文件数据以及内容协商,让web API可用于不同的客户端
- Model binding自动映射HTTP request的数据到动作方法参数
- Model validation自定执行客户端以及服务端的验证
- 主要用于构建web APIs以及web apps
-
Client-side development
- 客户端框架包括Blazor、Angular、React以及Bootstrap
-
ASP.NET Core target frameworks
- ASP.NET Core 3.x后只能定向到.NET Core。
- 整体上,ASP.NET Core由.NET Standard料库构成,支持.NET Standar 2.0。
- .NET Core的益处
- 跨平台
- 高性能
- Side-by-side versioning
- 新API
- 开源
-
Recommended learning path
- Web app
- 新的服务端web UI开发,用Razor Pages
- 维护MVC app,用MVC
- 客户端web UI开发,用Blazor
- Web API
- RESTful HTTP services
- RPC
- 基于Potocol Buffers的gRPC
- Real-time
- 基于SignalR
- basic data access
- 新开发
- Razor Pages搭配Entity Framework Core
- 维护MVC
- MVC搭配Entity Framework Core
- 新开发
- Web app
-
Migrate from .NET Framework(略)
-
How to download a sample(略)
-
Breaking changes and security advisories(过)
-
Next steps(过)
- About ASP.NET Core
-
Foundamnetals
- Dependency injection (services)
-
Overview of dependency injection
- DI是如何解决问题的
- ASP提供了IServiceProvider
- 层层的依赖会形成一个依赖图、或者依赖树
- 化解依赖的时候会采用https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/types#open-and-closed-types,避免注册每个https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/types#constructed-types
- DI语境下,一个服务
- 要么是一个对象,提供服务给另一个对象
- 要么和web服务不太相关
- DI是如何解决问题的
-
Register groups of services with extension methods
- 一个成例是使用单个
Add{GROUP_NAME}
扩展方法来注册某个框架特性所需的所有服务 - (具体略)
- 一个成例是使用单个
-
Service lifetimes
-
Service registration methods
- (暂停)
-
- Configuration
- 配置源于配置提供者,如下
- 设置文件,例如
appsettings.json
- 环境变量
- Azure Key Vault
- Azure App Configuration
- 命令行参量
- 自定义的提供者,installed 或created
- 目录文件
- 内存中的.NET对象
- 设置文件,例如
-
Application and Host Configuration
- 应用需要配置和加载一个宿主,用于应用的启动和存续管理
- ASP.NET Core模板创建一个WebApplicationBuilder,其中包含宿主
- 应用和宿主都可以提供配置
- 应用提供的配置优先级高
-
Default application configuration sources
- 模板中带的代码
var builder = WebApplication.CreateBuilder(args);
- 例现化了WebApplicationBuilder,此过程会提供一些默认配置,按优先级排序如下
- 命令行参量
- 无前缀的环境变量
- Development模式下的用户密信
appsettings.{Environment}.json
,比如appsettings.Production.json
appsettings.json
- 默认的宿主配置
- 例现化了WebApplicationBuilder,此过程会提供一些默认配置,按优先级排序如下
- 模板中带的代码
-
Default host configuration sources
- WebApplicationBuilder中宿主配置源,优先级从高到低
- 命令行参量
DOTNET_
为前缀的环境变量ASPNETCORE_
为前缀的环境变量
- 对于.NET Generic Host和Web Host,默认的宿主配置源,优先级从高到低
ASPNETCORE_
为前缀的环境变量- 命令行参量
DOTNET_
为前缀的环境变量
- WebApplicationBuilder中宿主配置源,优先级从高到低
-
Host variables
- 下面的变量在初始化宿主建构器的时候被锁定,不受应用配置影响
- Application name
- Environment name
- Content root
- Web root
- 是否找寻hosting startup assemblies,以及如何找寻
- 由应用或者料库代码在IHostBuilder.ConfigureAppConfiguration回调中从HostBuilderContext.Configuration读入的变量
- URLS是常见的非自举的宿主配置。宿主配置中的URLS用于保底
- 下面的变量在初始化宿主建构器的时候被锁定,不受应用配置影响
- 应用需要配置和加载一个宿主,用于应用的启动和存续管理
-
Application configuration providers
- (代码示例略)
-
appsettings.json
- (代码示例略)
- 配置源于配置提供者,如下
- Dependency injection (services)
-
Migration
- 5.0 to 6.0
-
New hosting model
- 只需单个文件加上少许代码即可
- 示例代码
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run();
- 使用minimal hosting model的益处
- 减少所需代码
- 将
Startup.cs
整合进Program.cs
-
Apps migrating to 6.0 don’t need to use the new minimal hosting model
- ASP.NET Core 3.1到5.0模板的Startup和Generic Host依然可用
-
Use Startup with the new minimal hosting model
- 举了一些代码例子吧
-
Differences between the ASP.NET Core 5 and 6 hosting models
- 开发模式下,默认开启exception page中间件
- app名字默认为入口点所在的装配件名:
Assembly.GetEntryAssembly().GetName().FullName
- 端点路由中间件裹挟了整个管线,不需要通过UseRouting或UseEndpoints来注册路由。
- 管线在IStartupFilter之前创建
- 工具(比如EF migration)使用Program.CreateHostBuilder 来访问应用的IServiceProvider
- 不可修改侯宿设置(比如app name,环境,content root),参考https://learn.microsoft.com/en-us/aspnet/core/migration/50-to-60-samples?view=aspnetcore-7.0#cii
- 不可在 WebApplicationBuilder.Host 或WebApplicationBuilder.WebHost使用Startup标类
- WebApplicationBuilder 的IHostBuilder 不会推迟执行ConfigureServices, ConfigureAppConfiguration, or ConfigureHostConfiguration ,以便观察到对IServiceCollection 以及IConfiguration的改动。
-
- 3.1/5.0 Code to 6.0
- 提供迁移到ASP.NET Core 6.0的新minimal hosting model的示例代码
- 5.0 to 6.0
Web Apps文档阅读。
- Choose an ASP.NET Core web UI
- 篇首(略)
- Client-side development
- Single Page Apps
- Overview of SPAs
-
Architecture of Single Page Application templates
- 为Anglar和React应用提供后端能力
- 提供一个后备路由,提供404处理,而不是直接返回404
- 开发过程中使用frontend路由
- 使用ASP.NET Core SPA模板的好处
- 在代理没有运行时,加载之
- 设置HTTPS
- 让一些请求代理到后端处理
- 为Anglar和React应用提供后端能力
-
Published Single Page Apps
-
Developing Single Page Apps
- 工程文件定义了一些辖属用于控制开发态应用的行为
-
<SpaProxyServerUrl>https://localhost:44414</SpaProxyServerUrl> <SpaProxyLaunchCommand>npm start</SpaProxyLaunchCommand>
<PackageReference Include="Microsoft.AspNetCore.SpaProxy" Version="7.0.1" />
- Microsoft.AspNetCore.SpaProxy需要在
Properties/launchSettings.json
中加载"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy" "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy"
-
-
Angular setup
-
React setup
- 工程文件定义了一些辖属用于控制开发态应用的行为
-
Supported SPA framework version in ASP.NET Core SPA templates
-
- Use React with ASP.NET Core
- 使用的时Create React App。
- JavaScript Services
-
What is JavaScript Services
- 包括
- NodeServices
- SpaServices
- 用于支持以下场景
- 在服务器上运行JavaScript
- 使用一个SPA框架或者料库
- 在Webpack中构建客户端资产
- 包括
-
- Overview of SPAs
- Run .NET from JavaScript
- 涉及
[JSImport]
和[JSExport]
- JS应用可以使用.NET 7中扩展了的客户端WebAssembly来支持在JS中重用.NET料库
- 涉及
- Single Page Apps
- Razor syntax
- 篇首
- Rendering HTML
- HTMl是Razor的默认绘制语言
- Razor syntax
@
从HTML切到C#,@
通过自身转义- 在HTML的属性和内容中带邮件地址的,不把
@
当成切换字符
- Scalable Vector Graphics (SVG)
- 支持SVG的foreignObject
- Implicit Razor expressions
- 隐性表达式不支持泛型
- Explicit Razor expressions
- 显性表达式
@(...)
,其内容会被算出并绘制到输出 - 之前提到的隐性表达式,基本不能带空格
- 也可以用来输出泛型:
<p>@(GenericMethod<int>())</p>
- 显性表达式
- Expression encoding
- 输出的HTML会被转义,要原样输出的话,需要
@Html.Raw("<span>Hello World</span>")
- 输出的HTML会被转义,要原样输出的话,需要
- Razor code blocks
@{...}
之内的代码输出不会被绘制,需要显示调用操作来输出
- Implicit transitions
@{...}
之内默认是C#,但是可以切换成HTML
- Explicit delimited transition
- 使用
<text>
可以在C#代码块输出HTML<text>
内夹的空白不会被绘制- 外沿的空白也不会被绘制
- 使用
- Explicit line transition
- 在代码块中完整绘制HTML,可以使用
@:Name: @person.Name
- 在代码块中完整绘制HTML,可以使用
- Control structures
- 控制结构是代码块的扩展,代码块的所有功能和问题,也适用于控制结构
- Conditionals @if, else if, else, and @switch(过)
- Looping @for, @foreach, @while, and @do while(过)
- Compound @using
- 和C#的using用完即弃不同,Razor的
@using
用来内嵌HTML内容,比如构建表单的时候添加表单内容
- 和C#的using用完即弃不同,Razor的
- @try, catch, finally(过)
- @lock(过)
- Comments(过)
- Directives
- 隐性表达式中采用保留的关键字来代表指示
- A directive typically changes the way a view is parsed or enables different functionality.
@attribute
@code
,可以用于添加C#成员,等同于@functions
@functions
@implements
,用于实现接口@inherits
,用于派生标类@inject
,注入服务@layout
,只用于razor组件@model
,只用于razor页面@namespace
,指定命名空间以替换默认生成的@page
,razor页面和组件中含义不同@preservewhitespace
,默认是false@section
,只适用于MVC试图和Razor页面@using
,添加C#的using指示
- 隐性表达式中采用保留的关键字来代表指示
- Directive attributes
- 主要适用于元素,大部分只适用于razor组件
@attributes
,一股脑把未声明的属性们插进去@bind
@bind:culture
@on{EVENT}
@on{EVENT}:preventDefault
@on{EVENT}:stopPropagation
@key
@ref
@typeparam
,泛型参数
- Templated Razor delegates
- 可以定义UI snippet,形如:
@<tag>...</tag>
- 可以定义UI snippet,形如:
- Tag Helpers
- 只适用于MVC试图和Razor页面(略)
- Razor reserved keywords
- Razor keywords
- C# Razor keywords
- Reserved keywords not used by Razor
- Inspect the Razor C# class generated for a view
- Razor SDK用于编译Razor文件。默认不生成代码文件,如果需要生成的话,在.csproj中指定
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
- Razor SDK用于编译Razor文件。默认不生成代码文件,如果需要生成的话,在.csproj中指定
- View lookups and case sensitivity
- File based source
- Precompiled views
- Imports used by Razor
- Additional resources
- Razor class libraries
- 开头
- Razor views, pages, controllers, page models, Razor components, View components, and data models 可以放置在RCL中
- 在使用的时候可以覆盖之,RCL中的页面优先级不如App中
- Create a class library containing Razor UI
- VS和.NET CLI中均可创建,默认只支持Razor Pages不支持views
- 默认模板在Areas目录
- Reference RCL content
- 可以作为NuGet料包,或者csproj工程引用到使用处
- VS和.NET CLI中均可创建,默认只支持Razor Pages不支持views
- Override views, partial views, and pages
- Razor pages需要在侯宿处打开
builder.Services.AddRazorPages(); app.MapRazorPages();
- Razor pages需要在侯宿处打开
- RCL Pages layout
- (没有理解)
- Create an RCL with static assets
- 创建的wwwroot目录会自动包含在RCL中
- 打包的时候使用
dotnet pack
而不是nuget pack
- Exclude static assets
- 添加到工程文件的
$(DefaultItemExcludes)
- 添加到工程文件的
- Typescript integration
- 把ts文件放到wwwroot之外,比如在Client目录
- 配置TypeScript,设置
<TypescriptOutDir>wwwroot</TypescriptOutDir>
- 添加TypeScript的构建目标
- Consume content from a referenced RCL
- wwwroot目录中的内容是在前缀
_content/{PACKAGE ID}/
下的- 比如没有
<PackageId>
的话,Razor.Class.Lib的在_content/Razor.Class.Lib/
- 比如没有
- 侯宿处需要指定
app.UseStaticFiles();
- 非开发状态,需要指定
builder.WebHost.UseWebRoot("wwwroot"); builder.WebHost.UseStaticWebAssets();
- wwwroot目录中的内容是在前缀
- Multi-project development flow
- RCL的物资依然在RCL内
- RCL重新构建不会影响使用者
- RCL构建后会产生一个manifest,用以描述静态web物资的所在,可以被动态解读
- Publish
- 发布时,会将所有引用到的wwwroot的内容放置到
_content/{PACKAGE ID}/
- 发布时,会将所有引用到的wwwroot的内容放置到
- Additional resources
- 有一些示例代码。
- 开头
Fundamentals
- Overview
- Program.cs
- 配置所需服务
- app的请求处理管线,由一系列中间件构成
- 下面应用的启动代码(具体代码略)
- Razor Pages
- MVC 控制器和视图
- Web API及其控制器
- 最小的Web API
- Dependency injection (services)
- WebApplicationBuilder.Services用来管理服务
- Middleware
- 由一系列组件构成,每个组件在HttpContext上执行操作
- 要么把HttpContext传给管线上的下者,要么中止管线处理
- 添加中间件,需要应调
Use{Feature}
扩展方法。
- 由一系列组件构成,每个组件在HttpContext上执行操作
- Host
- 启动时会建构一个侯宿,用于保证应用的所有资源,包括
- HTTP server的实现
- 中间件组件
- 录记
- DI服务
- 配置
- 有不同的侯宿:
- .NET WebApplication Host,也就是Minimal Host
- 推荐的,也是ASP.NET Core模板中默认的
- .NET Generic Host
- 与WebApplication Host共享许多接口和标类
- ASP.NET Core Web Host
- 只为向后兼容存在
- .NET WebApplication Host,也就是Minimal Host
- WebApplicationBuilder.Build 会配置一个侯宿以默认选项
- 使用Kestrel为web服务器,并开启IIS集成
- 从
appsettings.json
、环境变量、命令行参量、以及其他配置源加载配置 - 将录记输出设置到控制台和调试频道
- Non-web scenarios
- Generic Host允许其他类型的应用使用cross-cutting framework extensions
- 启动时会建构一个侯宿,用于保证应用的所有资源,包括
- Servers
- Kestrel,跨平台,搭配IIS,Ngnix,Apache使用
- IIS HTTP Server
- HTTP.sys
- Configuration(略)
- Environments(略)
- Logging(略)
- Routing(略)
- Error handling(略)
- Make HTTP requests(略)
- Content root(略)
- Web root(略)
- Additional resources
- Program.cs
- Dependency injection (services)
- (待读)
博客篇
Build client web assets for your Razor Class Library
- 文首
- 将npm和webpack整合进构建过程
- 介绍https://www.nuget.org/packages/Microsoft.AspNetCore.ClientAssets/,注意这个料包还处于Alpha状态
- Adding a client web assets build process
- 关于客户端web物资,构建时有两件事要做
- 恢复npm或者yarn设置的料包
- 构建所需的静态web物资
- 假设物资在assets目录,物资构建有几个选项
- 把生成目录设为dist,符合web习惯
- 把生成目录设为obj,符合.NET习惯
- 此外,Web物资构建最好是按需执行
- 关于客户端web物资,构建时有两件事要做
- Using the MicrosoftAspNetCore.ClientAssets package
- 自动添加支持npm、webpack以及其他构建工具
- 使用此料包
- 工程中引用此料包
- 创建一个assets目录,然后创建一个
package.json
文件 - 在此
package.json
中定义build:Debug
和build:Release
目标
- 这样就ok了,此处是一个示例
- Add a client web assets build process using MSBuild
- 提供了自定义的MSBuild目标,此章讨论如何设置这个目标
- Integrating npm install with Razor Class Libraries
- 指定input和output
<Target Name="NpmInstall" Inputs="assets\\package.json" Outputs="assets\\node_modules.package-lock.json"> <Message Importance="high" Text="Running npm install..." /> <Exec Command="npm install" WorkingDirectory="assets" /> </Target>
- 指定input和output
- Running an npm command and collecting the outputs as static web assets
- 创建一个NpmRunBuild目标,来完成以下动作
- 运行给定的npm命令
- 收集命令的输出
- 将输出作为Content条目,将其链接到wwwroot目录
- 录记生成的文件列表
- NpmRunBuild目标定义如下:
<Target Name="NpmRunBuild" DependsOnTargets="NpmInstall" BeforeTargets="AssignTargetPaths"> <Exec Command="npm run build:$(Configuration) -- -o $(IntermediateOutputPath)npm" WorkingDirectory="assets" /> </Target>
- 将输出作为Content,链接到wwwroot:
<ItemGroup> <_NpmOutput Include="$(IntermediateOutputPath)npm**" /> <Content Include="@(_NpmOutput)" Link="wwwroot%(_NpmOutput.RecursiveDir)%(_NpmOutput.FileName)%(_NpmOutput.Extension)" /> <FileWrites Include="@(_NpmOutput)" /> </ItemGroup>
- 确保只在需要时运行,先录记一个生成的文件列表,然后让MSBuild知道Input和Outupt是啥:
<WriteLinesToFile File="$(IntermediateOutputPath)npmbuild.complete.txt" Lines="@(_NpmOutput)" /> <FileWrites Include="$(IntermediateOutputPath)npmbuild.complete.txt" /> <ItemGroup> <NpmBuildInputs Include="assets**" Exclude="assetsnode_modules**" /> </ItemGroup>
- 创建一个NpmRunBuild目标,来完成以下动作
- Adding scripts in package.json:
"scripts": { "build:Debug": "webpack --mode development", "build:Release": "webpack --mode production" }
- Reusing the MSBuild code
- 给出了总览
- 如果要将生成的文件放置在dist目录、而非assets目录,则:
<PropertyGroup> <ClientAssetsDirectory>js</ClientAssetsDirectory> <DefaultItemExcludes>$(ClientAssetsDirectory)dist**</DefaultItemExcludes> </PropertyGroup>
- Summary