После создания базового c проекта Web API на основе. NET Core 3.0 framework все ответы API приходили в случае верблюда. Я установил SwashBuckle Swagger + встроенный JSON сериализатор из System.Text. Json, в частности, чтобы отображать перечисления в виде строк, все работало как раньше. Затем я решил переключиться на NSwag + NewtonSoft Json из-за некоторых ограничений встроенного сериализатора с динамическими c и объектами расширения. Теперь все ответы API отображаются в PascalCase, и я не могу изменить ни политику именования, ни даже создать собственный обработчик контрактов.
Пример
https://forums.asp.net/t/2138758.aspx?Configure+SerializerSettings+ContractResolver
Вопрос
Я подозреваю, что может быть, какой-то пакет переопределяет решатель контрактов за сценой Как убедиться, что служба API использует ТОЛЬКО настраиваемый обработчик контрактов, который я назначаю при запуске, и игнорирует все другие подобные настройки?
Пользовательский JSON распознаватель контрактов
public class CustomContractResolver : IContractResolver
{
private readonly IHttpContextAccessor _context;
private readonly IContractResolver _contract;
private readonly IContractResolver _camelCaseContract;
public CustomContractResolver(IHttpContextAccessor context)
{
_context = context;
_contract = new DefaultContractResolver();
_camelCaseContract = new CamelCasePropertyNamesContractResolver();
}
// When API endpoint is hit, this method is NOT triggered
public JsonContract ResolveContract(Type value)
{
return _camelCaseContract.ResolveContract(value);
}
}
Контроллер
[ApiController]
public class RecordsController : ControllerBase
{
[HttpGet]
[Route("services/records")]
[ProducesResponseType(typeof(ResponseModel<RecordEntity>), 200)]
public async Task<IActionResult> Records([FromQuery] QueryModel queryModel)
{
var response = new ResponseModel<RecordEntity>();
return Content(JsonConvert.SerializeObject(response), "application/json"); // NewtonSoft serializer
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services
.AddCors(o => o.AddDefaultPolicy(builder => builder
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod()));
services
.AddControllers(o => o.RespectBrowserAcceptHeader = true)
/*
.AddJsonOptions(o =>
{
o.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
o.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
o.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
})
*/
.AddNewtonsoftJson(o =>
{
o.UseCamelCasing(true);
o.SerializerSettings.Converters.Add(new StringEnumConverter());
//o.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver { NamingStrategy = new CamelCaseNamingStrategy() };
o.SerializerSettings.ContractResolver = new CustomContractResolver(new HttpContextAccessor());
});
services.AddOpenApiDocument(o => // NSwag
{
o.PostProcess = document =>
{
document.Info.Version = "v1";
document.Info.Title = "Demo API";
};
});
DataConnection.DefaultSettings = new ConnectionManager(DatabaseOptionManager.Instance); // LINQ to DB
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(o => o.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(o => o.MapControllers());
app.UseOpenApi(); // NSwag
app.UseSwaggerUi3(o => o.Path = "/v2/docs");
app.UseReDoc(o => o.Path = "/v1/docs");
}