在 httpContextAccessor.HttpContext 上返回 null

2024-02-24

我们重写 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 中获取 null。有任何想法吗?我们提供了以下来源。

环境:

.NET核心2.1

SQL服务器

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您的财产OnBeforeSaving() method.

例如:

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。这与网络调用的原理相同。这ConfigureStartup 中的方法不是网络调用,因此没有HttpContext.

来自另一个网站:

HttpContext 对象将保存有关当前 http 的信息 要求。具体来说,将重新构造 HttpContext 对象 向 ASP.Net 应用程序发出的每个请求以及该对象都会 保存当前请求的特定信息,例如请求、响应、 服务器、会话、缓存、用户等。对于每个请求,都会有一个新的 将创建 ASP.Net 运行时将使用的 HttpContext 对象 在请求处理期间。一个新的 HttpContext 对象将是 在请求开始时创建并在请求时销毁 完成了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 httpContextAccessor.HttpContext 上返回 null 的相关文章

随机推荐

  • 是否可以将热敏收据打印机连接到 Google Open print?

    我正在考虑将热敏收据打印机连接到 Google Open Print 这可能吗 如果是的话 您知道我可以购买哪些热敏打印机吗 出现上述情况的原因是我有一家外卖店 有网上商店 下订单后 订单将在 A4 喷墨打印机上打印 这浪费了我很多纸张和墨
  • 使用 php 函数格式化 JSON 值并在 div#id 中打印结果

    到目前为止 我已经得到以下内容 getJSON getinfo php id id parseInfo function parseInfo data div info fadeOut fast function div info html
  • ObservableCollection.CollectionChanged 未触发

    我有以下界面 当一个项目被添加到DataGrid the Total column将根据 价格 数量 更新 总计TextBox还将添加所有添加的行的总数 但是 当我更改行的数量时 Total column更新 但总计TextBox才不是 这
  • jQuery - 如何通过文本选择下拉列表项?

    如何通过文本而不是值选择下拉列表项 我想用 jQuery 通过文本选择一个下拉项 use contains link http api jquery com contains selector select option contains
  • 如何监控MySQL空间?

    我下载了使用 MySQL 的 Web 应用程序的 VM 映像 如何监控其空间消耗并知道何时必须添加额外空间 我有一些很大的疑问要分享 运行此命令以获取存储引擎的 MySQL 总数据和索引使用情况 SELECT IFNULL B engine
  • java正则表达式匹配

    能匹配下面2个字符串的正则表达式是什么 Hi
  • 如何处理 Rust 中的包装类型不变性?

    对包装类型的引用 例如 Rc
  • Cold observable 的 Scheduler.CurrentThread - 它将在哪个线程中运行?

    我是 RX 的新手 开始了解一些概念 我在网上找不到的概念 我在代码中使用计时器 Observable Timer TimeSpan FromSeconds 2 schedulerProvider CurrentThread where s
  • PHP 中子类的构造函数是否必须调用parent::__construct?

    是否必须从子类构造函数中调用父类的构造函数 为了解释 请考虑以下示例 class Parent function construct something is done here class Child extends Parent fun
  • 由于用户数据脚本,AWS 自动缩放启动未就绪的实例

    我有一个运行良好的自动缩放功能 带有一个启动配置 其中我定义了一个在新实例启动时执行的用户数据脚本 用户脚本更新基本代码并生成缓存 这需要几秒钟的时间 但是 一旦实例 创建 而不是 准备就绪 自动缩放就会将其添加到负载均衡器中 这是一个问题
  • 在现有 ASP.NET WebForms 站点中添加带有根路径的第二语言支持

    我继承了一个非常小的 ASP NET WebForms 项目 我的客户希望为其添加第二种语言 对于每个 somepage aspx 我想支持它的 第二语言路径 版本 例如 fr somepage aspx 我想使用正常的全球化 两种语言的
  • github.io 阻止了 ajax 请求

    我所有带有ajax请求的应用程序都返回错误 此请求已被阻止 内容必须通过 HTTPS 提供 例如 https zzharuk github io local weather widget https zzharuk github io lo
  • 在运行时合并两个程序集 - C#

    是否可以在运行时合并两个程序集 以便在迭代 ExportedTypes 时返回两个原始程序集中的所有类型 The why 我使用数据库迁移框架来更新我的数据库 它采用由特殊类组成的单个程序集 用于定义对数据库所做的修改 我有两个非常相似的数
  • 使用 git stash 时的 sh.exe.stackdump

    我是 Git 新手 对 stash 命令有疑问 当我编写 git stash git stash list git stash apply git drop 等命令时 我总是得到一个名为 sh exe stackdump 的文件 Excep
  • 带参数的 REST GET 动词

    我正在和我的队友一起阅读一些 REST 我们正在编写一个 RoR 应用程序 它将向世界其他地方公开它的一些功能 我在这个团队的任务是制作一个公开日记报告的资源 如果你打电话 http root com journalreports http
  • 如何确保curl 使用openssl,而不是nss?

    是否可以通过配置来保证parameter http curl haxx se docs manpage html that curl uses OpenSSL http www openssl org and not NSS http ww
  • 在 codeigniter 中启用 $_GET

    我一直在试图弄清楚如何在 CI 中启用 GET 看起来框架故意破坏了 GET 数组 并且启用它需要对核心类进行认真的修改 谁能说出这是为什么 以及如何克服它 请注意 我希望保持 URI 解析和路由的方式不变 只需让 GET 也可用即可 将以
  • Django - 使用 templatetags 渲染许多模板非常慢

    假设 我有一个带有照片库的页面 每个缩略图都有例如照片 国家 地区 作者等 我使用模板标签 加载指定的模板 渲染这些项目 小部件 由于 DRY 我在页面上的不同位置单独使用这些项目 小部件 所以会这样 而且速度非常慢 我使用 django
  • 如何使按钮可重复使用?

    我对编程世界还比较陌生 我对 HTML 和 CSS 有扎实的了解 最近又学习了 JavaScript 我正在开发一系列文本生成器作为学校项目 我的目标是能够在网站上单击一个按钮 并让计算机在每次单击该按钮时吐出随机文本 然而 虽然我对 HT
  • 在 httpContextAccessor.HttpContext 上返回 null

    我们重写 SaveChangesAsync 以自动更新 DateCreated CreatedBy LastDateModified 和 LastModifiedBy 对于CreatedBy和LastModifiedBt 我们需要Ident