net core 3.1 知识累积
执行顺序
Host.CreateDefaultBuilder(args)
// • set the Microsoft.Extensions.Hosting.IHostEnvironment.ContentRootPath to the
// result of System.IO.Directory.GetCurrentDirectory
// • load host Microsoft.Extensions.Configuration.IConfiguration from "DOTNET_"
// prefixed environment variables
// • load host Microsoft.Extensions.Configuration.IConfiguration from supplied command
// line args
// • load app Microsoft.Extensions.Configuration.IConfiguration from 'appsettings.json'
// and 'appsettings.[Microsoft.Extensions.Hosting.IHostEnvironment.EnvironmentName].json'
// • load app Microsoft.Extensions.Configuration.IConfiguration from User Secrets
// when Microsoft.Extensions.Hosting.IHostEnvironment.EnvironmentName is 'Development'
// using the entry assembly
// • load app Microsoft.Extensions.Configuration.IConfiguration from environment
// variables
// • load app Microsoft.Extensions.Configuration.IConfiguration from supplied command
// line args
// • configure the Microsoft.Extensions.Logging.ILoggerFactory to log to the console,
// debug, and event source output
// • enables scope validation on the dependency injection container when Microsoft.Extensions.Hosting.IHostEnvironment.EnvironmentName
// is 'Development'
部署发布
IIS发布篇
模块 --> AspNetCoreModuleV2
为什么不发布就不能部署? -- 直接指向项目,会失败
命令行篇
1.在bin目录直接运行
dotnet Study.NetCore31.practical.dll --urls=http://*:3001
样式问题:
//1.把wwwroot拷贝过去
//2.添加默认路径
app.UseStaticFiles( new StaticFileOptions()
{
FileProvider =new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(),"wwwroot"))
});
AOP注册
新建一个 Filter\CustomExceptionFilterAttribute.cs
public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
Console.WriteLine("aaaa");
//base.OnException(context);
}
}
1.全局注册
在有错的地方就会执行
services.AddControllersWithViews(option =>
{
//全局注册filter
option.Filters.Add(typeof(CustomExceptionFilterAttribute));
});
2.ServiceFilter
Startup.cs
services.AddTransient(typeof(CustomExceptionFilterAttribute));
HomeController.cs
//放在控制器
[ServiceFilter(typeof(CustomExceptionFilterAttribute))]
public class HomeController : Controller
{
...
public IActionResult Privacy()
{
throw new Exception("12");
return View();
}
}
3.TypeFilter
4.IFilterFactory
StartUp 启动顺序
IOC的注册方法
先来自定义OrderService
public interface IOrderService { }
public class OrderService : IOrderService
{
}
其他类似,下面是一些使用方法
#region 注册不同声明周期的服务
services.AddSingleton<IMySingletonService, MySingletonService>();
services.AddTransient<IMyTransientService, MyTransientService>();
services.AddScoped<IMyScopeService, MyScopeService>();
#endregion
#region 花式注册
services.AddSingleton<IOrderService>(new OrderService());
//可以组装复杂注册
services.AddSingleton<IOrderService>(serviceProvider =>
{
serviceProvider.GetService<IOrderService>();
return new OrderService();
});
#endregion
#region 尝试注册
//如果注册过 IMySingletonService,这里是不会成功的
services.TryAddSingleton<IOrderService, OrderService>();
//如果注册过 IMySingletonService,这里是不会成功的,但是如果实例不同,就会注册成功
services.TryAddEnumerable(ServiceDescriptor.Singleton<IOrderService, OrderServiceEx>());
#endregion
#region 移除和替换
services.RemoveAll<IOrderService>();
services.Replace(ServiceDescriptor.Singleton<IOrderService, OrderServiceEx>());
#endregion
比较特殊点的是泛型模版注册
public interface IGenericService<T> { }
public class GenericService<T> : IGenericService<T>
{
public T Data { get; set; }
public GenericService(T data)
{
this.Data = data;
}
}
这里像开始那样写就不行了,必须像这样
#region 泛型模版
//services.AddSingleton<IGenericService<>,GenericService<>(); //失败
services.AddSingleton(typeof(IGenericService<>), typeof(GenericService<>));
#endregion
配置框架
static void Main(string[] args)
{
IConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddInMemoryCollection(new Dictionary<string, string>
{
{"MyKey", "Dictionary MyKey Value"},
{"Position:Title", "Dictionary_Title"},
{"Position:Name", "Dictionary_Name" },
{"Logging:LogLevel:Default", "Warning"}
});
//IConfigurationRoot 配置结构的根
IConfigurationRoot configurationRoot = builder.Build();
Console.WriteLine(configurationRoot["MyKey"]); //Dictionary MyKey Value
Console.WriteLine(configurationRoot["Position:Title"]); //Dictionary_Name
IConfiguration config = configurationRoot;
IConfigurationSection section = config.GetSection("Logging");
Console.WriteLine(section["LogLevel:Default"]); //Warning
}
命令行
使用默认配置,CommandLineConfigurationProvider 会从以下配置源后的命令行参数键值对中加载配置:
- appsettings.json 和 appsettings.
Environment
.json 文件 。appsettings.json and appsettings.Environment
.json files. - 开发环境中的应用机密(机密管理器)。App secrets (Secret Manager) in the Development environment.
- 环境变量。
支持的格式
- 无前缀的key=value模式
- 双中横线模式--key=value 或--key value
- 正斜杠模式/key=value或/key value
备注: 等号分隔符和空格分隔符不能混用
例子
Properties\launchSettings.json
{
"profiles": {
"CommandDemo": {
"commandName": "Project",
"commandLineArgs": "help=F9 --CommandLineKey2=value2 /CommandLineKey3=value3 "
//"commandLineArgs": "help=F9 --CommandLineKey2=value2 /CommandLineKey3=value3 -k1=k3"
}
}
}
Program.cs
static void Main(string[] args)
{
IConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddCommandLine(args);
#region
//var mapper = new Dictionary<string, string>() { { "-k1", "help" } };
//builder.AddCommandLine(args, mapper);
#endregion
var configurationRoot = builder.Build();
Console.WriteLine($"help:{configurationRoot["help"]}");
Console.WriteLine($"CommandLineKey2:{configurationRoot["CommandLineKey2"]}");
Console.WriteLine($"CommandLineKey3:{configurationRoot["CommandLineKey3"]}");
Console.ReadKey();
}
//help:F9
//CommandLineKey2:value2
//CommandLineKey3:value3
命令替换模式
- 必须以单划线(-)或双划线(--)开头
- 映射字典不能包含重复Key
例子
Properties\launchSettings.json
{
"profiles": {
"CommandDemo": {
"commandName": "Project",
//"commandLineArgs": "help=F9 --CommandLineKey2=value2 /CommandLineKey3=value3 "
"commandLineArgs": "help=F9 --CommandLineKey2=value2 /CommandLineKey3=value3 -k1=k3"
}
}
}
Program.cs
static void Main(string[] args)
{
IConfigurationBuilder builder = new ConfigurationBuilder();
//builder.AddCommandLine(args);
#region 命令替换
var mapper = new Dictionary<string, string>() { { "-k1", "help" } };
builder.AddCommandLine(args, mapper);
#endregion
var configurationRoot = builder.Build();
Console.WriteLine($"help:{configurationRoot["help"]}");
Console.WriteLine($"CommandLineKey2:{configurationRoot["CommandLineKey2"]}");
Console.WriteLine($"CommandLineKey3:{configurationRoot["CommandLineKey3"]}");
Console.ReadKey();
}
//help:k3
//CommandLineKey2:value2
//CommandLineKey3:value3
总结:类似于 -h
是 --help
的简写
-h|--help 显示命令行帮助。
环境变量
EnvironmentVariablesConfigurationProvider 会在读取 appsettings.json、appsettings.Environment
.json 和机密管理器后从环境变量键值对加载配置 。
所有平台上的环境变量分层键都不支持 :
分隔符。
__
(双下划线)代替:
:
- 受所有平台支持。 例如,Bash 不支持 : 分隔符,但支持 __。
- 自动替换为
:
分层键
#region 环境变量
IConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddEnvironmentVariables();
var configurationRoot = builder.Build();
Console.WriteLine($"STAGING:{configurationRoot["STAGING"]}");
//分层键
var production = configurationRoot.GetSection("Production");
Console.WriteLine($"hotfix:{production["hotfix"]}");
Console.WriteLine($"hotfix:{production["hotfix:vn"]}");
#endregion
前缀过滤
//前缀过滤
builder.AddEnvironmentVariables("STAGING_");
var configurationRoot = builder.Build();
Console.WriteLine($"STAGING:{configurationRoot["Brance2"]}"); //JAP
路由
路由方式
- 路由模版的方式(MVC)
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddRouting();
//core 3.1 必须设置 option.EnableEndpointRouting = false
services.AddMvc(option => option.EnableEndpointRouting = false);
...
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseMvc(route =>
{
route.MapRoute("default", template: "api/{controller}/{action}");
});
}
//[Route("api/Authors")]
//[ApiController]
public class AuthorController : ControllerBase
{
public IAuthorRepository AuthorRepository { get; }
public AuthorController(IAuthorRepository authorRepository)
{
AuthorRepository = authorRepository;
}
//https://localhost:5001/api/Author/GetAuthors
[HttpGet]
public ActionResult<List<AuthorDto>> GetAuthors()
{
return AuthorRepository.GetAuthors().ToList();
}
//https://localhost:5001/api/Author/GetAuthor?authorId=72D5B5F5-3008-49B7-B0D6-CC337F1A3330
[HttpGet]
public ActionResult<AuthorDto> GetAuthor(Guid authorId)
{
var author = AuthorRepository.GetAuthor(authorId);
if (author == null)
{
return NotFound();
}
else
{
return author;
}
}
}
- RouteAttribute 方式 (WebApi)
app.UseEndpoints(endpoints =>
{
//使用 RouteAttribute
endpoints.MapControllers();
});
[Route("api/Authors")]
[ApiController]
public class AuthorController : ControllerBase
{
public IAuthorRepository AuthorRepository { get; }
public AuthorController(IAuthorRepository authorRepository)
{
AuthorRepository = authorRepository;
}
//https://localhost:5001/api/Authors
[HttpGet]
public ActionResult<List<AuthorDto>> GetAuthors()
{
return AuthorRepository.GetAuthors().ToList();
}
//https://localhost:5001/api/Authors/72D5B5F5-3008-49B7-B0D6-CC337F1A3330
[HttpGet("{authorId}")]
public ActionResult<AuthorDto> GetAuthor(Guid authorId)
{
var author = AuthorRepository.GetAuthor(authorId);
if (author == null)
{
return NotFound();
}
else
{
return author;
}
}
}
路由约束
- 类型约束
- 范围约束
- 正则表达式
- 是否必选
- 自定义 IRouteConstraint
URL生成
- LinkGenerator
- IUrlHelper