在 ASP.NET Boilerplate .NET Core v3 中设置和获取会话变量

320*_*ser 6 session-variables asp.net-boilerplate asp.net-core aspnetboilerplate angular

我正在尝试在某个组件中设置变量值(从 angular 选择组件中选择的选项)以在另一个组件中使用它,我不想通过 javascript 使用 window.sessionStorage()我想在.NET core 但问题是我可以设置变量值,但是当我想获取它时,它没有返回值。

以下是我的应用程序服务代码

 public class MainProjectAppService : AsyncCrudAppService<MainProject, MainProjectDto,int,PagedAndSortedResultRequestDto,MainProjectDto>
    {



         private readonly IHttpContextAccessor _httpContextAccessor;


        public MainProjectAppService(IRepository<MainProject, int> repository, IHttpContextAccessor httpContextAccessor) : base(repository)
        {

            _httpContextAccessor = httpContextAccessor;
        }

        public void setVaraibleValurinSesseion(int ID)
        {
            _httpContextAccessor.HttpContext.Session.SetInt32("GID", ID);
        }

        public int getVaraibleValurFromSesseion()
        {
            return (int)_httpContextAccessor.HttpContext.Session.GetInt32("GID");

        }
Run Code Online (Sandbox Code Playgroud)

这是我更新的 Startup.cs 类代码:


using System;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Castle.Facilities.Logging;
using Abp.AspNetCore;
using Abp.AspNetCore.Mvc.Antiforgery;
using Abp.Castle.Logging.Log4Net;
using Abp.Extensions;
using TTT.Configuration;
using TTT.Identity;
using Abp.AspNetCore.SignalR.Hubs;
using Abp.Dependency;
using Abp.Json;
using Microsoft.OpenApi.Models;
using Newtonsoft.Json.Serialization;
using Microsoft.AspNetCore.Http;

namespace TTT.Web.Host.Startup
{
    public class Startup
    {
        private const string _defaultCorsPolicyName = "localhost";

        private readonly IConfigurationRoot _appConfiguration;

        public Startup(IWebHostEnvironment env)
        {
            _appConfiguration = env.GetAppConfiguration();
        }

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddDistributedMemoryCache(); //added this

            services.AddSession(options =>
            {
                options.IdleTimeout = TimeSpan.FromSeconds(10);
                options.Cookie.HttpOnly = true;
                options.Cookie.IsEssential = true;
            });//added this 
            //MVC
            services.AddControllersWithViews(
                options =>
                {
                    options.Filters.Add(new AbpAutoValidateAntiforgeryTokenAttribute());
                }
            ).AddNewtonsoftJson(options =>
            {
                options.SerializerSettings.ContractResolver = new AbpMvcContractResolver(IocManager.Instance)
                {
                    NamingStrategy = new CamelCaseNamingStrategy()
                };
            });

                 services.AddHttpContextAccessor(); // added this but no need as //I think

            services.AddMvc().AddSessionStateTempDataProvider();//added this
            services.AddSession();// added this 

            IdentityRegistrar.Register(services);
            AuthConfigurer.Configure(services, _appConfiguration);

            services.AddSignalR();

            // Configure CORS for angular2 UI
            services.AddCors(
                options => options.AddPolicy(
                    _defaultCorsPolicyName,
                    builder => builder
                        .WithOrigins(
                            // App:CorsOrigins in appsettings.json can contain more than one address separated by comma.
                            _appConfiguration["App:CorsOrigins"]
                                .Split(",", StringSplitOptions.RemoveEmptyEntries)
                                .Select(o => o.RemovePostFix("/"))
                                .ToArray()
                        )
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials()
                )
            );

            // Swagger - Enable this line and the related lines in Configure method to enable swagger UI
            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new OpenApiInfo() { Title = "TTT API", Version = "v1" });
                options.DocInclusionPredicate((docName, description) => true);

                // Define the BearerAuth scheme that's in use
                options.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme()
                {
                    Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey
                });
            });

            // Configure Abp and Dependency Injection
            return services.AddAbp<TTTWebHostModule>(
                // Configure Log4Net logging
                options => options.IocManager.IocContainer.AddFacility<LoggingFacility>(
                    f => f.UseAbpLog4Net().WithConfig("log4net.config")
                )
            );
        }

        public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
        {

            app.UseAbp(options => { options.UseAbpRequestLocalization = false; }); // Initializes ABP framework.

            app.UseCors(_defaultCorsPolicyName); // Enable CORS!

            app.UseStaticFiles();

            app.UseRouting();

            app.UseAuthentication();

            app.UseAbpRequestLocalization();
            //app.UseHttpContextItemsMiddleware();
             app.UseSession(); // <================= I've added this without it //will not work 
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapHub<AbpCommonHub>("/signalr");
                endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
                endpoints.MapControllerRoute("defaultWithArea", "{area}/{controller=Home}/{action=Index}/{id?}");
            });

            // Enable middleware to serve generated Swagger as a JSON endpoint
            app.UseSwagger();
            // Enable middleware to serve swagger-ui assets (HTML, JS, CSS etc.)
            app.UseSwaggerUI(options =>
            {
                options.SwaggerEndpoint(_appConfiguration["App:ServerRootAddress"].EnsureEndsWith('/') + "swagger/v1/swagger.json", "TTT API V1");
                options.IndexStream = () => Assembly.GetExecutingAssembly()
                    .GetManifestResourceStream("TTT.Web.Host.wwwroot.swagger.ui.index.html");
            }); // URL: /swagger
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

