ASP.NET Core学习

  1. .net core是.net生态发展的未来;是微软重新设计的、和FW比整个体系、结构完全变化了。
  2. 开源、跨平台(开发、部署、物联网、云服务)
  3. 模块化、组件化、体积小、运行速度快
  4. 维护:不是微软一家了,而有一个社区、.net基金
  5. 微服务、docker
  6. 3.0前包含移植了.net fw类库,3.0后不一样了。
  7. 运行命令行(vs code)、部署灵活
  8. 向下兼容(与FW兼容)
  9. .Net Core目前3.1,下一代.Net5(16年.net core1,19年.net core 3.1)
  10. .net core3.1目前支持:winform\wpf不太完善、asp.net core 3.0、EF core 3.0
  • ASP.NET CORE 学习要点:

  启动流程、主机配置、IOC、服务、管道、中间件、应用配置、多环境、日志、路由、异常、处理、静态文件、部署

 

  • 启动:自宿主、IIS 2种

入口点:Startup.cs

看代码:Program.cs

 

    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            //这里默认配置
            //环境变量(DotNet开关)
            //加载命令行参数
            //加载应用配置
            //配置的默认日志组件
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    //这里进行-组件配置
                    //webBuilder.ConfigureKestrel((context,option)=>option.Limits.MaxRequestBodySize=1024);//示例
                    //webBuilder.ConfigureLogging((context,builder)=>builder...;

                    //这里是-主机配置项
                    webBuilder.UseStartup<Startup>();

                    //配置主机的方式:
                    //(1)硬编码
                    //(2)环境变量(ASPNETCORE开关的,不管配置在什么地方)
                    //(3) 应用配置(appsettings.json)
                    //(4)命令行(优先级最高)

                    //这里改变了端口(这里的硬编码先生效了,端口实际默认配置在Properties下面的launchSettings.json中)
                    webBuilder.UseUrls("http://*:6000");
                    //也可以在命令行(bin目录下)运行命令启动:dotnet WebApplication-NetCoreTest.dll --urls http://*:7999

                });

    }

 通过下面的命令行运行看,代码中虽然配置了6000端口,但命令行优先级最高 

 

 

  • Host.CreateDefaultBuilder主机:管理web应用程序启动、生存期管理、配置、请求处理管道、日志、IOC(实际是封装了应用资源的一个对象)
  • 流程:创建主机生成器》配置》创建主机》运行主机
  • kestrel:跨平台、类IIS、高性能、支持HTTPS\HTTPS/2、在linux下性能更高、不支持反向代理、负载均衡(主要用于后端WEB托管、调试,最好不放在前端,应该用iis\nginx代替)

 http请求 > 反向代理 > webserver kertrl > 中间件 > 返回给客户

 

 

 

 

 

 

  • 配置介绍

    • 命令行配置(通过运行时在命令行里输入的参数)=========默认参数(代码里的硬编码参数)
    • Json文件配置(使用json文件的配置)
    • 从配置文件文本到c#对象实例的映射 - Options 与 Bind(将配置文件的配置绑定到一个C#的类【直接映射】https://blog.csdn.net/Upgrader/article/details/104785213/
    • 配置文件热更新(不用重新启动)【用IoptionSnapeShot】
    • 框架设计:Configuration
  • 其他配置:

    • (已安装或已创建的)自定义提供程序
    • 目录文件
    • 环境变量
    • 内存中的 .NET 对象

   net core 中的配置====参考资源https://www.w3cschool.cn/netcore/netcore-vaqb31ks.html

 

 

 

 

 依赖注入:

参考资源:http://www.jessetalk.cn/2017/11/06/di-in-aspnetcore/

实现方式:通过依赖倒置和IOC容器注入来实现的

  • 客户端new一个对象时,不依赖于具体实现,而依赖于一个抽象
  • 通过IOC容器将对象注入进来,而不是客户端类自己去new一个对象【不用自己去拿,而是别人拿什么来,你就用什么】

优点:

  • 解耦:对于客户端类来说,解除对 对象的强依赖,很容易替换掉依赖的类,对于被引用过很多次的类很容易就替换掉了【容器给你什么对像就用什么对象】
  • 松耦合让代码更具灵活性,能更好地应对需求变动综上所述项目维护将带来好处。
  • 单元测试友好:在测试方法里,直接new各种对象,然后扔到一个controler的构造函数里就可以了。

注入的方式:

  • 构造函数注入
  • 属性注入

隐式依赖:把一个类用到的所有外部组件放到一个类最上面,在构造函数里面初始化

private CustomerContext _context;

public CustomerController()
{
    _context = new CustomerContext(new DbContextOptions<CustomerContext>{});
}

显示依赖:需要用到的地方再初始化,不推荐

var context = new CustomerContext(new DbContextOptions<CustomerContext>{});

 

实例的生命周期之单例

.NET Core DI 为我们提供的实例生命周其包括三种
  • Transient: 每一次GetService都会创建一个新的实例
  • Scoped:  在同一个Scope内只初始化一个实例 ,可以理解为( 每一个request级别只创建一个实例,同一个http request会在一个 scope内)
  • Singleton :整个应用程序生命周期以内只创建一个实例 

DI在ASP.NET Core中的应用

  • 在Startup类中初始化:Startup.cs的  ConfigureService中配置DI,大家看到 IServiceCollection这个参数应该就比较熟悉了
public void ConfigureServices(IServiceCollection services)
{
    services.AddTransient<ILoginService<ApplicationUser>, 
      EFLoginService>();
    services.AddMvc();
)
  • Controller中使用:一般可以通过构造函数或者属性来实现注入,但是官方推荐是通过构造函数。这也是所谓的显式依

 private ILoginService<ApplicationUser> _loginService;
