.NetCore常用知识大全
谈一谈对DDD的理解?
DDD,领域驱动设计。就是通过领域来指导软件设计,是一种十分抽象的软件设计思想;
它主要分为战略设计和战术设计:1)战略方面,通过事件风暴进行领域模型的划分,划分出核心域,子域,支撑域,定义通用语言,划分出界限上下文。
2)战术设计方面,ddd将架构分层,“松耦合,高内聚”是架构设计的整体思想。按照DDD思想,可以分为领域层,基础设施层,应用层,接口层。
接口层为前端用户提供api接口。基础设施层可以放一些第三方的服务,数据库连接等内容。应用层是对领域服务的编排,是很薄的一层(目前我自己的架构,应用的是cqrs,所有的相关逻辑都是放在了应用层,而领域层只是放了实体,因为暂时还不是特别理解领域层的服务和事件都应该写什么)。领域层包括实体,值对象,聚合根,领域服务,领域事件等内容。
如何在controller中注入service?
在config services方法中配置这个service。
在controller的构造函数中,添加这个依赖注入。
ASP.NET Core 比 ASP.NET 更具优势的地方是什么?
1)跨平台(.NET Core 可以运行在 Windows 、Linux 和 MAC 系统上);
2)对框架本安装没有依赖,所有依赖都跟程序本身在一起;
3).NET Core 处理请求的效率更高,进而可以处理更多的请求;
4).NET Core 具有更多的安装配置方法。
asp.net core 主要的特性有哪些?
1)依赖注入。
2)日志系统架构。
3)引入了一个跨平台的网络服务器,kestrel。可以没有iis, apache和nginx就可以单独运行。
4)可以使用命令行创建应用。
5)使用AppSettings.json 来配置工程。
6)使用start up来注册服务。
7)更好的支持异步编程。
8)支持web socket和signal IR。
9)对于跨网站的请求的预防和保护机制。
ASP.NET Core Filter如何支持依赖注入?
可以通过全局注册,支持依赖注入
通过TypeFilter(typeof(Filter)) 标记在方法,标记在控制器
通过ServiceType(typeof(Filter))标记在方法,标记在控制器,必须要注册Filter这类;
TypeFilter和ServiceType的本质是实现了一个IFilterFactory接口;
Asp.Net Core中有哪些异常处理的方案?
1.继承Controller,重写OnActionExecuted
默认都会继承一个Controller类,重写OnActionExecuted,添加上异常处理即可。一般情况下我们会新建一个BaseController, 让所有Controller继承BaseController。代码如下
1 | public class BaseController : Controller |
2.使用 ActionFilterAttribute。
ActionFilterAttribute是一个特性,本身实现了 IActionFilter 及 IResultFilter , 所以不管是action里抛错,还是view里抛错,理论上都可以捕获。我们新建一个 ExceptionActionFilterAttribute, 重写 OnActionExecuted及OnResultExecuted,添加上异常处理,完整代码如下:
1 | public class ExceptionActionFilterAttribute:ActionFilterAttribute |
使用方式有两种, 在controller里打上 [TypeFilter(typeof(ExceptionActionFilter)] 标签;
在Startup里以filter方式全局注入。
1 | services.AddControllersWithViews(options => |
3.使用 IExceptionFilter 我们知道, .Net Core提供了5类filter, IExceptionFilter是其中之一,顾名思义,这就是用来处理异常的。.net Core中ExceptionFilterAttribute已经实现了IExceptionFilter,所以我们只需继承ExceptionFilterAttribute,重写其中方法即可。 同样新建CustomExceptionFilterAttribute继承 ExceptionFilterAttribute,重写 OnException ,添加异常处理,完整代码如下:
1 | public class CustomExceptionFilterAttribute : ExceptionFilterAttribute |
4.使用ExceptionHandler.
在 startup 里,vs新建的项目会默认加上.
1 | if (env.IsDevelopment()) |
5.自定义Middleare处理
通过middleware全局处理。
1 | public class ErrorHandlingMiddleware |
ASP.NET Core中服务的生命周期?
.NET Core支持依赖注入软件设计模式,它允许在不同的组件中注入我们的服务,并且控制服务的初始化。有些服务可以在短时间内初始化,并且只能在某个特别的组件,以及请求中才能用到;而还有一些服务,仅仅只用初始化一次,就可以在整个应用程序中使用。
Singleton –单例模式:
只有一个服务的实例被创建,这个实例,存储在内存中,可以在整个应用程序中使用。我们可以对一些初始化代价比较大的服务,使用Singleton模式。在代码中可以这样:
services.AddSingleton<IProductService, ProductService>();
Scoped –作用域
这种模式下,将会为每一个请求,都创建一个服务的实例。所有同一个请求中的中间件、MVC控制器,等等,都会得到一个相同的服务实例。Entity Framework Context就是一个Scoped服务最好的参考例子。我们可以通过使用AddScoped方法来使用Scoped模式:
services.AddScoped<IProductService, ProductService>();
Transient –短暂的、瞬变的
Transient模式下,服务每次被请求的时候,都会创建一个服务实例,这种模式特别适合轻量级、无状态的服务。我们可以使用AddTransient方法,来注入服务:
services.AddTransient<IProductService, ProductService>();
什么是依赖注入?
依赖注入是一个过程,就是当一个类需要调用另一个类来完成某项任务的时候,在调用类里面不要去new被调用的类的对象,而是通过注入的方式来获取这样一个对象。具体的实现就是在调用类里面有一个被调用类的接口,然后通过调用接口的函数来完成任务。比如A调用B,而B实现了接口C,那么在A里面用C定义一个变量D,这个变量的实例不在A里面创建,而是通过A的上下文来获取。这样做的好处就是将类A和B分开了,他们之间靠接口C来联系,从而实现对接口编程。
依赖注入有哪几种方式?
setter注入
就是在类A里面定义一个C接口的属性D,在A的上下文通过B实例化一个对象,然后将这个对象赋值给属性D。主要就是set 与 get
构造函数注入
就是在创建A的对象的时候,通过参数将B的对象传入到A中。 还有常用的注入方式就是工厂模式的应用了,这些都可以将B的实例化放到A外面,从而让A和B没有关系。还有一个接口注入,就是在客户类(A)的接口中有一个服务类(B)的属性。在实例化了这个接口的子类后,对这个属性赋值,这和setter注入一样。
接口注入
相比构造函数注入和属性注入,接口注入显得有些复杂,使用也不常见。具体思路是先定义一个接口,包含一个设置依赖的方法。然后依赖类,继承并实现这个接口。
控制反转是什么?
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。
通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
依赖注入有哪些著名的框架?
Unity、autofac、spring.net、MEF、Injection、.Net Core的ServiceCollection。
介绍一些ABP.VNEXT?
.NET Boilerplate是.Net平台非常优秀的一个开源Web应用程序框架,在国内也有大量的粉丝.
从名称可以看出来, 这是.NET Boilerplate的下一代框架。
ABP框架创作于2013年,那时候没有.Net Core和.NET Core,也没有Angular2 +。ABP发布后,它们都是从头开发的。
.NET Core引入了许多内置解决方案(扩展库),用于依赖注入,日志记录,缓存,本地化,配置等。它们实际上独立于.NET Core,可用于任何类型的应用程序。
什么是dotnet core的startup class?
Startup class是dotnet core应用的入口。所有的dotnet core应用必须有这个class。这个类用来配置应用。这个类的调用是在program main函数里面进行配置的。类的名字可以自己定义。
startup class的configure方法有什么作用?
这个方法来定义整个应用如何响应HTTP请求。它有几个比较重要的参数,application builder,Hosting environment, logo factory, 在这里我们可以配置一些中间件用来处理路径,验证和session等等。
什么是中间件(Middleware)?
应用程序对HTTP请求的处理过程进行划分,每个环节称为中间件,将各个中间件串联起来,就形成了HTTP管道。
中间件是组装到应用程序管道中以处理请求和响应的软件。 每个组件:
选择是否将请求传递给管道中的下一个组件。
可以在调用管道中的下一个组件之前和之后执行工作。请求委托(Request delegates)用于构建请求管道,处理每个HTTP请求。
请求委托使用Run,Map和Use扩展方法进行配置。单独的请求委托可以以内联匿名方法(称为内联中间件)指定,或者可以在可重用的类中定义它。这些可重用的类和内联匿名方法是中间件或中间件组件。请求流程中的每个中间件组件都负责调用流水线中的下一个组件,如果适当,则负责链接短路。
中间件的使用场景有哪些?
身份验证
Session存储
日志记录等。
其实我们的.net core项目中本身已经包含了很多个中间件。比如 身份认证中间件 UseAuthorization()等系列。
中间件的执行顺序与添加方法?
执行中间件的顺序与它们添加到管道的顺序相同,先添加的中间件会先执行。
添加方法有三种:
(1)委托:中间件专用委托类型为RequestDelegate,对应的方法结构就是带HttpContext类型的输入参数,并返回Task对象。一般委托方式适用于代码量较少,处理逻辑比较简单的中间件。(2)基于约定的中间件类:基于约定的中间件类必须包含Invoke或InvokeAsync方法,输入参数为一个HttpContext对象,并返回Task对象。中间件类可以通过构造函数的依赖注入来获取下一个中间件的方法引用。
(3)实现IMiddleware接口:该接口同样包含Invoke或InvokeAsync方法,输入参数为一个HttpContext对象,并返回Task对象。用这种定义的中间件需要在代码中显式将其添加到服务容器中,因此此种中间件可修改生命周期,而前两种都是单例,应用程序中只创建一次实例。
以委托形式定义中间件
下面的例子创建了三个中间件,并在每个中间件代码中生成了一个字符串,在最后一个中间件中拼接并打印。
1 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) |
定义中间件类
通过约定方式定义中间件类。一般会戴上“Middleware”作为后缀。必须包含Invoke或InvokeAsync方法。除了HttpContext类型参数外,可在该方法后面定义其他参数,支持依赖注入。
1 | public class SampleMiddleware |
带参数的中间件
中间件允许使用参数,但并不是调用参数,而且在中间件注册时使用,即生命周期内参数只传递一次。通过构造函数传递,第一个参数是HTTP管道下一个中间件引用,第二个参数开始可以定义中间件参数。
1 |
|
IMiddleware接口的用途
基于约定的中间件类在程序运行期间只创建单例,而实现了IMiddleware接口的中间件类的生命周期就可以灵活控制。IMiddleware接口实现的中间件,在Startup.Configure方法中调用UseMiddleware方法之前,必须在Startup.ConfigureServices方法中进行注册。
1 | public class TestMiddleware : IMiddleware |
让HTTP管道“短路”
直接调用IApplicationBuilder的Run扩展方法,会使整个HTTP请求管道发生“短路”,即直接把响应消息发回给客户端,终止此次HTTP通信。
如下面代码
1 | app.Run(async context => |
程序运行的时候,只有第一个Run方法的调用会被执行,后面两次都不会被执行。因为遇到Run方法意味着HTTP请求管道的将被终结,并且将处理结果直接发回给客户端,不管Run后面还有没有插入新的中间件都不会执行了。
中间件的分支映射
添加到HTTP管道的中间件是默认响应根URL请求的,但在实际开发中,有时候需要在根URL下面通过子路径来区分不同的功能,即根据不同的子URL来调用不同的中间件。
分支映射有两种比较常见的场景。
一种用法是错误处理,例如,根URL是 http://abc.org ,可将 http://abc.org/errors 专用于错误处理,调用向客户端返回错误信息的中间件。
另一种用法是Web Socket,例如,http://abc.org/ws 分支可专用于Web Socket通信。
1 | public void Configure(IApplicationBuilder app, IHostingEnvironment env) |
列举官方常用的中间件?
异常/错误处理
当应用在开发环境中运行时: 开发人员异常页中间件 (UseDeveloperExceptionPage) 报告应用运行时错误。 数据库错误页中间件报告数据库运行时错误。 当应用在生产环境中运行时: 异常处理程序中间件 (UseExceptionHandler) 捕获以下中间件中引发的异常。 HTTP 严格传输安全协议 (HSTS) 中间件 (UseHsts) 添加 Strict-Transport-Security 标头。HTTPS 重定向中间件 (UseHttpsRedirection)
将 HTTP 请求重定向到 HTTPS。静态文件中间件 (UseStaticFiles)
返回静态文件,并简化进一步请求处理。Cookie 策略中间件 (UseCookiePolicy)
使应用符合欧盟一般数据保护条例 (GDPR) 规定。 用于路由请求的路由中间件 (UseRouting)。身份验证中间件 (UseAuthentication)
尝试对用户进行身份验证,然后才会允许用户访问安全资源。用于授权用户访问安全资源的授权中间件 (UseAuthorization)。
会话中间件 (UseSession)
建立和维护会话状态。 如果应用使用会话状态,请在 Cookie 策略中间件之后和 MVC 中间件之前调用会话中间件。用于将 Razor Pages 终结点添加到请求管道的终结点路由中间件(带有 MapRazorPages 的 UseEndpoints)。
中间件的执行顺序?
异常/错误处理
》
HTTP 严格传输安全协议
》
HTTPS 重定向
》
静态文件服务器
》
Cookie 策略实施
》
身份验证
》
会话
》
MVC
application builder的use和run方法有什么区别?
这两个方法都在startup class的configure方法里面调用。都是用来向应用请求管道里面添加中间件的。
Use:通过Use的方式注册中间件,可以控制是否将请求传递到下一个中间件;
Run:通过Run的方式注册中间件,一般用于断路或请求管道末尾,即不会将请求传递下去;
dotnet core 管道里面的map拓展有什么作用?
可以针对不同的路径添加不同的中间件。
1 | public void Configure(IApplicationBuilder app) |
dot net core里面的路径是如何处理的?
路径处理是用来为进入的请求寻找处理函数的机制。所有的路径在函数运行开始时进行注册。
主要有两种路径处理方式:
1)常规路径处理和属性路径处理。常规路径处理就是用MapRoute的方式设定调用路径;
2)属性路径处理是指在调用函数的上方设定一个路径属性;
dotnet core工程里面有哪些常见的工程文件?
global, launch setting,app settings,bundle config,bower, package。
依赖注入实现原理?
实现DI,核心在于依赖注入容器IContainer,该容器具有以下功能:
①.(容器)保存可用服务的集合 // 要用的特定对象、特定类、接口服务
②.(注册)提供一种方式将各种部件与他们依赖的服务绑定到一起;// Add…函数或containerBuilder.Register函数,
③.(解析点)为应用程序提供一种方式来请求已配置的对象: 构造函数注入、属性注入.运行时,框架会一层层通过反射构造实例,最终得到完整对象。
ASP.NET Core项目如何设置IP地址和端口号?
可以使用Properties文件夹下的launchSettings配置文件来配置不同的启动方式的时候,分别配置IP和端口号。