StatusCode не может быть установлен, потому что ответ уже начался - PullRequest
1 голос
/ 17 марта 2020

Я сталкиваюсь с ошибкой, которую не могу устранить самостоятельно.

У меня есть 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();
    }
}

Спасибо за вашу помощь, любые советы будут рассмотрены. Пол.

...