Visual Studio 2019 Preview 16.2.0 Preview 2 .Net Core 3.0.0 Preview 6 Build 19307 Windows 10 Версия 1809 OS Build 17763.402
У меня возникла проблема, когда мой настраиваемый заголовок ответа не отображаетсяв ответе API, но он появляется в ответе MVC.
Я создал следующий класс для использования в качестве промежуточного программного обеспечения.
public class HostHeaderMiddleware
{
private readonly RequestDelegate _next;
public HostHeaderMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
// process context.Request
// since we are adding to the response headers, we can't do that once the response
// has been started. we need to hook the event.
context.Response.OnStarting(() =>
{
context.Response.Headers.Add("X-Host", Environment.MachineName);
return Task.CompletedTask;
});
// let the next object in the pipeline handle the context.
await _next(context);
// process context.Response
}
}
public static class HostHeaderMiddlewareExtensions
{
public static IApplicationBuilder UseHostHeaders(this IApplicationBuilder builder)
{
return builder.UseMiddleware<HostHeaderMiddleware>();
}
}
Для моего класса запуска у меня есть следующее:
using System;
using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace company.division.project.app
{
public static class Consts
{
/// <summary>
/// The pattern of a user id.
/// </summary>
public const string UserIdPattern = "[a-zA-Z0-9/-]{10,32}";
/// <summary>
/// The pattern of a list id.
/// </summary>
/// <remarks>A list id is a guid without all the formatting.</remarks>
public const string ListIdPattern = "[a-fA-F0-9]{32}";
}
public class MprStartup<TStartup>
{
protected bool UsingFluentValidations { get; }
protected bool RunAsService { get; }
protected Type ServiceType { get; }
public MprStartup(IConfiguration configuration)
{
Configuration = configuration;
UsingFluentValidations = Configuration.GetValue<bool>("UsingFluentValidations");
RunAsService = Configuration.GetValue<bool>("RunAsService");
if (RunAsService)
{
var aqn = Configuration["MprServiceType"];
if (!string.IsNullOrWhiteSpace(aqn))
ServiceType = Type.GetType(aqn);
}
}
protected IConfiguration Configuration { get; }
protected ILogger<TStartup> Logger { get; set; }
// This method gets called by the runtime. Use this method to add services to the container.
protected void ConfigureServices(IServiceCollection services)
{
services.Configure<MongoSettings>(Configuration.GetSection("MongoConnection"));
services.AddSingleton<MongoSettings>(sp => sp.GetRequiredService<IOptions<MongoSettings>>().Value);
services.Configure<RouteOptions>(options =>
{
options.ConstraintMap.Add("userid", typeof(UserIdRouteConstraint));
options.ConstraintMap.Add("listid", typeof(ListIdRouteConstraint));
});
if (RunAsService)
{
// this would normally be: services.TryAddEnumerable(ServiceDescriptor.Singleton<IHostedService, WorkerService>()
// since we are passing in a generic, the above call doesn't work, we need to duplicate the underlying call.
services.TryAddEnumerable(ServiceDescriptor.Singleton(typeof(IHostedService), ServiceType));
}
var mvcBuiilder = services.AddMvc(options => options.EnableEndpointRouting = false)
.ConfigureApiBehaviorOptions(options =>
{
options.InvalidModelStateResponseFactory = InvalidModelStateResponseFactoryExtension.BnInvalidModelStateResponse;
});
if (UsingFluentValidations)
mvcBuiilder.AddFluentValidation();
services.AddHttpContextAccessor();
services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
options.SerializerSettings.DefaultValueHandling = DefaultValueHandling.Ignore;
});
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1",
new OpenApiInfo()
{
Title = "Mobile Personalized Recommendations API",
Version = "v1"
});
var xmlFile = Path.ChangeExtension(typeof(Startup).Assembly.Location, ".xml");
options.IncludeXmlComments(xmlFile);
options.SchemaGeneratorOptions.DescribeAllEnumsAsStrings = true;
options.SwaggerGeneratorOptions.DescribeAllParametersInCamelCase = true;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
protected void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
Logger = app.ApplicationServices.GetRequiredService<ILogger<TStartup>>();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
beginConfigure?.Invoke(app, env);
app.ConfigureExceptionHandler();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseHostHeaders();
app.UseMvc();
var autoMapper = a.ApplicationServices.GetRequiredService<IMapper>();
autoMapper.ConfigurationProvider.AssertConfigurationIsValid();
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.DisplayOperationId();
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Do something API, v1");
});
}
}
}
Я не включил CORS явно.
Что я делаю неправильно, из-за чего в настраиваемом заголовке отображаются только ответы MVC, а не ответы API?
Спасибо