收集.NET6中一些常用组件的配置

这篇具有很好参考价值的文章主要介绍了收集.NET6中一些常用组件的配置。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

介绍

.NET 6的CoreApp框架,用来学习.NET6的一些变动和新特性,使用EFCore,等一系列组件的运用;

软件架构

分为模型层,服务层,接口层来做测试使用

0.如何使用IConfiguration、Environment

直接在builder后的主机中使用。

builder.Configuration;
builder.Environment

1.如何使用Swagger

.NET 6 自带模板已经默认添加Swagger,直接使用即可。

builder.Services.AddSwaggerGen();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

2. 如何添加EFCore到.NET 6中

按照EFCore常规使用方法,申明表的Entity及Dbcontext后,在program.cs文件中添加

builder.Services.AddDbContext<Service.DataContext>(opt => {
    opt.UseSqlServer(builder.Configuration.GetConnectionString("Default"));
});

即可在其他地方注入使用 DataContext

使用Sqlite数据库,需要引用 Microsoft.EntityFrameworkCore.Sqlite,
并在添加服务时,改为

opt.UseSqlite(builder.Configuration.GetConnectionString("Default"));

包管理控制台数据库结构生成方法:
使用 add-migration 创建迁移
使用 update-database 更新数据结构

3.如何注入一个服务

builder.Services.AddScoped<UserIdentyService>();

4.如何定义全局的using引用

在根目录下新建一个 cs文件,比如Globalusing.cs,在里面添加你的全局引用,和常规引用不同的是,在using前面添加 global

global using Service;
global using Entity;
global using Entity.Dto;

5.如何使用Autofac

添加 Nuget 引用

Autofac.Extensions.DependencyInjection

program.cs文件添加autofac的使用和注入配置

builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
 {
     Assembly assembly = Assembly.Load("Service.dll");
     builder.RegisterAssemblyTypes(assembly)
            //.AsImplementedInterfaces()// 无接口的注入方式
            .InstancePerDependency();
 });

此时即可构造函数注入使用。

6.如何使用Log4Net

添加引用

Microsoft.Extensions.Logging.Log4Net.AspNetCore

新建配置文件 log4net.config;
添加service配置

//注入Log4Net
builder.Services.AddLogging(cfg =>
{
    //默认的配置文件路径是在根目录,且文件名为log4net.config
    //cfg.AddLog4Net();
    //如果文件路径或名称有变化,需要重新设置其路径或名称
    //比如在项目根目录下创建一个名为config的文件夹,将log4net.config文件移入其中,并改名为log4net.config
    //则需要使用下面的代码来进行配置
    cfg.AddLog4Net(new Log4NetProviderOptions()
    {
        Log4NetConfigFileName = "config/log4net.config",
        Watch = true
    });
});

即可在需要的地方定义使用

_logger = LogManager.GetLogger(typeof(UserController));

7.如何使用全局异常过滤器

首先新建 GlobalExceptionFilter 全局异常过滤器,继承于 ExceptionFilter ,用于接收处理抛出的异常

public class GlobalExceptionFilter : IExceptionFilter
{
    readonly IWebHostEnvironment hostEnvironment;
    readonly ILog logger;
    public GlobalExceptionFilter(IWebHostEnvironment _hostEnvironment)
    {
        this.hostEnvironment = _hostEnvironment;
        this.logger = LogManager.GetLogger(typeof(GlobalExceptionFilter));
    }
    public void OnException(ExceptionContext context)
    {
        if (!context.ExceptionHandled)//如果异常没有处理
        {
            var result = new ApiResult
            {
                Code = 500,
                IsSuccess = false,
                Message = "服务器发生未处理的异常"
            };

            if (hostEnvironment.IsDevelopment())
            {
                result.Message += "," + context.Exception.Message;
                result.Data = context.Exception.StackTrace;
            }

            logger.Error(result);

            context.Result = new JsonResult(result);
            context.ExceptionHandled = true;//异常已处理
        }
    }
}

然后在Service中添加全局异常过滤器

builder.Services.AddControllers(option =>
    {
        option.Filters.Add<GlobalExceptionFilter>();
    }
);

