Я сталкиваюсь с ошибкой, которую не могу устранить самостоятельно.
У меня есть API отдыха в ASP. NET Core 2.1, использующий EntityFrameworkCore для связи с базой данных MySQL.
Все работает нормально, когда я запускаю свой API из VS2017 с IIS Express. Но когда я запускаю его с docker, он возвращает StatusCode cannot be set because the response has already started
Вот пример кода:
Во-первых, это обобщенный c метод для получения всех элементов для данный класс в базе данных.
/// <summary>
/// Return all the elements of the table T
/// </summary>
/// <param name="navigationProperties"></param>
/// <returns></returns>
public static IList<T> GetAll(params Expression<Func<T, object>>[] navigationProperties)
{
List<T> list;
using (var context = new SupGoDatabaseContext())
{
IQueryable<T> dbQuery = context.Set<T>();
//Apply eager loading
foreach (Expression<Func<T, object>> navigationProperty in navigationProperties)
dbQuery = dbQuery.Include<T, object>(navigationProperty);
list = dbQuery
.AsNoTracking()
.ToList<T>();
}
return list;
}
Во-вторых, это контроллер, который вызывает вышеуказанный метод
// GET api/category
[Authorize(Policy = "Administrator")]
[HttpGet]
public List<Category> Get()
{
List<Category> categories = new List<Category>();
categories = DatabaseService<Category>.GetAll().ToList();
return categories;
}
И, наконец, это класс Startup.cs, который, вероятно, является наиболее важно.
public class Startup
{
public IConfiguration Configuration { get; }
public IHostingEnvironment Environment { get; }
public Startup(IHostingEnvironment environment, IConfiguration configuration)
{
Configuration = configuration;
Environment = environment;
}
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddCors(options =>
{
options.AddPolicy("*",
builder =>
{
builder.WithOrigins("*").AllowAnyHeader().AllowAnyMethod();
});
});
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
o.RequireHttpsMetadata = false;
o.Audience = "supgo-api";
o.Authority = "http://keycloak:8080/auth/realms/SupGo";
o.IncludeErrorDetails = true;
o.TokenValidationParameters = new TokenValidationParameters()
{
ValidateAudience = false,
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidIssuer = "http://keycloak:8080/auth/realms/SupGo",
ValidateLifetime = true
};
o.Events = new JwtBearerEvents()
{
OnAuthenticationFailed = c =>
{
c.NoResult();
c.Response.StatusCode = 401;
c.Response.ContentType = "text/plain";
if (Environment.IsDevelopment())
{
return c.Response.WriteAsync(c.Exception.ToString());
}
return c.Response.WriteAsync("An error occured processing your authentication.");
}
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("Administrator", policy =>
{
policy.RequireClaim("user_roles", "supgo-api-admin");
policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
});
options.AddPolicy("User", policy =>
{
policy.RequireClaim("user_roles", "supgo-api-user");
policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
});
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseHsts();
}
app.UseAuthentication();
//app.UseHttpsRedirection();
app.UseMvc();
}
}
Спасибо за вашу помощь, любые советы будут рассмотрены. Пол.