ASP.NET Core使用HostingStartup增强启动操作方法详解

概念

在ASP.NET Core中我们可以使用一种机制来增强启动时的操作,它就是HostingStartup。如何叫"增强"操作,相信了解过AOP概念的同学应该都非常的熟悉。我们常说AOP使用了关注点分离的方式,增强了对现有逻辑的操作。而我们今天要说的HostingStartup就是为了"增强"启动操作,这种"增强"的操作甚至可以对现有的程序可以做到无改动的操作。例如,外部程序集可通过HostingStartup实现为应用提供配置服务、注册服务或中间件管道操作等。

使用方式

HostingStartup属性表示要在运行时激活的承载启动程序集。大致分为两种情况,一种是自动扫描当前Web程序集中通过HostingStartup指定的类,另一种是手动添加配置hostingstartupassembles指定外部的程序集中通过HostingStartup指定的类。第一种方式相对简单,但是对Web程序本身有入侵,第二种方式稍微复杂一点点,但是可以做到对现有代码无入侵操作,接下来我们分别演示这两种使用方式。

ASP.NET Core中直接定义

首先是在ASP.NET Core程序中直接使用HostingStartup,这种方式比较简单首先在Web程序中随便定义一个类,然后实现IHostingStartup接口,最后别忘了在程序集中添加HostingStartupAttribute指定要启动的类的类型,具体代码如下所示

using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
//通过HostingStartup指定要启动的类型
[assembly: HostingStartup(typeof(HostStartupWeb.HostingStartupInWeb))]
namespace HostStartupWeb
{
 public class HostingStartupInWeb : IHostingStartup
 {
 public void Configure(IWebHostBuilder builder)
 {
  //程序启动时打印依据话,代表执行到了这里
  Debug.WriteLine("Web程序中HostingStartupInWeb类启动");

  //可以添加配置
  builder.ConfigureAppConfiguration(config => {
  //模拟添加一个一个内存配置
  var datas = new List<KeyValuePair<string, string>>
  {
   new KeyValuePair<string, string>("ServiceName", "HostStartupWeb")
  };
  config.AddInMemoryCollection(datas);
  });

  //可以添加ConfigureServices
  builder.ConfigureServices(services=> {
  //模拟注册一个PersonDto
  services.AddScoped(provider=>new PersonDto { Id = 1, Name = "yi念之间", Age = 18 });
  });

  //可以添加Configure
  builder.Configure(app => {
  //模拟添加一个中间件
  app.Use(async (context, next) =>
  {
   await next();
  });
  });
 }
 }
}

仅仅使用上面所示的这些代码,便可在Web程序启动的时候去自动执行HostingStartupInWeb的Configure方法,在这里面我们几乎可以使用所有针对ASP.NET Core程序配置的操作,而且不需要在Web程序中额外添加别的代码就可以自动调用HostingStartupInWeb的Configure方法。

外部程序集引入

我们之前也说过,上面的方式虽然使用起来相对简单一点,仅仅是一点,那就是省去了指定启动程序集的逻辑。但是,上面的方式需要在Web程序中添加,这样的话还是会修改代码。而且,可能更多的时候我们是在外部的程序集中编写HostingStartup逻辑,这时候就需要使用另一种方式在将外部程序集中引入HostingStartup。首先我们要在自定义的程序集中至少引入Microsoft.AspNetCore.Hosting包才能使用HostingStartup

<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />

如果你不需要使用注册中间件的逻辑那么仅仅引入Microsoft.AspNetCore.Hosting.Abstractions即可

<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />

如果需要使用其他功能包,可以自行在定义的程序集中引入。比如我们定义了一个名为HostStartupLib的Standard类库,并创建了名为HostStartupLib的类