添加控制器方法完成测试

[HttpGet("exception")]
public ApiResult ExceptionAction()
{
    throw new NotImplementedException();
}

8.如何使用redis做缓存

使用 StackExchange.Redis 作为缓存组件(其他组件类似的使用方式)。nuget 安装 StackExchange.Redis.Extensions.Core
首先,先建立一个类 RedisClient ,用于管理redis的连接和操作,再建立一个 RedisClientFactory 类,用于创建 redis的连接;

public class RedisClient{...}
public class RedisClientFactory{...}

appsettings.json 中添加redis的配置

"RedisConfig": {
    "Redis_Default": {
      "Connection": "127.0.0.1:6379",
      "InstanceName": "Redis1:"
    },
    "Redis_6": {
      "Connection": "127.0.0.1:6379",
      "DefaultDatabase": 6,
      "InstanceName": "Redis2:"
    }
  }

service中添加 redis客户端的引用

//添加redis的使用
builder.Services.AddSingleton<RedisClient>(_=> RedisClientFactory.GetInstance(builder.Configuration));

一顿操作后,就可以在你想要使用redis的地方引用了

RedisClient redisClient
...
this.redisDb = redisClient.GetDatabase("Redis_Default");
redisDb.StringSet("clientId", "clientId", TimeSpan.FromSeconds(10));

要使用redis做分布式缓存,先引用 Microsoft.Extensions.Caching.StackExchangeRedis

//将Redis分布式缓存服务添加到服务中
builder.Services.AddStackExchangeRedisCache(options =>
    {
        //用于连接Redis的配置  Configuration.GetConnectionString("RedisConnectionString")读取配置信息的串
        options.Configuration = "Redis_6";// Configuration.GetConnectionString("RedisConnectionString");
        //Redis实例名RedisDistributedCache
        options.InstanceName = "RedisDistributedCache";
    });

引用自 "分布式 Redis 缓存"

9. 如何添加使用定时任务组件

此处使用 Hangfire 定时任务组件,轻便,可持久化,还有面板。
引用 Hangfire 后,即可新增定时任务。

//启用Hangfire服务.
builder.Services.AddHangfire(x => x.UseStorage(new MemoryStorage()));
builder.Services.AddHangfireServer();

...

//启用Hangfire面板
app.UseHangfireDashboard();
//开启一个定时任务
RecurringJob.AddOrUpdate("test",() => Console.WriteLine("Recurring!"), Cron.Minutely());

访问 https://localhost:7219/hangfire 即可看到任务面板

10. 如何使用业务锁锁住下单或者支付操作

首先,做这个事需要能先构建出一个锁出来,这个锁有个锁的标识key,可以根据这个key判定key对应的锁是否存在,
这样的话,在某个用户支付或者下单减库存啥的时候,就可以按照这个key先上锁,后面有用户走其他渠道进行同样的操作的时候,就可以根据是否上锁了,来判断操作能否继续。

比如一个支付订单的业务,可以在手机上操作,也可以在电脑上操作,这个时候就可以给支付接口上锁,只要一个支付过程存在着,并且没有超时,那就不能在其他渠道进行操作。
我们上面已经使用了redis,下面就用redis构建个锁来模拟这个操作,具体看代码:

/// <summary>
    /// 测试业务锁
    /// </summary>
    /// <returns></returns>
    [HttpGet("lockhandle")]
    public async Task<ApiResult> LockHandle(int userId)
    {
        var key = "user";
        var token = $"ID:{userId}";
        try
        {
            if (redisDb.LockTake(key, token, TimeSpan.FromSeconds(50)))
            {
                await Task.Delay(30 * 1000);
                return await Task.FromResult(ApiResult.Success($"ID:{userId} 获取到锁了,操作正常,connectId:{Request.HttpContext.Connection.Id}"));
            }
            else
            {
                return await Task.FromResult(ApiResult.Fail($"有正在操作的锁,connectId:{Request.HttpContext.Connection.Id}"));
            }
        }
        catch (Exception)
        {
            throw;
        }
        finally
        {
            redisDb.LockRelease(key, token);
        }
    }

11. 如何配置跨域

