gpt4 book ai didi

asp.net-core - 在 httpContextAccessor.HttpContext 上返回 null

转载 作者:行者123 更新时间:2023-12-03 21:21:34 28 4
gpt4 key购买 nike

我们覆盖 SaveChangesAsync() 以自动更新 DateCreated、CreatedBy、LastDateModified 和 LastModifiedBy。使用 CreatedBy 和 LastModifiedBt,我们需要 Identity 的 User Id。

在 ApplicationDbContext 的构造函数中,我们添加了如下内容:
_userName = httpContextAccessor.HttpContext.User.Identity.Name;
//_userID = userManager.GetUserId(httpContext.HttpContext.User);

.. 并始终在此 httpContextAccessor.HttpContext 中获取空值。有任何想法吗?我们在下面包含了来源。

环境:

.NET 核心 2.1

数据库服务器

ApplicationDBContext.cs:

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using AthlosifyWebArchery.Models;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Linq.Expressions;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity;

namespace AthlosifyWebArchery.Data
{
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string>
{
private readonly string _userID;
private readonly string _userName;


public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options,
IHttpContextAccessor httpContextAccessor
)
: base(options)
{
_userName = httpContextAccessor.HttpContext.User.Identity.Name;

//_userID = userManager.GetUserId(httpContext.HttpContext.User);

}

public DbSet<AthlosifyWebArchery.Models.TournamentBatchItem> TournamentBatchItem { get; set; }
public DbSet<AthlosifyWebArchery.Models.TournamentBatch> TournamentBatch { get; set; }

public virtual DbSet<AthlosifyWebArchery.Models.Host> Host { get; set; }

public DbSet<AthlosifyWebArchery.Models.HostApplicationUser> HostApplicationUser { get; set; }

protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);

foreach (var entityType in builder.Model.GetEntityTypes())
{
// 1. Add the IsDeleted property
entityType.GetOrAddProperty("IsDeleted", typeof(bool));

// 2. Create the query filter

var parameter = Expression.Parameter(entityType.ClrType);

// EF.Property<bool>(post, "IsDeleted")
var propertyMethodInfo = typeof(EF).GetMethod("Property").MakeGenericMethod(typeof(bool));
var isDeletedProperty = Expression.Call(propertyMethodInfo, parameter, Expression.Constant("IsDeleted"));

// EF.Property<bool>(post, "IsDeleted") == false
BinaryExpression compareExpression = Expression.MakeBinary(ExpressionType.Equal, isDeletedProperty, Expression.Constant(false));

// post => EF.Property<bool>(post, "IsDeleted") == false
var lambda = Expression.Lambda(compareExpression, parameter);

builder.Entity(entityType.ClrType).HasQueryFilter(lambda);
}


// Many to Many relationship

builder.Entity<HostApplicationUser>()
.HasKey(bc => new { bc.HostID, bc.Id });


builder.Entity<HostApplicationUser>()
.HasOne(bc => bc.Host)
.WithMany(b => b.HostApplicationUsers)
.HasForeignKey(bc => bc.HostID);

builder.Entity<HostApplicationUser>()
.HasOne(bc => bc.ApplicationUser)
.WithMany(c => c.HostApplicationUsers)
.HasForeignKey(bc => bc.Id);

}

public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
OnBeforeSaving();
return base.SaveChanges(acceptAllChangesOnSuccess);
}

public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default(CancellationToken))
{
OnBeforeSaving();
return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}