using System;
using System.Collections.Generic;
using System.Diagnostics;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
[assembly: HostingStartup(typeof(HostStartupLib.HostingStartupInLib))]
namespace HostStartupLib
{
 public class HostingStartupInLib : IHostingStartup
 {
 public void Configure(IWebHostBuilder builder)
 {
  Debug.WriteLine("Lib程序中HostingStartupInLib类启动");

  //添加配置
  builder.ConfigureAppConfiguration((context, config) => {
  var datas = new List<KeyValuePair<string, string>>
  {
   new KeyValuePair<string, string>("ServiceName", "HostStartupLib")
  };
  config.AddInMemoryCollection(datas);
  });

  //添加ConfigureServices
  builder.ConfigureServices(services=> {
  services.AddScoped(provider=>new PersonDto { Id = 2, Name = "er念之间", Age = 19 });
  });

  //添加Configure
  builder.Configure(app => {
  app.Use(async (context, next) =>
  {
   await next();
  });
  });

 }
 }
}

然后我们将自定义的HostStartupLib这个Standard类库引入Web项目中,运行Web程序,发现HostingStartupInLib的Configure方法并不能被调用。其实我们上面说过了,将HostingStartup从外部程序集引入的话需要手动指定启动程序集的名称。指定启动程序集的方式有两种,一种是指定IWebHostBuilder的扩展UseSetting指定

public static IHostBuilder CreateHostBuilder(string[] args) =>
  Host.CreateDefaultBuilder(args)
  .ConfigureWebHostDefaults(webBuilder =>
  {
   //通过UseSetting的方式指定程序集的名称
   webBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "HostStartupLib");
   //如果HostingStartup存在多个程序集中可以使用;分隔,比如HostStartupLib;HostStartupLib2
   //webBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "HostStartupLib;HostStartupLib2");
   webBuilder.UseStartup<Startup>();
  });

另一种通过添加环境变量ASPNETCORE_HOSTINGSTARTUPASSEMBLIES的方式,可以通过设置launchSettings.json中

"environmentVariables": {
 "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "HostStartupLib"
 //如果HostingStartup存在多个程序集中可以使用;分隔,比如HostStartupLib;HostStartupLib2
 //"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "HostStartupLib;HostStartupLib2"
}

可以引入多个包含HostingStartup的程序集,在设置WebHostDefaults.HostingStartupAssembliesKey或者ASPNETCORE_HOSTINGSTARTUPASSEMBLIES指定多个程序集名称可以使用英文分号(;)隔开程序集名称。虽然是两种形似指定,但是其实本质是一样的那就是设置配置key为hostingStartupAssemblie配置的值,下面我们会详细讲解。
通过在程序中设置环境变量的方式等同于Window系统中Set的方式设置环境变量,或Linux系统中export的方式设置环境变量,亦或是直接设置系统环境变量,效果都是一致的。指定完成启动程序集之后,再次运行程序便可以看到HostingStartupInLib的Configure方法被调用到了。在这里我们可以看到如果是使用的环境变量的方式去指定启动程序集的话,对现有代码可以做到完全无入侵。

源码探究

在上面我们简单的介绍了HostingStartup的概念及基本的使用方式,基于这些我们产生了几个疑问

  • 首先是关于HostingStartup的基本工作方式是什么
  • 其次是为什么HostingStartup在Web程序中不需要配置程序集信息就可以被调用到,而通过外部程序集引入HostingStartup需要手动指定程序集
  • 最后是通过外部程序集引入HostingStartup的指定方式为何只能是UseSetting和环境变量的方式
  • 基于以上几个疑问,我们来探索一下HostingStartup的相关源码,来揭开它的神秘面纱。首先废话不多说直接找到源码位置[点击查看源码👈]在GenericWebHostBuilder类中的ExecuteHostingStartups方法中,关于GenericWebHostBuilder类我们在上篇文章深入探究ASP.NET Core Startup初始化中主要就是分析这个类,因为这是构建WebHost的默认类,而我们接下来要说的ExecuteHostingStartups方法也是承载在这个类中,直接贴代码如下所示