此处主要记录全局跨域,不包括指定api跨域。先增加一个配置 "Cors": "http:127.0.0.1:5001",配置可以跨域的url,也可以使用默认跨域配置。
host配置以下服务,按需使用:

builder.Services.AddCors(delegate (CorsOptions options)
{
    options.AddPolicy("CorsPolicy", delegate (CorsPolicyBuilder corsBuilder)
    {
        //指定url跨域
        corsBuilder.WithOrigins(builder.Configuration.GetValue<string>("Cors").Split(','));
        //默认跨域
        corsBuilder.SetIsOriginAllowed((string _) => true).AllowAnyMethod().AllowAnyHeader()
            .AllowCredentials();
    });
});

12. 如何使用NewtonsoftJson

.NET6 默认的系列化库是内置的 System.Text.Json,使用中如果有诸多不熟悉的地方,那肯定是想换回 NewtonsoftJson,需要nuget 引用 Microsoft.AspNetCore.Mvc.NewtonsoftJson 来配置使用,
常用配置包括日期格式、大小写规则、循环引用配置。。。等,下面是一个配置

builder.Services.AddControllers(option =>
    {
        option.Filters.Add<GlobalExceptionFilter>();
    }
).AddNewtonsoftJson(options =>
{
    options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); //序列化时key为驼峰样式
    options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Local;
    options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
    options.SerializerSettings.ReferenceLoopHandling =  ReferenceLoopHandling.Ignore;//忽略循环引用
});

13. 如何使用SignalR

首先添加一个 ChatHub 作为 交互中心处理器

public class ChatHub : Hub
    {
        public async Task SendMessage(string user, string message)
        {
            await Clients.All.SendAsync("ReceiveMessage", user, message);
        }
    }

在主机中使用服务

builder.Services.AddSignalR();
...
app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<ChatHub>("/chatHub");
});

14. 如何使用Dapper

Dapper是大家常用的一个数据库连接扩展组件,下面介绍下,如何使用常规扩展,来在.net Core中使用Dapper。
首先,建立一个DbComponent ,来获取由 .netCore 提供的 Configuration 配置文件,并用 DbProviderFactories 工厂,创建数据库连接,此类只管创建连接,又其他使用类进行销毁。

/// <summary>
/// 创建连接处理
/// </summary>
public class DbComponent
{
    /// 数据库连接配置
    private static ConnectionStringSettings connectionSetting;

    public static void InitDapper(ConnectionStringSettings connectionStringSettings)
    {
        connectionSetting = connectionStringSettings;
    }

    //通过工厂模式创建Connection连接 此连接已打开
    public static IDbConnection GetConnection()
    {
        get {
            var cnnection = DbProviderFactories.GetFactory(connectionSetting.ProviderName).CreateConnection();
            if (cnnection == null)
                throw new Exception("数据库链接获取失败!");
            cnnection.ConnectionString = connectionSetting.ConnectionString;
            cnnection.Open();
            return cnnection;
        }
    }
}

使用前,需要在program中初始化一下组件

/// <summary>
/// 初始化Dapper组件
/// </summary>
DbProviderFactories.RegisterFactory("Microsoft.Data.Sqlite", Microsoft.Data.Sqlite.SqliteFactory.Instance);
DbComponent.InitDapper(new System.Configuration.ConnectionStringSettings
{
    ConnectionString = builder.Configuration.GetConnectionString("Default"),
    ProviderName = "Microsoft.Data.Sqlite"
});

程序启动后,就可以在需要的地方使用

public class UserIdentyService
{
    public ApiResult DapperList()
    {
        using (var connect = DbComponent.Connection)
        {
            var users= connect.Query<User>("SELECT * FROM Users").ToList();
            return ApiResult.Success(users);
        }
    }    
}

15. 如何添加自定义配置文件

有时候我们不想把配置全部放在 appsettings.json ,我们想自己建立一个文件夹来存储其他配置文件,比如config/...json之类的,咋整呢,
我们新建个文件夹 config,下面建立一个配置文件app.json,里面存几个配置以便验证。

使用前添加如下代码即可

builder.Configuration.AddJsonFile("config/app.json");
Console.WriteLine(builder.Configuration.GetValue<string>("weixin"));