private void OnBeforeSaving()
{
// Added
var added = ChangeTracker.Entries().Where(v => v.State == EntityState.Added && typeof(IBaseEntity).IsAssignableFrom(v.Entity.GetType())).ToList();

added.ForEach(entry =>
{
((IBaseEntity)entry.Entity).DateCreated = DateTime.UtcNow;
((IBaseEntity)entry.Entity).CreatedBy = _userID;
((IBaseEntity)entry.Entity).LastDateModified = DateTime.UtcNow;
((IBaseEntity)entry.Entity).LastModifiedBy = _userID;
});

// Modified
var modified = ChangeTracker.Entries().Where(v => v.State == EntityState.Modified &&
typeof(IBaseEntity).IsAssignableFrom(v.Entity.GetType())).ToList();

modified.ForEach(entry =>
{
((IBaseEntity)entry.Entity).LastDateModified = DateTime.UtcNow;
((IBaseEntity)entry.Entity).LastModifiedBy = _userID;
});

// Deleted
//var deleted = ChangeTracker.Entries().Where(v => v.State == EntityState.Deleted &&
//typeof(IBaseEntity).IsAssignableFrom(v.Entity.GetType())).ToList();

var deleted = ChangeTracker.Entries().Where(v => v.State == EntityState.Deleted).ToList();

deleted.ForEach(entry =>
{
((IBaseEntity)entry.Entity).DateDeleted = DateTime.UtcNow;
((IBaseEntity)entry.Entity).DeletedBy = _userID;
});

foreach (var entry in ChangeTracker.Entries()
.Where(e => e.State == EntityState.Deleted &&
e.Metadata.GetProperties().Any(x => x.Name == "IsDeleted")))
{
switch (entry.State)
{
case EntityState.Added:
entry.CurrentValues["IsDeleted"] = false;
break;

case EntityState.Deleted:
entry.State = EntityState.Modified;
entry.CurrentValues["IsDeleted"] = true;
break;
}
}
}
}



}

启动.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using AthlosifyWebArchery.Data;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using AthlosifyWebArchery.Models;
using DinkToPdf.Contracts;
using DinkToPdf;

namespace AthlosifyWebArchery
{
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.
public void ConfigureServices(IServiceCollection services)
{
//services.AddHttpContextAccessor();

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddSingleton(typeof(IConverter), new SynchronizedConverter(new PdfTools()));

services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));

// Extended Application User from IdentityUser
// and ApplicationRole from IdentityRole

services.AddIdentity<ApplicationUser, ApplicationRole>(
options => options.Stores.MaxLengthForKeys = 128)
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultUI()
.AddDefaultTokenProviders();

services.AddMvc()
.AddRazorPagesOptions(options =>
{
options.Conventions.AuthorizeFolder("/Tournaments");
options.Conventions.AuthorizeFolder("/TournamentAtheletes");
options.Conventions.AuthorizeFolder("/TournamentBatches");
options.Conventions.AuthorizeFolder("/TournamentContingents");
options.Conventions.AuthorizeFolder("/Admin");
//options.Conventions.AuthorizeFolder("/Private");
//options.Conventions.AllowAnonymousToPage("/Private/PublicPage");
//options.Conventions.AllowAnonymousToFolder("/Private/PublicPages");
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ApplicationDbContext context,
RoleManager<ApplicationRole> roleManager,
UserManager<ApplicationUser> userManager)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();

app.UseAuthentication();

app.UseMvc();

//UserManagerInitialData.Initialize(context, userManager, roleManager).Wait();

}


}
}

最佳答案

HttpContext仅在请求期间有效。当 .NET Core 创建 ApplicationDbContext用于调用 Configure 的类没有有效的上下文。

您需要存储对 IHttpContextAccessor 的引用。在您的 DbContext构造函数,然后您可以使用该变量访问 HttpContext您的属性(property)OnBeforeSaving()方法。

例如:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string>
{
private readonly IHttpContextAccessor _httpContextAccessor;


public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options,
IHttpContextAccessor httpContextAccessor
)
: base(options)
{
_httpContextAccessor = httpContextAccessor;
}

....

}

然后,在您的 OnBeforeSaving() 方法中:
private void OnBeforeSaving()
{
var userName = _httpContextAccessor.HttpContext.User.Identity.Name;

...
}

想想 HttpContext作为电话。如果您在无人来电时拿起电话,则没有 context即它是空的。当有人打电话时,您就有了一个有效的 context .这与网络调用的原理相同。 Configure Startup 中的方法不是网络调用,因此没有 HttpContext .

从另一个网站:

HttpContext object will hold information about the current http request. In detail, HttpContext object will be constructed newly for every request given to an ASP.Net application and this object will hold current request specific informations like Request, Response, Server, Session, Cache, User and etc. For every request, a new HttpContext object will be created which the ASP.Net runtime will use during the request processing. A new HttpContext object will be created at the beginning of a request and destroyed when the request is completed.

关于asp.net-core - 在 httpContextAccessor.HttpContext 上返回 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53439742/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com