private void ExecuteHostingStartups()
{
 //通过配置_config和当前程序集名称构建WebHostOptions类
 var webHostOptions = new WebHostOptions(_config, Assembly.GetEntryAssembly()?.GetName().Name);
 //如果PreventHostingStartup属性为true则直接返回
 //通过这个可以配置阻止启动逻辑
 if (webHostOptions.PreventHostingStartup)
 {
 return;
 }

 var exceptions = new List<Exception>();
 //构建HostingStartupWebHostBuilder
 _hostingStartupWebHostBuilder = new HostingStartupWebHostBuilder(this);
 //GetFinalHostingStartupAssemblies获取最终要执行的程序集名称
 foreach (var assemblyName in webHostOptions.GetFinalHostingStartupAssemblies().Distinct(StringComparer.OrdinalIgnoreCase))
 {
 try
 {
  //通过程序集名称加载程序集信息,因为使用了AssemblyName所以只需要使用程序集名称即可
  var assembly = Assembly.Load(new AssemblyName(assemblyName));
  //获取包含HostingStartupAttribute的程序集
  foreach (var attribute in assembly.GetCustomAttributes<HostingStartupAttribute>())
  {
  //实例化HostingStartupAttribute的HostingStartupType属性的对象实例
  //即我们上面声明的[assembly: HostingStartup(typeof(HostStartupWeb.HostingStartupInWeb))]
  var hostingStartup = (IHostingStartup)Activator.CreateInstance(attribute.HostingStartupType);
  //调用HostingStartup的Configure方法
  hostingStartup.Configure(_hostingStartupWebHostBuilder);
  }
 }
 catch (Exception ex)
 {
  exceptions.Add(new InvalidOperationException($"Startup assembly {assemblyName} failed to execute. See the inner exception for more details.", ex));
 }
 }

 if (exceptions.Count > 0)
 {
 _hostingStartupErrors = new AggregateException(exceptions);
 }
}

通过上面的源码我们就可以很清楚的了解到HostingStartup的基本工作方式。获取的程序集中包含的HostingStartupAttribute,通过获取HostingStartupAttribute的HostingStartupType属性得到要执行的IHostingStartup实例,最后执行Configure方法,Configure方法需要传递IWebHostBuilder的实例,而HostingStartupWebHostBuilder正是实现了IWebHostBuilder接口。
我们了解到了HostStartup的工作方式,接下来我们来探究一下为什么HostingStartup在Web程序中不需要配置程序集信息就可以被调用到,而通过外部程序集引入HostingStartup需要手动指定程序集。通过上面的源码我们可以得到一个信息那就是所有需要启动的程序集信息都是来自WebHostOptions的GetFinalHostingStartupAssemblies方法,接下来我们就来查看一下GetFinalHostingStartupAssemblies方法的实现源码[点击查看源码👈]

public IEnumerable<string> GetFinalHostingStartupAssemblies()
{
 return HostingStartupAssemblies.Except(HostingStartupExcludeAssemblies, StringComparer.OrdinalIgnoreCase);
}

从这里我们可以看出程序集信息来自于HostingStartupAssemblies属性,而且还要排除掉HostingStartupExcludeAssemblies包含的程序集。我们找到他们初始化的相关逻辑大致如下

//承载启动是需要调用的HostingStartup程序集
public IReadOnlyList<string> HostingStartupAssemblies { get; set; }
//承载启动时排除掉不不要执行的程序集
public IReadOnlyList<string> HostingStartupExcludeAssemblies { get; set; }
//是否阻止HostingStartup启动执行功能,如果设置为false则HostingStartup功能失效
//通过上面的ExecuteHostingStartups方法源码可知
public bool PreventHostingStartup { get; set; }
//应用程序名称
public string ApplicationName { get; set; }

public WebHostOptions(IConfiguration configuration, string applicationNameFallback)
{
 ApplicationName = configuration[WebHostDefaults.ApplicationKey] ?? applicationNameFallback;
 HostingStartupAssemblies = Split($"{ApplicationName};{configuration[WebHostDefaults.HostingStartupAssembliesKey]}");
 HostingStartupExcludeAssemblies = Split(configuration[WebHostDefaults.HostingStartupExcludeAssembliesKey]);
 PreventHostingStartup = WebHostUtilities.ParseBool(configuration, WebHostDefaults.PreventHostingStartupKey);
}