16. 如何简单上传文件

上传文件是每个api框架都会实现的功能,我们先实现一个简单的文件上传。
首先做个配置文件,存储上传的文件存储位置、大小及格式限制等的配置

public class UploadConfig
{
    /// <summary>
    /// 最大值
    /// </summary>
    public int MaxSize { get; set; } = 1024 * 1024 * 1024;
    /// <summary>
    /// 存储路径
    /// </summary>
    public string UploadDir { get; set; } = @"D://Upload";
    /// <summary>
    /// 站点名称
    /// </summary>
    public string WebSite { get; set; }
}

添加测试action,完成文件上传,并返回文件访问路径

/// <summary>
/// 上传文件测试
/// </summary>
/// <param name="files"></param>
/// <returns></returns>
[HttpPost("upload")]
public async Task<ApiResult> Upload([FromForm(Name ="file")] List<IFormFile> files)
{
    var config = configuration.GetSection("UploadConfig").Get<UploadConfig>();
    if (files.Count == 0)
    {
        return ApiResult.Fail("没有需要上传的文件");
    }
    var dir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, config.UploadDir);
    
    if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);

    //验证大小或者格式之类
    foreach (var file in files)
    {
        var fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName;
        var fileSize = file.Length;
        if (fileSize > config.MaxSize)
        {
            return ApiResult.Fail($"{fileName}文件过大");
        }
    }
    //存储文件
    var result = new List<string>();
    foreach (var file in files)
    {
        var fileName = file.FileName;
        using (var stream = System.IO.File.Create(Path.Combine(dir, fileName)))
        {
            await file.CopyToAsync(stream);
        }
        result.Add(string.Join('/',config.WebSite,"upload/view" fileName));
    }
    return ApiResult.Success(result);
}

上述文件访问路径需要配置静态目录来进行访问

//启动www静态目录
app.UseStaticFiles();
//启动上传文件目录
app.UseStaticFiles(new StaticFileOptions { 
    FileProvider =  new PhysicalFileProvider(builder.Configuration.GetValue<string>("UploadConfig:UploadDir")),
    RequestPath = "/upload/view"
});

至此,文件上传及访问已添加完成

17. 如何添加验证码

验证码是常用的一个api功能,需要完成2步,先生成验证码字符串值及存储,后需要输出验证码图片到前端,即验证码功能需要2个api,1.获取验证码,2.验证验证码。
先实现一个类,用于获取随机值及生成图片
为了方便部署到unix系统,使用 ImageSharp 相关类库

public class CaptchaHelper
{
   private const string Letters = "1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,J,K,L,M,N,P,Q,R,S,T,U,V,W,X,Y,Z";

   /// <summary>
   /// 生成验证码随机值
   /// </summary>
   /// <param name="codeLength"></param>
   /// <returns></returns>
   public Task<string> GenerateRandomCaptchaAsync(int codeLength = 4)
   {
       var array = Letters.Split(new[] { ',' });
       var random = new Random();
       var temp = -1;
       var captcheCode = string.Empty;
       for (int i = 0; i < codeLength; i++)
       {
           if (temp != -1)
               random = new Random(i * temp * unchecked((int)DateTime.Now.Ticks));

           var index = random.Next(array.Length);
           if (temp != -1 && temp == index)
               return GenerateRandomCaptchaAsync(codeLength);

           temp = index;
           captcheCode += array[index];
       }
       return Task.FromResult(captcheCode);
   }