更新 3:


现在在 Startup.cs 类中添加了一些配置后,它可以通过 Swagger 工作,但我想通过 angular front 它来获取值,如下所示返回

System.InvalidOperationException: 'Nullable 对象必须有一个值。'

角度设置代码:

   this.http.post('http://localhost:21021/api/services/app/MainProject/setVaraibleValurinSesseion?ID=555',{ID:555}).subscribe(data=>{
  alert('saved');
});
Run Code Online (Sandbox Code Playgroud)

角度获取代码:

  this.http.get('http://localhost:21021/api/services/app/MainProject/getVaraibleValurFromSesseion').subscribe(data=>{
  console.log("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$");
      console.log(data);
      console.log(("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"));
});
Run Code Online (Sandbox Code Playgroud)

Aim*_*age 1

使用 SignalR 代替

您可以使用 SignalR 来存储连接状态,而不是使用 httpcontext 会话:

微软就此事表示:

SignalR 和会话状态 SignalR 应用程序不应使用会话状态来存储信息。SignalR 应用程序可以将每个连接状态存储在中心的 Context.Items 中。

此处描述了如何执行此操作: SignalR Docs

基本上,您要做的就是创建一个中心,为前端提供公共方法来调用项目并将项目添加到上下文中。集线器可能看起来像这样。

public class MyAwesomeHub : Hub
    {
        public void setVaraibleValurinSesseion(int ID)
        {
            Context.Items.Add("GID", ID);
        }

        public int getVaraibleValurFromSesseion(string key)
        {
            var value = Context.Items[key];
            return (int)value;
        }
    }
Run Code Online (Sandbox Code Playgroud)

您可能需要添加更多检查以确保设置并获取正确类型的值等,上面的示例非常基本,但它应该可以完成工作。

在启动时,您需要添加以下内容:

app.UseEndpoints(endpoints =>
{
    endpoints.MapHub<MyAwesomeHub>("/myAwesomeHub");
});

Run Code Online (Sandbox Code Playgroud)

这是让它工作的最低限度,微软提到的文档有更多细节。您还可以查看此 Microsoft 示例,了解有关如何在代码中设置集线器的更多详细信息。

原答案

您需要按照文档中所述将 HttpContextAccessor 添加到启动中:

对于需要访问 HttpContext 的其他框架和自定义组件,建议的方法是使用内置依赖项注入容器注册依赖项。依赖项注入容器向在其构造函数中将其声明为依赖项的任何类提供 IHttpContextAccessor:

public void ConfigureServices(IServiceCollection services) {
     services.AddHttpContextAccessor(); // add this one to what is already in your startup.cs

} 
Run Code Online (Sandbox Code Playgroud)