//分隔配置的程序集信息,分隔依据为";"分号,这也是我们上面说过配置多程序集的时候采用分号分隔的原因
private IReadOnlyList<string> Split(string value)
{
 return value?.Split(';', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
 ?? Array.Empty<string>();
}

首先,通过HostingStartupAssemblies的初始化逻辑我们可以得出,默认会是有两个数据来源,一个是当前的ApplicationName,另一个是通过HostingStartupAssembliesKey配置的程序集信息。这也解答了我们上面说过的为什么HostingStartup在Web程序中不需要配置程序集信息就可以被调用到,而通过外部程序集引入HostingStartup需要手动指定程序集。其次,我们可以了解到通过配置HostingStartupExcludeAssemblies信息排除你不想启动的HostingStartup程序集,而且还可以通过配置PreventHostingStartup值来禁止使用HostingStartup的功能。
通过上面的代码我们还了解到这三个属性的来源的配置名称都是来自WebHostDefaults这个常量类,接下来我们查看一下这三个属性对应的配置名称

public static readonly string HostingStartupAssembliesKey = "hostingStartupAssemblies";
public static readonly string HostingStartupExcludeAssembliesKey = "hostingStartupExcludeAssemblies";
public static readonly string PreventHostingStartupKey = "preventHostingStartup";

也就是说,我们可以可以通过配置这三个名称的配置,来完成HostingStartup相关的功能比如

public static IHostBuilder CreateHostBuilder(string[] args) =>
  Host.CreateDefaultBuilder(args)
  .ConfigureWebHostDefaults(webBuilder =>
  {
   //通过UseSetting的方式指定程序集的名称
   webBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "HostStartupLib");
   //如果HostingStartup存在多个程序集中可以使用;分隔,比如HostStartupLib;HostStartupLib2
   //webBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "HostStartupLib;HostStartupLib2");

   //排除执行HostStartupLib2程序集执行HostingStartup逻辑
   webBuilder.UseSetting(WebHostDefaults.HostingStartupExcludeAssembliesKey, "HostStartupLib2");
   //禁用HostingStartup功能
   webBuilder.UseSetting(WebHostDefaults.PreventHostingStartupKey, "true");
   webBuilder.UseStartup<Startup>();
  });

或通过环境变量的方式去操作

"environmentVariables": {
 "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "HostStartupLib",
 //如果HostingStartup存在多个程序集中可以使用;分隔,比如HostStartupLib;HostStartupLib2
 //"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "HostStartupLib;HostStartupLib2"

 //排除执行HostStartupLib2程序集执行HostingStartup逻辑
 "ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES":"HostStartupLib2",
 //禁用HostingStartup功能
 "ASPNETCORE_PREVENTHOSTINGSTARTUP":"true"
}

其实这两种配置方式是完全等价的,为什么这么说呢?首先是在Configuration中获取配置是忽略大小写的,其实是使用ConfigureWebHostDefaults配置WebHost相关信息的时候会添加configBuilder.AddEnvironmentVariables(prefix: "ASPNETCORE_")逻辑这样的话获取环境变量的时候可以忽略ASPNETCORE_前缀。
那么到目前为止,还有一个疑问尚未解决,那就是为何只能通过UseSetting和环境变量的方式去配置HostingStartup相关配置,解铃还须系铃人,我们在上面的ExecuteHostingStartups方法中看到了这个逻辑

//这里传递了一个_config
var webHostOptions = new WebHostOptions(_config, Assembly.GetEntryAssembly()?.GetName().Name);

我们可以看到传递了配置Configuration的实例_config,我们到初始化_config地方有如下逻辑

var configBuilder = new ConfigurationBuilder()
  .AddInMemoryCollection();
if (!options.SuppressEnvironmentConfiguration)
{
 //添加环境变量
 configBuilder.AddEnvironmentVariables(prefix: "ASPNETCORE_");
}
//构建了_config实例
private readonly IConfiguration _config = configBuilder.Build();

也就可以解释为何我们可以通过环境变量去配置HostingStartup,然后我们再来看UseSetting方法的逻辑

public IWebHostBuilder UseSetting(string key, string value)
{
 _config[key] = value;
 return this;
}

原来UseSetting也是给_config实例设置值,所以无论通过UseSetting或环境环境变量的方式去配置,本质都是在操作_config这个配置实例,到此为止所有谜团均以解开。

在SkyAPM中的使用

我们上面说了HostingStartup可以增强启动时候的操作,可以通过对现有代码无入侵的方式增强程序功能。而SkyAPM-dotnet也正是使用了这个功能,实现了无入侵启动APM监控。我们来回顾一下SkyAPM-dotnet的使用方式