   /// <summary>
   /// 生成验证码及图片
   /// </summary>
   /// <param name="captchaCode"></param>
   /// <param name="width"></param>
   /// <param name="height"></param>
   /// <returns></returns>
   public Task<(string code, MemoryStream ms)> GenerateCaptchaImageAsync(string captchaCode, int width = 0, int height = 30)
   {
       //验证码颜色集合
       Color[] colors = { Color.Black, Color.Red, Color.DarkBlue, Color.Green, Color.Orange, Color.Brown, Color.DarkCyan, Color.Purple };
       //验证码字体集合
       string[] fonts = { "Verdana", "Microsoft Sans Serif", "Comic Sans MS", "Arial" };
       var r = new Random();
       
       if(width == 0) { width = captchaCode.Length * 25; }
       //定义图像的大小,生成图像的实例
       using var image = new Image<Rgba32>(width, height);

       // 字体
       var font = SystemFonts.CreateFont(SystemFonts.Families.First().Name, 25, FontStyle.Bold);

       image.Mutate(ctx =>
       {
           // 白底背景
           ctx.Fill(Color.White);

           // 画验证码
           for (int i = 0; i < captchaCode.Length; i++)
           {
               ctx.DrawText(captchaCode[i].ToString()
                   , font
                   , colors[r.Next(colors.Length)]
                   , new PointF(20 * i + 10, r.Next(2, 12)));
           }

           // 画干扰线
           for (int i = 0; i < 10; i++)
           {
               var pen = new Pen(colors[r.Next(colors.Length)], 1);
               var p1 = new PointF(r.Next(width), r.Next(height));
               var p2 = new PointF(r.Next(width), r.Next(height));

               ctx.DrawLines(pen, p1, p2);
           }

           // 画噪点
           for (int i = 0; i < 80; i++)
           {
               var pen = new Pen(colors[r.Next(colors.Length)], 1);
               var p1 = new PointF(r.Next(width), r.Next(height));
               var p2 = new PointF(p1.X + 1f, p1.Y + 1f);

               ctx.DrawLines(pen, p1, p2);
           }
       });
       using var ms = new MemoryStream();

       // gif 格式
       image.SaveAsGif(ms);
       return Task.FromResult((captchaCode, ms));
   }
}

测试代码

/// <summary>
/// 测试验证码
/// </summary>
/// <returns></returns>
[HttpGet("captcha")]
public async Task<IActionResult> GetCaptcha()
{
   var captchaHelper = new CaptchaHelper();
   var captcha = await captchaHelper.GenerateCaptchaImageAsync();
   this.HttpContext.Session.SetString("captcha", captcha.code);
   return File(captcha.ms.ToArray(), "image/gif");
}

18. 如何发布到windows

发布到windows比较简单,一步步选择发布,只要注意是按照框架依赖还是独立发布就好了,框架依赖的意思是, 你的服务器已经安装好了个.NetCore的运行时,你就可以直接框架依赖来发布就好了,如果你的服务器没有安装运行时, 或者是需要兼容以前的老的运行时不能更新啥的,你就使用独立发布。

19. 如何发布到linux

发布到linux其实也比较简单,首先,需要有待发布的程序文件,和windows一样,做好框架依赖和独立发布的安装包,目标运行时记得选择linux.64 或者linux-arm,编译发布,获得程序文件。
服务器运行时,和windows一样,框架依赖需要安装下.NET Core的运行时,注意匹配版本号,运行时安装好之后,把程序通过xshell 或者 scp压缩包上传到linux服务器你想要的目录下面,完成程序文件部署,在运行时版本没问题的情况下,dotnet xxx.dll 即可启动站点,还有一些其他的配置可能需要注意,比如后台运行,比如开放防火墙端口之类的,照着整就可以了。文章来源地址https://www.toymoban.com/news/detail-466529.html

