目标?
把以前的asp.net web api网站迁移到asp.net core3.1,过程很不平滑,磕磕绊绊。
1.HttpContent.Current 找不到了
core里面需要先在 Startup.cs 的 ConfigureServices 方法里加一句services.AddHttpContextAccessor(),再通过?HttpContextAccessor.HttpContext 获得这个HttpContent.Current,参考这篇文章。
2.调用不了 gRPC http 服务
gRPC 服务只提供了 http 地址,没有提供 https 地址,调用不到,根据微软官方文档,需要在Cofigure方法中加上:
// This switch must be set before creating the GrpcChannel/HttpClient. AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
3.Web Api返回对象属性默认 camel 小写了
要保持对象属性自身的大小写不变,而不是默认首字母小写,需要在ConfigureServices方法中加上:
services.AddControllers().AddJsonOptions(options =>{options.JsonSerializerOptions.PropertyNamingPolicy = null;});
4.Action返回 null 时不再是200而是204?
如果仍然要返回200+null,那需要在ConfigureServices方法中加上:
services.AddControllers().AddJsonOptions(options =>{options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>(); });
5.URL地址中的 null 不能给 int? 参数赋值
有一个Controller C的HttpGet 方法参数是 (int? a, int? b),url类似?***/Api/C?a=null&b=1,在asp.net mvc可以,在core里不行, url里面的null 会被解析为string,然后报错:'null' is not valid。
解决(将就)的办法是,把 int? 改成 string 类型,然后判断其值是否为"null"。
6.BasicAuthentication
BasicAuthentication 通过这篇文章实现了。
最后,Startup代码
代码中 AllowEmptyInputInBodyModelBinding 似乎没啥用;
WebHelper只是我定义的静态类,用来挂一个 HttpContextAccessor 方便别的地方用;
DateTimeConverter 用于改变DateTime的Json序列化格式,默认格式有3位毫秒值。
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.AddCors(options =>
{
options.AddPolicy("Open", builder => builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
});
services.AddControllers(x =>
{
x.AllowEmptyInputInBodyModelBinding = true;
x.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
}).AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
options.JsonSerializerOptions.Converters.Add(new DateTimeConverter());
});//Pascal 大小写.
services.AddHttpContextAccessor();
// configure basic authentication
services.AddAuthentication("BasicAuthentication")
.AddScheme<AuthenticationSchemeOptions, BasicAuthenticationHandler>("BasicAuthentication", null);
}
// 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();
}
WebHelper.HttpContextAccessor = app.ApplicationServices.GetRequiredService<IHttpContextAccessor>();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors("Open");
// This switch must be set before creating the GrpcChannel/HttpClient.
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
public class DateTimeConverter : JsonConverter<DateTime>
{
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return DateTime.Parse(reader.GetString());
}
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToUniversalTime().ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss"));
}
}
|