public AccountController(
  ILoginService<ApplicationUser> loginService)
{
  _loginService = loginService;
}
  • View中使用:在View中需要用@inject 再声明一下,起一个别名。

@using MilkStone.Services;
@model MilkStone.Models.AccountViewModel.LoginViewModel
@inject ILoginService<ApplicationUser>  loginService
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head></head>
<body>
  @loginService.GetUserName()
</body>
</html>
  • 通过 HttpContext来获取实例

HttpContext下有一个RequestedService同样可以用来获取实例对象,不过这种方法一般不推荐。同时要注意GetService<>这是个范型方法,默认如果没有添加Microsoft.Extension.DependencyInjection的using,是不用调用这个方法的。

HttpContext.RequestServices.GetService<ILoginService<ApplicationUser>>();

如何替换其它的Ioc容器

Autofac也是不错的选择,但我们首先要搞清楚为什么要替换掉默认的 DI容器?,替换之后有什么影响?.NET Core默认的实现对于一些小型的项目完全够用,甚至大型项目麻烦点也能用,但是会有些麻烦,原因在于只提供了最基本的AddXXXX方法来绑定实例关系,需要一个一个的添加。如果项目可能要添加好几百行这样的方法。
 
如果熟悉Autofac的同学可能会这下面这样的代码有映象。
builder.RegisterGeneric(typeof(LoggingBehavior<,>)).As(typeof(IPipelineBehavior<,>));
 
builder.RegisterGeneric(typeof(ValidatorBehavior<,>)).As(typeof(IPipelineBehavior<,>));

这会给我们的初始化带来一些便利性,我们来看看如何替换Autofac到ASP.NET Core。我们只需要把Startup类里面的 ConfigureService的 返回值从 void改为 IServiceProvider即可。而返回的则是一个AutoServiceProvider。

public IServiceProvider ConfigureServices(
  IServiceCollection services){
    services.AddMvc();
    // Add other framework services

    // Add Autofac
    var containerBuilder = new ContainerBuilder();
    containerBuilder.RegisterModule<DefaultModule>();
    containerBuilder.Populate(services);
    var container = containerBuilder.Build();
    return new AutofacServiceProvider(container);
}

其中很大的一个变化在于:Autofac 原来的一个生命周期InstancePerRequest,将不再有效。正如我们前面所说的,整个request的生命周期被ASP.NET Core管理了,所以Autofac的这个将不再有效。我们可以使用 InstancePerLifetimeScope ,同样是有用的,对应了我们ASP.NET Core DI 里面的Scoped。 

 

 

  • 管道:

    • 用于检查、重路由或修改传入请求和传出响应
    • 基于中间件组件而形成的管道(Startup.Configure方法中通过IApplicationBuilder的在使用Use方法添加中间件)
    • 管道的实现机制:RequestDelegate与ApplicationBuilder

参考资源:

https://www.cnblogs.com/artech/p/how-pipeline-is-built.html

https://www.cnblogs.com/artech/p/asp-net-core-pipeline.html

 

 添加中间件的方法:

//向应用程序的请求管道中添加一个内联定义的中间件委托
//调用的方法:public static IApplicationBuilder Use(this IApplicationBuilder app, Func<HttpContext, Func<Task>, Task> middleware);
//命名空间:Microsoft.AspNetCore.Builder
//类 static class UseExtensions

app.Use(async (contex,next)=> { //await await next.Invoke(); });

//命名空间:Microsoft.AspNetCore.Builder
//接口类:public interface IApplicationBuilder
//方法:IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware);
//将中间件委托添加到应用程序的请求管道
app.Use(next=> { return (context) => { return next(context); }; });
//namespace Microsoft.AspNetCore.Builder
//public static class MapExtensions
//public static IApplicationBuilder Map(this IApplicationBuilder app, PathString pathMatch, Action<IApplicationBuilder> configuration);
//基于给定请求路径的匹配分支请求管道。如果请求路径以给定路径开始,则执行分支
//会启用一个新的taskApp[taskApp.Run()],作为另外一个环境运行了。不是特别复杂的业务,用不到这个方法
app.Map("/task",taskApp=> { taskApp.Run( async (context) => { await context.Response;/// } ); });

 

  • 应用程序宿主环境信息和应用程序生存周期事件

//IHostEnvironment 提供有关应用程序正在运行的宿主环境的信息
//IHostApplicationLifetime
 向使用者通知应用程序生存期事件。
public
void Configure(IApplicationBuilder app, IHostEnvironment env, IHostApplicationLifetime lftime) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } lftime.ApplicationStarted.Register(() => { ///...启动事件 } ); lftime.ApplicationStopping.Register(() => { ///正在停止事件 } ); lftime.ApplicationStopped.Register(()=> { //停止事件 }); app.UseStaticFiles(); app.UseOrchardCore(); }
  •  RouttingMiddleware配置路由

我们首先需要在Startup.cs文件中的ConfigureServices方法中进行路由依赖注入 services.AddRouting();

        //第一种方式
            app.UseRouter(builder=>builder.MapGet("actionfirst",async context =>{
                await context.Response.WriteAsync("this is first action");
            }));

            //第二种方式
            RequestDelegate handler=context=>context.Response.WriteAsync("this is second action");
            var route=new Route(new RouteHandler(handler),"actionsecond",app.ApplicationServices.GetRequiredService<IInlineConstraintResolver>());
            app.UseRouter(route);

            //第三种方式:不常用
            app.Map("/task",taskApp=>{
                taskApp.Run(async context=>{
                    await context.Response.WriteAsync("this is a task");
                });
            });

 

 

 

 

 

posted @ 2020-02-23 11:25  无聊的蚂蚁  阅读(431)  评论(0编辑  收藏  举报