到了这里,关于收集.NET6中一些常用组件的配置的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • .net core .net6 读取数据库 读取配置文件 保姆级教程

    .net core .net6 读取数据库 读取配置文件 保姆级教程

    本文环境 Microsoft Visual Studio 2022 .Net6 SQLServer2019 在解决方案管理器右键添加相关的包,如下两个包 Microsoft.Data.SqlClient SQLServer SQLServer数据库 Microsoft.Extensions.Configuration.Json json配置文件 添加配置文件 appsettings.json,选始终复制 添加json配置文件内容如下 DefaultConnection 根据自己的

    2024年02月08日
    浏览(9)
  • .Net6 Web Core API 配置 Autofac 封装 --- 依赖注入

    .Net6 Web Core API 配置 Autofac 封装 --- 依赖注入

    目录 一、NuGet 包导入 二、Autofac 封装类 三、Autofac 使用 四、案例测试 下列封装 采取 程序集注入方法 , 单个依赖注入, 也适用, 可依赖注入的地方配置 Autofac Autofac.Extensions.DependencyInjection Autofac.Extras.DynamicProxy    

    2024年02月14日
    浏览(39)
  • 本仓库主要用来收集一些 Android 开发中常用的第三方 UI 库及其简单 Demo

    本仓库主要用来收集一些 Android 开发中常用的第三方 UI 库及其简单 Demo

    | 第三方库 | 介绍 | Demo | 使用说明 | | — | — | — | — | | CircleImageView | 显示圆形图片 | CircleImageViewDemo | Android UI Libs 之 CircleImageView.md | | android-gif-drawable | 显示 gif 图片 | android-gif-drawabledemo | Android UI Libs 之 android-gif-drawable.md | | AndroidSwipeLayout | 滑动布局,可以实现侧滑菜单与侧

    2024年04月15日
    浏览(13)
  • .NET 一些常用的类型转换扩展

    记录下在开发中经常用到的类型转换  

    2024年02月08日
    浏览(7)
  • 如何在.net6webapi中配置Jwt实现鉴权验证

    如何在.net6webapi中配置Jwt实现鉴权验证

    jwt是一种用于身份验证的开放标准,他可以在网络之间传递信息,jwt由三部分组成:头部,载荷,签名。头部包含了令牌的类型和加密算法,载荷包含了用户的信息,签名则是对头部和载荷的加密结果。 jwt鉴权验证是指在用户登录成功后,服务器生成一个jwt令牌并返回给客户

    2024年02月07日
    浏览(10)
  • Ubuntu20和22的 /etc/netplan/*.yaml 一些配置静态IP的文件收集

    Ubuntu20和22的 /etc/netplan/*.yaml 一些配置静态IP的文件收集

    Ubuntu22.04Desktop原始 /etc/netplan/01-network-manager-all.yaml Ubuntu22.04Server原始 /etc/netplan/00-installer-config.yaml 注释中的 subiquity 是服务安装程序的名称 开头的数字00或01等, 有优先级的作用 Ubuntu22, server版和desktop版使用netplan管理下层 不同 的网络工具 Server版用 netplan 配置 systemd-networkd Des

    2024年01月16日
    浏览(21)
  • 移动端开发常用的一些UI 组件库

    1、Vant 是一个 轻量、可靠的移动端组件库 ,于 2017 年开源。 目前 Vant 官方提供了 Vue 2 版本、Vue 3 版本和微信小程序版本,并由社区团队维护 React 版本和支付宝小程序版本。 2、VUX(读音 [v’ju:z],同 views)是基于WeUI和Vue(2.x)开发的移动端UI组件库,主要服务于微信页面。缺

    2024年02月13日
    浏览(9)
  • Elasticsearch学习-ES中的一些组件介绍

    Elasticsearch学习-ES中的一些组件介绍

    ES是什么 Elastic Search简称ES, 是一个高性能的全文检索框架。它提供存储、搜索、大数据准实时分析等。一般用于提供复杂搜索的服务。 ES是基于Lucene进行二次开发的一个框架,首先Lucene是一个类库,业务系统中想要使用它,你必须使用Java来作为开发语言并将其直接集成到你

    2024年02月06日
    浏览(9)
  • 介绍一个.Net远程日志组件

    介绍一个.Net远程日志组件

    对于软件开发的阶段和正式运行阶段,我们都需要查看日志来诊断出现的问题。不过,在查看日志时需要登录服务器,找到特定的日志文件,再查看其中的内容,这显然不是很方便。 为了解决这个问题,我们可以使用远程日志,让所有的程序产生的日志都可以通过一个 web 页

    2023年04月17日
    浏览(9)
  • 介绍.NET几种人脸识别组件

    人脸识别技术在现代社会中扮演着越来越重要的角色,比如人脸识别门禁、人脸识别支付、甚至人脸识别网站登录等。 最近有群友问.NET有没有人脸识别的组件,小编查阅相关资料介绍下面几种.NET人脸识别组件供大家参考。 1、Microsoft Azure Face API 简介:Microsoft Azure Face API是微

    2024年02月07日
    浏览(7)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包