System.InvalidOperationException: 'The response headers cannot be modified because the response has



我正在使用Blazor服务器端,并希望设置Cookie,因为我正在使用HttpContext的SignInAsync函数,但给了我这个错误"无法修改响应标头,因为响应已启动";。

当涉及到以下行时,错误会闪烁

await httpContextAccessor.HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, 
new ClaimsPrincipal(claimsIdentity), 
authProperties);

我已经尝试了所有这些,但仍然面临错误

我的Startup.cs页面


using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using power_SLIC.Data;
using System.Net.Http;
using power_SLIC.Services;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection.Extensions;

namespace power_SLIC
{
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.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
// services.AddProtectedBrowserStorage();
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,
options => {
options.LoginPath = "/";
});
//.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, act => {
//    act.LoginPath = "/";
//    act.AccessDeniedPath = "/";
//    act.SlidingExpiration = true;
//}

// services.AddHttpClient();
services.AddSingleton<HttpClient>();
//  services.AddScoped<AuthenticationStateProvider, TokenAuthenticationServices>();
//services.AddScoped<ILoginservices, TokenAuthenticationServices>();
/// services.AddSingleton<HttpClient>();
services.AddAuthorization(option =>
{
option.AddPolicy("Employee", policy => policy.RequireClaim("IsUserEmployee", "true"));
});
}

// 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();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();



app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}
}

我的剃刀页是这样的Loginscreen.razor

@layout LoginLayout
@page "/"
@using System.Threading.Tasks
@using Microsoft.AspNetCore.Authentication
@using Microsoft.AspNetCore.Authentication.Cookies
@using Microsoft.AspNetCore.Http
@using Microsoft.AspNetCore.Mvc
@using Newtonsoft.Json
@using System.Text
@using Newtonsoft.Json.Linq
@using Microsoft.AspNetCore.ProtectedBrowserStorage
@using System.Security.Claims
@using System.Web
@*@inject ProtectedSessionStorage ProtectedSessionStore*@
@inject IJSRuntime JsRuntime;
@inject NavigationManager NavigationManager
@inject HttpClient http
@inject IHttpContextAccessor httpContextAccessor

<div style="margin-left:39%;margin-right:17%"> 
<div class="card">
<h4 class="card-header">Login</h4>
<div class="card-body">
<EditForm Model="@model" >
@*<DataAnnotationsValidator />*@
<div class="form-group">
<label>Username</label>
<InputText @bind-Value="model.SSam_User" class="form-control" />
@*<ValidationMessage For="@(() => model.Username)" />*@
</div>
<div class="form-group">
<label>Password</label>
<InputText @bind-Value="model.SSam_Pwd" type="password" class="form-control" />
@*<ValidationMessage For="@(() => model.Password)" />*@
</div>
<button  class="btn btn-primary" @onclick = "AddItem" >

Login
</button>
@* <NavLink href="account/register" @onClick = "window.location.href = 'home'" class="btn btn-link">Register</NavLink>*@
</EditForm>
</div>
</div>
</div>

@code{
private bool isConnected = false;
private Model.LoginModel model = new Model.LoginModel();
class Values
{

public string result {get; set;}
}




class Result{
public List<Values>  result { get; set;}
};
public async void AddItem()
{
var addItem = new Model.LoginModel {SSam_User=model.SSam_User,SSam_Pwd=model.SSam_Pwd, UnitSname = "HFHO" };
string output = JsonConvert.SerializeObject(addItem);
var Stringcontent = new StringContent(output,Encoding.UTF8,"application/json");

var op = await http.PostAsync("https://localhost:44392/api/outputs/getpowerbi_token", Stringcontent);
var resultcontent = op.Content.ReadAsStringAsync().Result;

dynamic oit = JsonConvert.DeserializeObject<dynamic>(resultcontent);
var accesstoken = oit["result"]["Token_status"].Value;
var op1 = oit["result"]["login_response"][0]["status"].Value;
if(op1 == "success")
{
var reo = httpContextAccessor.HttpContext.Request.Headers;
var prerender = !httpContextAccessor.HttpContext.Response.HasStarted;  
if (!httpContextAccessor.HttpContext.Request.Headers.ContainsKey("Header"))
{
if (!httpContextAccessor.HttpContext.Response.HasStarted)
{
string result;
httpContextAccessor.HttpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
result = JsonConvert.SerializeObject(new { error = "Request doesn't contains header" });
httpContextAccessor.HttpContext.Response.ContentType = "application/json";
await httpContextAccessor.HttpContext.Response.WriteAsync(result);
}
else
{
await httpContextAccessor.HttpContext.Response.HttpContext.Response.WriteAsync(string.Empty);
}
var reo1 = httpContextAccessor.HttpContext.Response.HttpContext.Response;

AuthenticateResult.Fail("request doesn't contains header");
}

var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, model.SSam_User),
new Claim("Token", accesstoken),
new Claim(ClaimTypes.Role, "User"),
};

var claimsIdentity = new ClaimsIdentity(
claims, CookieAuthenticationDefaults.AuthenticationScheme);

var authProperties = new AuthenticationProperties
{
IsPersistent = true,
RedirectUri = "/",
ExpiresUtc = DateTime.UtcNow.AddSeconds(30)
};
var j1 = CookieAuthenticationDefaults.AuthenticationScheme;

await httpContextAccessor.HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, 
new ClaimsPrincipal(claimsIdentity), 
authProperties);
NavigationManager.NavigateTo("/powerbi",true);
}

}
}

问题是async void。这仅适用于异步事件处理程序,Blazor中未使用。这样的方法不能等待,这意味着调用者不会启动并等待它们完成。由于运行时不知道AddItem仍在运行,因此它开始向客户端发送响应。

没有结果的异步方法应该返回async Task,而不是async void:

public async Task AddItem()
{
...
}

相关内容

最新更新