首先是使用Nuget添加SkyAPM.Agent.AspNetCore程序集引用。

  • 其次是在launchSettings.json文件中添加ASPNETCORE_HOSTINGSTARTUPASSEMBLIES:"SkyAPM.Agent.AspNetCore"环境变量配置(等同于set ASPNETCORE_HOSTINGSTARTUPASSEMBLIES=SkyAPM.Agent.AspNetCore或export ASPNETCORE_HOSTINGSTARTUPASSEMBLIES=SkyAPM.Agent.AspNetCore
  • 的方式,本质都是在配置环境变量)
  • 最后通过SKYWALKING__SERVICENAME设置程序名称
  • 这里我们通过需要配置ASPNETCORE_HOSTINGSTARTUPASSEMBLIES名称可以看出确实是使用了HostingStartup功能,而通过HostingStartup增强的操作入口肯定就在SkyAPM.Agent.AspNetCore程序集中,我们找到SkyAPM.Agent.AspNetCore程序集的源码[点击查看源码👈]看到了SkyApmHostingStartup类实现如下
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using SkyApm.Agent.AspNetCore;
using SkyApm.AspNetCore.Diagnostics;

[assembly: HostingStartup(typeof(SkyApmHostingStartup))]

namespace SkyApm.Agent.AspNetCore
{
 internal class SkyApmHostingStartup : IHostingStartup
 {
 public void Configure(IWebHostBuilder builder)
 {
  builder.ConfigureServices(services => services.AddSkyAPM(ext => ext.AddAspNetCoreHosting()));
 }
 }
}

通过这个我们可以看出确实如此,当然也是等同于我们通过UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "SkyApm.Agent.AspNetCore")去配置,我们甚至可使用如下的方式去使用SkyAPM-dotnet

public void ConfigureServices(IServiceCollection services)
{
 services.AddSkyAPM(ext => ext.AddAspNetCoreHosting())
}

这些写法其实是完全等价的,但是通过环境变量的方式配置HostingStartup启动程序集的方式无疑是最优雅的。所以我们在日常的学习开发中,最好还是通过这种方式去操作。

改造Zipkin使用

我们在之前的文章ASP.NET Core整合Zipkin链路跟踪中曾演示过基于诊断日志DiagnosticSource改进Zipkin的集成方式,通过本篇文章讲述的HostingStartup我们可以进步一改进Zipkin的集成方式,可以让它使用起来和SkyAPM-dotnet类似的方式,我们基于之前的示例中的ZipkinExtensions程序集中添加一个ZipkinHostingStartup类,用于承载集成Zipkin的操作,代码如下

using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;

namespace ZipkinExtensions
{
 public class ZipkinHostingStartup: IHostingStartup
 {

 public void Configure(IWebHostBuilder builder)
 {
  builder.ConfigureServices(services=> {
  services.AddZipkin();
  services.AddSingleton<ITraceDiagnosticListener, HttpDiagnosticListener>();
  });

  builder.Configure(app=> {
  IHostApplicationLifetime lifetime = app.ApplicationServices.GetService<IHostApplicationLifetime>();
  ILoggerFactory loggerFactory = app.ApplicationServices.GetService<ILoggerFactory>();
  IConfiguration configuration = app.ApplicationServices.GetService<IConfiguration>();
  string serivceName = configuration.GetValue<string>("ServiceName");
  string zipKinUrl = configuration.GetValue<string>("ASPNETCORE_ZIPKINADDRESS");

  app.UseZipkin(lifetime, loggerFactory, serivceName, zipKinUrl);
  });
 }
 }
}

然后在每个项目的launchSettings.json文件中添加如下所示的配置即可,这样的话就可以做到对现有业务代码无任何入侵。

 "environmentVariables": {
 "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "ZipkinExtensions",
 "ASPNETCORE_ZIPKINADDRESS": "http://localhost:9411/"
 }

总结

