# 开发整理问题

# IConfiguration

1.配置文件值读取的顺序

/*
CLI > 环境变量 > appsettings.xx.json > appsettings.json
*/
//源代码解析
IHostingEnvironment hostingEnvironment = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile("appsettings." + hostingEnvironment.EnvironmentName + ".json", optional: true, reloadOnChange: true);
if (hostingEnvironment.IsDevelopment())
{
    Assembly assembly = Assembly.Load(new AssemblyName(hostingEnvironment.ApplicationName));
    if (assembly != null)
    {
        config.AddUserSecrets(assembly, optional: true);
    }
}

config.AddEnvironmentVariables();
if (args != null)
{
    config.AddCommandLine(args);
}

# DI 注入详解

参考

# netcore3.1 改 razorpage 需要重新编译解决

//1. 安装 Install-Package Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation
//2. 在service进行配置
public void ConfigureServices(IServiceCollection services)
{
    services.AddRazorPages()
      //这段话就行
        .AddRazorRuntimeCompilation();
}

# UnitTest 调试 WebAPI

参考

//1. nuget 安装 Microsoft.AspNetCore.TestHost
//2. UnitTest项目增加测试辅助类
public class ClientProvider:IDisposable
{
    private TestServer _server;
    public  HttpClient Client { get; private set; }
    public ClientProvider()
    {
        //UseStartup<Startup> 对应webapi的startup类就行了
        _server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
        Client = _server.CreateClient();
    }

    public void Dispose()
    {
        _server?.Dispose();
        Client?.Dispose();
    }
}
//3. 测试调用
public class EmployeeApiIntergrationTests
{
    [Fact]
    public async Task Test_GetAll()
    {
        using (var client = new ClientProvider().Client)
        {
            var response = await client.GetAsync("/api/employee");
            response.EnsureSuccessStatusCode();
            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
        }
    }

}

# WebAPI 全局的 exception 捕捉

stackoverflow

其他参考 1

其他参考 2

/*
1. 使用 `exceptionHandler` 去处理
2. 自己实现一个中间件去处理
*/

# AspnetCore3.1JSON 日期格式 UTC 异常处理

参考官网链接--JOSN.Text 和 Json.Net 的迁移
使用的库是JSON.Net,由于 3.1 没有设置 json 的格式操作的话,默认就是 UTC 的时间格式,所以导致数据呈现不对.
作为WEBAPI而言的话:JSON.Net是贯穿了整个数据输入和数据输出的规范,所以这个需要花时间去整理下。

//startup.cs里进行如下配置即可
 services.AddControllers()
        .AddNewtonsoftJson(options=> {
            //设置时间格式
            options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
            //设置时区
            options.SerializerSettings.DateTimeZoneHandling =  Newtonsoft.Json.DateTimeZoneHandling.Local;
        });

//还有一种处理方式使用JSON.Text进行操作,不使用JSON.Net
//startup.cs里进行如下配置即可
services.AddControllers().AddJsonOptions(options=> {
    options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
    options.JsonSerializerOptions.Converters.Add(new DateTimeConverter());
    options.JsonSerializerOptions.Converters.Add(new DateTimeNullableConvert());
});

public class DateTimeConverter : JsonConverter<DateTime>
{
    public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return DateTime.TryParse(reader.GetString(), out var dateTime) ? dateTime : default(DateTime);
    }

    public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
    }
}
public class DateTimeNullableConvert : JsonConverter<DateTime?>
{
    public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        return DateTime.TryParse(reader.GetString(), out var dateTime) ? dateTime : default(DateTime?);
    }

    public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options)
    {
        writer.WriteStringValue(value?.ToString("yyyy-MM-dd HH:mm:ss"));
    }
}

# 获取 WEBAPI 请求 Body 内容

AspnetCore3.1 之后,默认对应的读取 IO 流操作,服务器全部默认禁用同步读取操作:
Kestrel
HttpSys
IIS in-process
TestServer

实现增加对应的请求流支持
参考链接-github-issue
版本 2.2 到 3.1 的更改
IIS 配置同步读取 IO 流

//实现同步读取方案
//1.kestrel需要手动启用这个配置, Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            //kestrel服务器配置启用同步读取
            webBuilder.ConfigureKestrel((context, options) =>
            {
                options.AllowSynchronousIO = true;
            })
            ;
            webBuilder.UseStartup<Startup>();
        });
//2. IIS, startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IGreeting, Greeting>();
    //IIS启用同步读取流
    services.Configure<IISServerOptions>(options =>
    {
        options.AllowSynchronousIO = true;
    });
    services.AddControllers()
        //.AddXmlSerializerFormatters();
        ;
}

//实现异步读取方案

[HttpPost]
public async Task<IActionResult> TestQimenReqXML()
{
    var contents = string.Empty;
    using (var reader = new StreamReader(Request.Body, Encoding.UTF8))
    {
        contents = await reader.ReadToEndAsync();
    }
    var stu = topsdk_net_core.Util.XmlHelper.XmlDeserialize<Student>(contents);
    return Content(contents, "text/xml");
}

# WebApi 序列化

  • 支持请求和序列化 XML 参考链接

    //1. 引用包
    //Microsoft.AspNetCore.Mvc.Formatters.Xml
    
    //2. startup.cs配置
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
        .AddXmlSerializerFormatters();
    //3. 请求XML格式进行反序列化
    //响应
    [HttpPost]
    [Produces("application/xml")]
    public Student TestQimenRps()
    {
        var stu = new Student
        {
            Age = 20,
            Name = "Jack"
        };
        return stu;
    }
    
    //请求转为实体
    [HttpPost]
    [Consumes("application/xml")]
    public Student TestQimenReq([FromBody]Student student)
    {
        var stu = new Student
        {
            Age = 20,
            Name = "Jack"
        };
        return stu;
    }
    //JSON格式保持原样
    [HttpPost]
    public Student TestQimenReqJson([FromBody] Student student)
    {
        var stu = new Student
        {
            Age = 20,
            Name = "Jack"
        };
        return stu;
    }
    

# ApsNetCore 编码处理

根据 System.Text.Encoding.CodePages nuget 主页 的描述,这个包能为程序提供 Windows-1252, Shift-JIS, and GB2312 三种编码。

//1. 安装nuget包
//System.Text.Encoding.CodePages

//2.在使用的地方,优先执行注册CodePages的操作,当然可以考虑直接配置全局默认直接注册
System.Text.Encoding.RegisterProvider (System.Text.CodePagesEncodingProvider.Instance);

# Https 接口调用

出现基础连接已关闭的错误,参考链接
stackoverflow

//注意FrameWork的框架4.5或以上才支持
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
Last Updated: Monday, November 9, 2020 8:49 PM