旅游网站 系统,海外网络加速器免费,南昌做网站软件,wordpress文章形式前言至于为什么要搭建.Net Core 平台#xff0c;这个网上的解释以及铺天盖地#xff0c;想了想#xff0c;还是感觉重要的一点#xff0c;跨平台#xff0c;嗯#xff01;没错#xff0c;而且比.Net 更容易搭建#xff0c;速度也更快#xff0c;所有的包均由Nuget提供… 前言至于为什么要搭建.Net Core 平台这个网上的解释以及铺天盖地想了想还是感觉重要的一点跨平台嗯没错而且比.Net 更容易搭建速度也更快所有的包均由Nuget提供不再像以前的单纯引入组件已经没有了之前的Assemblies和COM的引入初次使用感觉会很别扭不过使用多了发现还是很方便的所以你一定要会使用Nuget真的很强大这点儿设计思路感觉更像Linux了。下边这三点是先对 .net core 有一个初步的认识看得懂或者看不懂都没有关系以后大家肯定都会明白的 1、.net core 框架性能测试http://www.techempower.com/benchmarks/ 我们可以通过这个web框架性能测试来看看 aspcore 的性能 2、.net core 执行过程3、中间件执行过程启动的时候先执行该中间件类的构造函数然后一路 Next() 下去返回的时候正好是反向的执行的是该类的逻辑部分 4、AOP切面 5、整体框架结构与数据库表UML 一、创建第一个Core 说了从零开始就得从零开始老生常谈开始。1、SDK 安装当然前提是你得安装.Net Core 的 SDK 环境这里只能使用 vs 2019 且版本在 16.3 以上。 下载 SDK 地址 https://dotnet.microsoft.com/download选择指定的平台即可安装 这里说下SDK 和 RunTime 的区别1、SDK 是用来开发 NetCore 的内部捆绑了 Runtime 运行时2、但是如果只想运行 NetCore 项目的话只需要在服务器中安装 Runtime 运行时即可 怎么判断安装成功了呢直接运行命令如果有结果证明成功了 2、新建项目1、打开vs2019 创建一个新的项目这里有很多模板大家都可以试试 2、点击下一步 Next。3、然后创建模板 这里要注意下关于Https选项问题有很多小伙伴在以后的接口调用中勾选了这个但是还是一直使用 http 协议去访问导致找不到响应的接口地址。 1、是你的项目创建的时候勾选了 Https 选项如果你还没有创建那就可以不要勾选那个 HTTPS选项。2、如果你的项目已经创建好了每次访问都是HTTPS的但是你不想这么做可以在 launthSettings.json 文件中把sslPort 端口号改成0即可 3、删除IIS配置默认使用 kestrel 服务器 3、项目整体结构分析接下来咱们看看这个项目都包含了哪些东西 这里默认有一个 WeatherForecastController.cs 打开后1、当前控制器继承了 ControllerBase 基类2、有一个路由特性可以配置当前路由规则比如当前的是[Route([controller])]表示 Url 路径为 localhost:5000/weacherforecast 如果你配置 [Route([controller]/[action])] 表明 Url 路径为 localhost:5000/weacherforecast/get3、发现有一个默认的构造函数里边已经注入了日志 ILogger这个依赖注入相关内容以后会讲到4、默认提供了一个 get 方法随机生成了一个天气集合 接下来点开appsettings.json文件这里就是整个系统app的配置地址更类似以前的web.config以后大家会用到。 继续往下打开Startup.cs 文件这里是整个项目的启动文件所有的启动相关的都会在这里配置比如 依赖注入跨域请求Redis缓存等更多详情在以后的文章中都会有所提起 二、重要文件说明1、Program.csnamespace blog.core.test3._0{ public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder { webBuilder.UseStartupStartup(); }); }}下边的内容如果不理解也无所谓以后会慢慢懂的至少要读几遍知道相关概念。这个Program是程序的入口, 看起来很眼熟, 是因为asp.net core application实际就是控制台程序(console application).它是一个调用asp.net core 相关库的console application. Main方法里面的内容主要是用来配置和运行程序的。因为我们的web程序需要一个宿主,所以CreateHostBuilder这个方法就创建了一个IHostBuilder. 而且我们还需要Web Server.asp.net core 自带了两种http servers, 一个是WebListener, 它只能用于windows系统, 另一个是kestrel, 它是跨平台的.kestrel是默认的web server, 就是通过UseKestrel()这个方法来启用的.但是我们开发的时候使用的是IIS Express, 调用UseIISIntegration()这个方法是启用IIS Express, 它作为Kestrel的Reverse Proxy server来用. 如果在windows服务器上部署的话, 就应该使用IIS作为Kestrel的反向代理服务器来管理和代理请求.如果在linux上的话, 可以使用apache, nginx等等的作为kestrel的proxy server.当然也可以单独使用kestrel作为web 服务器, 但是使用iis作为反向代理还是有很多有优点的: 例如,IIS可以过滤请求, 管理证书, 程序崩溃时自动重启等.不过目前因为跨平台所以使用较多的还是 nginx。webBuilder.UseStartupStartup();, 这句话表示在程序启动的时候, 我们会调用Startup这个类.Build()完之后返回一个实现了 IHost 接口的实例(IHostBuilder), 然后调用Run()就会运行Web程序, 并且阻止这个调用的线程, 直到程序关闭. 如果想要对AspNetCore源码进行研究可以查看源码这里提供两个方法1、F12当然这个不能看到详细的你需要安装一个组件VS2017 Resharper2、查看Github 开源源码 https://github.com/aspnet/MetaPackages/tree/master/src/Microsoft.AspNetCore 最后让大家看看我的 Blog.Core 项目最终的 Services 2、Startup.cs public class Startup { public Startup(IConfiguration configuration) { Configuration configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints { endpoints.MapControllers(); }); } }其实Startup算是程序真正的切入点是配置服务和中间件的启动类。Startup 默认构造函数注入了配置项 IConfiguration。ConfigureServices方法是用来把services(各种服务, 例如identity, ef, mvc等等包括第三方的, 或者自己写的)加入(register)到container(asp.net core的容器)中去, 并配置这些services. 这个container是用来进行dependency injection的(依赖注入). 所有注入的services(此外还包括一些框架已经注册好的services) 在以后写代码的时候, 都可以将它们注入(inject)进去. 例如上面的Configure方法的参数, app, env, loggerFactory都是注入进去的services. Configure 方法是asp.net core程序用来具体指定如何处理每个http请求的, 例如我们可以让这个程序知道我使用mvc来处理http请求, 那就调用 app.UseEndpoints 这个方法就行这个是一个短路中间件表示 http 请求到了这里就不往下走了. 看一看我们项目的最后Configure方法是如何配置的这个现在看看就行以后肯定会让大家都慢慢掌握 public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IBlogArticleServices _blogArticleServices) { #region ReuestResponseLog if (Appsettings.app(AppSettings, Middleware_RequestResponse, Enabled).ObjToBool()) { app.UseReuestResponseLog();//记录请求与返回数据 } #endregion #region Environment if (env.IsDevelopment()) { // 在开发环境中使用异常页面这样可以暴露错误堆栈信息所以不要放在生产环境。 app.UseDeveloperExceptionPage(); //app.Use(async (context, next) //{ // //这里会多次调用这里测试一下就行不要打开注释 // //var blogs await _blogArticleServices.GetBlogs(); // var processName System.Diagnostics.Process.GetCurrentProcess().ProcessName; // Console.WriteLine(processName); // await next(); //}); } else { app.UseExceptionHandler(/Error); // 在非开发环境中使用HTTP严格安全传输(or HSTS) 对于保护web安全是非常重要的。 // 强制实施 HTTPS 在 ASP.NET Core配合 app.UseHttpsRedirection //app.UseHsts(); } #endregion #region Swagger app.UseSwagger(); app.UseSwaggerUI(c { //根据版本名称倒序 遍历展示 typeof(ApiVersions).GetEnumNames().OrderByDescending(e e).ToList().ForEach(version { c.SwaggerEndpoint($/swagger/{version}/swagger.json, ${ApiName} {version}); }); // 将swagger首页设置成我们自定义的页面记得这个字符串的写法解决方案名.index.html c.IndexStream () GetType().GetTypeInfo().Assembly.GetManifestResourceStream(Blog.Core.index.html);//这里是配合MiniProfiler进行性能监控的《文章完美基于AOP的接口性能分析》如果你不需要可以暂时先注释掉不影响大局。 c.RoutePrefix ; //路径配置设置为空表示直接在根域名localhost:8001访问该文件,注意localhost:8001/swagger是访问不到的去launchSettings.json把launchUrl去掉如果你想换一个路径直接写名字即可比如直接写c.RoutePrefix doc; }); #endregion #region MiniProfiler app.UseMiniProfiler(); #endregion #region CORS //跨域第二种方法使用策略详细策略信息在ConfigureService中 app.UseCors(LimitRequests);//将 CORS 中间件添加到 web 应用程序管线中, 以允许跨域请求。 #region 跨域第一种版本 //跨域第一种版本请要ConfigureService中配置服务 services.AddCors(); // app.UseCors(options options.WithOrigins(http://localhost:8021).AllowAnyHeader() //.AllowAnyMethod()); #endregion #endregion // 跳转https //app.UseHttpsRedirection(); // 使用静态文件 app.UseStaticFiles(); // 使用cookie app.UseCookiePolicy(); // 返回错误码 app.UseStatusCodePages();//把错误码返回前台比如是404 app.UseRouting(); #region 第三步开启认证中间件 //此授权认证方法已经放弃请使用下边的官方验证方法。但是如果你还想传User的全局变量还是可以继续使用中间件第二种写法//app.UseMiddlewareJwtTokenAuth(); //app.UseJwtTokenAuth(); //如果你想使用官方认证必须在上边ConfigureService 中配置JWT的认证服务 (.AddAuthentication 和 .AddJwtBearer 二者缺一不可) app.UseAuthentication(); #endregion app.UseAuthorization(); app.UseEndpoints(endpoints { endpoints.MapControllerRoute( name: default, pattern: {controllerHome}/{actionIndex}/{id?}); endpoints.MapHubChatHub(/api2/chatHub); }); } 3、运行方法.net core 调试的两种方法1、通过IIS调试 2、项目自带的Kestrel web应用调式 三、注册并使用MVC首先在 ConfigureServices里添加控制器服务因为我们这里是api项目所以只需要添加 AddController() 即可如果是 MVC可以使用 AddControllersWithViews();然后在 Configure 中配置一下中间件 app.UseEndpoints(endpoints { endpoints.MapControllers(); });这样就达到了目的这个不仅仅是 mvc 的开发过程其他的也都是这样的以后我们开发其他的都需要按照这个过程开发即可。四、核心知识点1、Routing 路由路由有两种方式: Convention-based (按约定), attribute-based(基于路由属性配置的). 其中convention-based (基于约定的) 主要用于MVC (返回View或者Razor Page那种的).Web api 推荐使用attribute-based.这种基于属性配置的路由可以配置Controller或者Action级别, uri会根据Http method然后被匹配到一个controller里具体的action上.常用的Http Method有:Get, 查询, Attribute: HttpGet, 例如: /api/product, /api/product/1POST, 创建, HttpPost, /api/productPUT 整体修改更新 HttpPut, /api/product/1PATCH 部分更新, HttpPatch, /api/product/1DELETE 删除, HttpDelete, /api/product/1还有一个Route属性(attribute)也可以用于Controller层, 它可以控制action级的URI前缀.//以下不是本系列教程就看思路即可不用敲代码namespace CoreBackend.Api.Controllers{ //[Route(api/product)] [Route(api/[controller])] public class ProductController: Controller { [HttpGet] public JsonResult GetProducts() { return new JsonResult(new ListProduct { new Product { Id 1, Name 牛奶, Price 2.5f }, new Product { Id 2, Name 面包, Price 4.5f } }); } }}使用[Route(api/[controller])], 它使得整个Controller下面所有action的uri前缀变成了/api/product, 其中[controller]表示XxxController.cs中的Xxx(其实是小写).也可以具体指定, [Route(api/product)], 这样做的好处是, 如果ProductController重构以后改名了, 只要不改Route里面的内容, 那么请求的地址不会发生变化.然后在GetProducts方法上面, 写上HttpGet, 也可以写HttpGet(). 它里面还可以加参数,例如: HttpGet(all), 那么这个Action的请求的地址就变成了 /api/product/All. 2、内容协商 Content Negotiation如果 web api提供了多种内容格式, 那么可以通过Accept Header来选择最好的内容返回格式: 例如:application/json, application/xml等等如果设定的格式在web api里面没有, 那么web api就会使用默认的格式.asp.net core 默认提供的是json格式, 也可以配置xml等格式.目前只考虑 Output formatter, 就是返回的内容格式. 如果想输出xml格式就配置这里 3、创建Post Action以下不是本系列就看思路即可不用敲代码//以下不是本系列教程就看思路即可不用敲代码 [Route({id}, Name GetProduct)] public IActionResult GetProduct(int id) { var product ProductService...(x x.Id id); if (product null) { return NotFound(); } return Ok(product); } [HttpPost] public IActionResult Post([FromBody] ProductCreation product) { if (product null) { return BadRequest(); } var maxId ProductService.Max(x x.Id); var newProduct new Product { Id maxId, Name product.Name, Price product.Price }; ProductService.Add(newProduct); return CreatedAtRoute(GetProduct, new { id newProduct.Id }, newProduct); }[HttpPost] 表示请求的谓词是Post. 加上Controller的Route前缀, 那么访问这个Action的地址就应该是: api/product后边也可以跟着自定义的路由地址, 例如 [HttpPost(create)], 那么这个Action的路由地址就应该是: api/product/create.[FromBody] , 请求的body里面包含着方法需要的实体数据, 方法需要把这个数据Deserialize成ProductCreation, [FromBody]就是干这些活的.客户端程序可能会发起一个Bad的Request, 导致数据不能被Deserialize, 这时候参数product就会变成null. 所以这是一个客户端发生的错误, 程序为让客户端知道是它引起了错误, 就应该返回一个Bad Request 400 (Bad Request表示客户端引起的错误)的 Status Code.传递进来的model类型是 ProductCreation, 而我们最终操作的类型是Product, 所以需要进行一个Map操作, 目前还是挨个属性写代码进行Map吧, 以后会改成Automapper.返回 CreatedAtRoute: 对于POST, 建议的返回Status Code 是 201 (Created), 可以使用CreatedAtRoute这个内置的Helper Method. 它可以返回一个带有地址Header的Response, 这个Location Header将会包含一个URI, 通过这个URI可以找到我们新创建的实体数据. 这里就是指之前写的GetProduct(int id)这个方法. 但是这个Action必须有一个路由的名字才可以引用它, 所以在GetProduct方法上的Route这个attribute里面加上NameGetProduct, 然后在CreatedAtRoute方法第一个参数写上这个名字就可以了, 尽管进行了引用, 但是Post方法走完的时候并不会调用GetProduct方法. CreatedAtRoute第二个参数就是对应着GetProduct的参数列表, 使用匿名类即可, 最后一个参数是我们刚刚创建的数据实体. 运行程序试验一下, 注意需要在Headers里面设置Content-Type: application/json.4、Validation 验证针对上面的Post方法, 如果请求没有Body, 参数product就会是null, 这个我们已经判断了; 如果body里面的数据所包含的属性在product中不存在, 那么这个属性就会被忽略.但是如果body数据的属性有问题, 比如说name没有填写, 或者name太长, 那么在执行action方法的时候就会报错, 这时候框架会自动抛出500异常, 表示是服务器的错误, 这是不对的. 这种错误是由客户端引起的, 所以需要返回400 Bad Request错误.验证Model/实体, asp.net core 内置可以使用 Data Annotations进行: //以下不是本系列教程就看思路即可不用敲代码using System;using System.ComponentModel.DataAnnotations;namespace CoreBackend.Api.Dtos{ public class ProductCreation { [Display(Name 产品名称)] [Required(ErrorMessage {0}是必填项)] // [MinLength(2, ErrorMessage {0}的最小长度是{1})] // [MaxLength(10, ErrorMessage {0}的长度不可以超过{1})] [StringLength(10, MinimumLength 2, ErrorMessage {0}的长度应该不小于{2}, 不大于{1})] public string Name { get; set; } [Display(Name 价格)] [Range(0, Double.MaxValue, ErrorMessage {0}的值必须大于{1})] public float Price { get; set; } }}这些Data Annotation (理解为用于验证的注解), 可以在System.ComponentModel.DataAnnotation找到, 例如[Required]表示必填, [MinLength]表示最小长度, [StringLength]可以同时验证最小和最大长度, [Range]表示数值的范围等等很多.[Display(Namexxx)]的用处是, 给属性起一个比较友好的名字.其他的验证注解都有一个属性叫做 ErrorMessage (string), 表示如果验证失败, 就会把ErrorMessage的内容添加到错误结果里面去. 这个ErrorMessage可以使用参数, {0}表示Display的Name属性, {1}表示当前注解的第一个变量, {2}表示当前注解的第二个变量.在Controller里面添加验证逻辑://以下不是本系列教程就看思路即可不用敲代码 [HttpPost] public IActionResult Post([FromBody] ProductCreation product) { if (product null) { return BadRequest(); } if (!ModelState.IsValid) { return BadRequest(ModelState); } var maxId ProductService.Max(x x.Id); var newProduct new Product { Id maxId, Name product.Name, Price product.Price }; ProductService.Add(newProduct); return CreatedAtRoute(GetProduct, new { id newProduct.Id }, newProduct); } ModelState: 是一个Dictionary, 它里面是请求提交到Action的Name和Value的对们, 一个name对应着model的一个属性, 它也包含了一个针对每个提交的属性的错误信息的集合.每次请求进到Action的时候, 我们在ProductCreationModel添加的那些注解的验证, 就会被检查. 只要其中有一个验证没通过, 那么ModelState.IsValid属性就是False. 可以设置断点查看ModelState里面都有哪些东西.如果有错误的话, 我们可以把ModelState当作 Bad Request的参数一起返回到前台.5、PUT请求put应该用于对model进行完整的更新. 首先最好还是单独为Put写一个Dto Model, 尽管属性可能都是一样的, 但是也建议这样写, 实在不想写也可以.ProducModification.cs public class ProductModification { [Display(Name 产品名称)] [Required(ErrorMessage {0}是必填项)] [StringLength(10, MinimumLength 2, ErrorMessage {0}的长度应该不小于{2}, 不大于{1})] public string Name { get; set; } [Display(Name 价格)] [Range(0, Double.MaxValue, ErrorMessage {0}的值必须大于{1})] public float Price { get; set; } }然后编写Controller的方法://以下不是本系列教程就看思路即可不用敲代码 [HttpPut({id})] public IActionResult Put(int id, [FromBody] ProductModification product) { if (product null) { return BadRequest(); } if (product.Name 产品) { ModelState.AddModelError(Name, 产品的名称不可以是产品二字); } if (!ModelState.IsValid) { return BadRequest(ModelState); } var model ProductService.SingleOrDefault(x x.Id id); if (model null) { return NotFound(); } model.Name product.Name; model.Price product.Price; // return Ok(model); return NoContent(); } 按照Http Put的约定, 需要一个id这样的参数, 用于查找现有的model.由于Put做的是完整的更新, 所以把ProducModification整个Model作为参数.进来之后, 进行了一套和POST一模一样的验证, 这地方肯定可以改进, 如果验证逻辑比较复杂的话, 到处写同样验证逻辑肯定是不好的, 所以建议使用FluentValidation.然后, 把ProductModification的属性都映射查询找到给Product, 这个以后用AutoMapper来映射.返回: PUT建议返回NoContent(), 因为更新是客户端发起的, 客户端已经有了最新的值, 无须服务器再给它传递一次, 当然了, 如果有些值是在后台更新的, 那么也可以使用Ok(xxx)然后把更新后的model作为参数一起传到前台. 五、结语 好啦项目搭建就这么愉快的解决了而且你也应该简单了解了.Net Core API是如何安装创建各个文件的意义以及如何运作如何配置等但是既然是接口那一定是要前后端一起进行配置使用交流的平台从上文看出每次都特别麻烦而且不直观UI 不友好怎么办呢 下一节我们就使用一个神器 Swagger一个快速轻量级的项目RESTFUL接口的文档在线自动生成功能测试功能软件。 Github Giteehttps://github.com/anjoy8/Blog.Core.git NOTE如何不会使用Git可以参考https://www.jianshu.com/p/2b666a08a3b5 一起学习一起进步 QQ群867095512