本文介绍了HostingStartup的基本概念,基础使用以及对其源码的分析和在SkyAPM-dotnet中的应用,最后我们改造了Zipkin的集成方式。HostingStartup在一些集成APM或者链路跟踪的类似场景还是非常实用的,或者如果我们有集成一些基础组件或者三方的组件,但是我们的代码中并不需要直接的使用这些组件中的类或者直接的代码关系,均可以使用HostingStartup的方式去集成,为我们实现对现有代码提供无入侵增强提供了强大的支持。关于HostingStartup我也是在看源码中无意发现的,后来发现微软ASP.NET Core官方文档
Use hosting startup assemblies in ASP.NET Core一文中有讲解,然后联想到自己使用过的SkyAPM-dotnet正是使用了HostingStartup+诊断日志DiagnosticSource的方式实现了对代码无入侵的方式进行监控和链路跟踪。于是决定深入研究一下,可谓收获满满,便写下这篇文章希望更多的人能够了解使用这个功能。

到此这篇关于ASP.NET Core使用HostingStartup增强启动操作的文章就介绍到这了,更多相关ASP.NET Core使用HostingStartup增强启动操作内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 深入探究ASP.NET Core Startup初始化问题

    前言 Startup类相信大家都比较熟悉,在我们使用ASP.NET Core开发过程中经常用到的类,我们通常使用它进行IOC服务注册,配置中间件信息等.虽然它不是必须的,但是将这些操作统一在Startup中做处理,会在实际开发中带来许多方便.当我们谈起Startup类的时候你有没有好奇过以下几点 为何我们自定义的Startup可以正常工作. 我们定义的Startup类中ConfigureServices和Configure只能叫这个名字才能被调用到吗? 在使用泛型主机(IHostBuilder)

  • VS初始化命令 ASP.NET常用技巧

    要使用此参数,请执行以下操作: 1. 关闭所有 Visual Studio 2005 实例. 2. 单击"开始",选择"运行...". 3. 键入"devenv.exe /resetuserdata". 此命令会运行几分钟时间,与此同时,Visual Studio 清除设置并将其自身重置到其最初的状态.此时,您可以打开"任务管理器"来检查 devenv.exe 进程是否仍在运行.在结束运行后,可以重新启动 Visual Stu

  • asp.net 初始化文本框的小例子

    复制代码 代码如下: private void ClearAllText(System.Web.UI.Control contrl)  {      int ctl_count=contrl.Controls.Count;   for (int i=0;i<ctl_count;i )    {    foreach(Control ctl in contrl.Controls[i].Controls)    {     if (ctl.HasControls())     {      Clea

  • ASP.NET Core使用HostingStartup增强启动操作方法详解

    概念 在ASP.NET Core中我们可以使用一种机制来增强启动时的操作,它就是HostingStartup.如何叫"增强"操作,相信了解过AOP概念的同学应该都非常的熟悉.我们常说AOP使用了关注点分离的方式,增强了对现有逻辑的操作.而我们今天要说的HostingStartup就是为了"增强"启动操作,这种"增强"的操作甚至可以对现有的程序可以做到无改动的操作.例如,外部程序集可通过HostingStartup实现为应用提供配置服务.注册服务或

  • ASP.NET Core WebSocket集群实现思路详解

    目录 前言 实现 nginx配置 一对一发送 群组发送 发送所有人 整合到一起 一对一处理 群组处理 全员消息处理 示例源码 总结 前言 提到WebSocket相信大家都听说过,它的初衷是为了解决客户端浏览器与服务端进行双向通信,是在单个TCP连接上进行全双工通讯的协议.在没有WebSocket之前只能通过浏览器到服务端的请求应答模式比如轮询,来实现服务端的变更响应到客户端,现在服务端也可以主动发送数据到客户端浏览器.WebSocket协议和Http协议平行,都属于TCP/IP四层模型中的第四层

  • ASP.NET Core中Cookie验证身份用法详解

    目录 添加配置 ASP.NETCore1.x ASP.NETCore2.x 创建身份认证Cookie ASP.NETCore1.x ASP.NETCore2.x Signingout(登出) ASP.NETCore1.x ASP.NETCore2.x 服务端变化反馈 ASP.NETCore1.x ASP.NETCore2.x Cookie设置选项 ASP.NETCore1.x ASP.NETCore2.x 持久Cookie ASP.NETCore1.x ASP.NETCore2.x 绝对到期时间

  • ASP.NET Core实现自定义WebApi模型验证详解

    Framework时代 在Framework时代,我们一般进行参数验证的时候,以下代码是非常常见的 [HttpPost] public async Task<JsonResult> SaveNewCustomerAsnyc(AddCustomerInput input) { if (!ModelState.IsValid) { return Json(Result.FromCode(ResultCode.InvalidParams)); } ..... } 或者高级一点是实现IActionFi

  • asp.net core中灵活的配置方式详解

    前言 asp.net core支持外部文件和命令行参数方式来配置系统运行所需要的配置信息,我们从下面两个常用场景来具体说下具体使用方法. 一.监听地址及端口配置 1,命令行方式 asp.net core系统通过命令行方式启动,使用的命令如下: dotnet run 上面的命令直接在源代码目录下执行,便可以编译程序并运行.那对于已经发布好的程序,就不能使用上面的指令了,应该使用下面的指令: dotnet 程序集文件名(程序集文件名就是程序发布后生成的dll文件) 上面两个指令都能够启动应用程序.程

  • Asp.Net Core中WebSocket绑定的方法详解

    说明 Websocket是html5后的产物,对于asp.net core中也得到了支持,Asp.Net Core中WebScoket的操作使用基本上和Asp.net中相同,不同的是,绑定监听. Asp.Net Core2.0默认已经支持WebSocket,不需要另外安装Nuget包. 通过对HttpContext中的WebSockets.AcceptWebSocketAsync方法,接受WebSocket请求:并返回WebScoket对象. 下面话不多说了,来一起看看详细的介绍吧. 一.示例1

  • ASP.NET Core MVC压缩样式、脚本详解

    前言 在.NET Core之前对于压缩样式文件和脚本我们可能需要借助第三方工具来进行压缩,但在ASP.NET MVC Core中则无需借助第三方工具来完成,本节我们来看看ASP.NET Core MVC为我们提供了哪些方便. 自动压缩样式和脚本 当我们在测试环境中肯定不需要压缩脚本的,如果一旦压缩脚本的话,若在控制台出现错误不利于我们调试,但是在生产环境中我们通过压缩脚本或者样式一来可以减少传输流量,二来可以加速页面加载时间,换句话说,此时我们需要测试环境和生产环境对应的原生版本和压缩版本,那么

  • ASP.NET CORE学习教程之自定义异常处理详解

    为什么异常处理选择中间件? 传统的ASP.NET可以采用异常过滤器的方式处理异常,在ASP.NET CORE中,是以多个中间件连接而成的管道形式处理请求的,不过常用的五大过滤器得以保留,同样可以采用异常过滤器处理异常,但是异常过滤器不能处理MVC中间件以外的异常,为了全局统一考虑,采用中间件处理异常更为合适 为什么选择自定义异常中间件? 先来看看ASP.NET CORE 内置的三个异常处理中间件 DeveloperExceptionPageMiddleware, ExceptionHandler

  • ASP.NET Core利用Jaeger实现分布式追踪详解

    前言 最近我们公司的部分.NET Core的项目接入了Jaeger,也算是稍微完善了一下.NET团队的技术栈. 至于为什么选择Jaeger而不是Skywalking,这个问题我只能回答,大佬们说了算. 前段时间也在CSharpCorner写过一篇类似的介绍 Exploring Distributed Tracing Using ASP.NET Core And Jaeger. 下面回到正题,我们先看一下Jaeger的简介 Jaeger的简单介绍 Jaeger是Uber开源的一个分布式追踪的工具,

  • 如何给ASP.NET Core Web发布包做减法详解

    1.引言 紧接上篇:ASP.NET Core Web App应用第三方Bootstrap模板.这一节我们来讲讲如何优化ASP.NET Core Web发布包繁重的问题. 在ASP.NET Core Web App中我们可以通过Bower或NPM来安装一些JS.CSS插件,来方便我们组织前端组件.但是这也给我带来了一个问题,那就是发布时需要把安装的Bower包或NPM包都要打包上传到服务器. 如果现在发布ASP.NET Core Web App,wwwroot下已包含到项目中的文件都会被发布.虽然

随机推荐