Установить и получить переменную сеанса в ASP. NET Boilerplate. NET Core v3 - PullRequest
5 голосов
/ 21 февраля 2020

Я пытаюсь установить значение переменной (выбранная опция из компонента select в angular) в каком-либо компоненте, чтобы использовать его в другом компоненте, и Я не хочу использовать window.sessionStorage () by javascript Я хочу использовать хранилище сеансов в ядре. NET, но проблема в том, что я могу установить значение переменной, но когда я хочу получить его, оно не возвращает значение.

Ниже приведен мой код обслуживания приложений

 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");

        }

А вот мой обновленный код класса 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
        }
    }
}

Обновление 3:


Теперь, после добавления некоторой конфигурации в класс Startup.cs, он работает Swagger, но я хочу получить значение angular перед ним, так как после него возвращается

System.InvalidOperationException: 'Обнуляемый объект должен иметь значение . '

angular установить код:

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

angular получить код:

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

Ответы [ 2 ]

0 голосов
/ 18 марта 2020

После просмотра вашего кода я вижу, что вы не инициализируете сервисы сеанса при запуске. Для инициализации сеанса вам необходимо предоставить сервис распределенного кэша и настроить сервисы сеанса. Вот только примеры конфигурационных битов, которые нужно добавить при запуске из официальной документации .

public void ConfigureServices(IServiceCollection services)
{
   services.AddDistributedMemoryCache();

   services.AddSession(options =>
   {
      options.IdleTimeout = TimeSpan.FromSeconds(10);
      options.Cookie.HttpOnly = true;
      options.Cookie.IsEssential = true;
   });
   // other needed initializations
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
   app.UseSession();
   // other configurations
}

. Для более подробных примеров проверьте Примеры Microsoft в GitHub .

Даже при этом это может не сработать, потому что вы используете SignalR. В документации говорится следующее:

Сеанс не поддерживается в приложениях SignalR, поскольку хаб SignalR может выполняться независимо от контекста HTTP. Например, это может произойти, когда длинный запрос опроса остается открытым концентратором после истечения срока действия контекста HTTP запроса.

0 голосов
/ 17 марта 2020

Вместо этого используйте SignalR

Вместо сеанса httpcontext вы можете использовать SignalR для сохранения состояния соединения:

Microsoft говорит это по этому вопросу. :

SignalR и состояние сеанса Приложения SignalR не должны использовать состояние сеанса для хранения информации. Приложения SignalR можно хранить для каждого состояния соединения в Context.Items в концентраторе.

Как это сделать, описано здесь: Документы SignalR

В основном, что вы do это создать концентратор, который предоставляет методы publi c для вашего внешнего интерфейса для вызова и добавления элементов в контекст. Концентратор может выглядеть примерно так:

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;
        }
    }

Возможно, вам потребуется добавить еще несколько проверок, чтобы убедиться, что вы устанавливаете и получаете правильные типы значений и т. Д. Приведенный выше пример очень прост c, но он должен выполнить работу.

При запуске вам необходимо добавить следующее:

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

Это минимум, чтобы заставить его работать, упомянутый Документация от Microsoft идет более подробно. Вы также можете проверить этот образец Microsoft для получения дополнительной информации о том, как настроить концентратор в вашем коде.

Оригинальный ответ

Вам необходимо добавить HttpContextAccessor в ваш запуск, как описано в документации :

Для других каркасов и пользовательских компонентов, которые требуется доступ к HttpContext, рекомендуемый подход заключается в регистрации зависимости с помощью встроенного контейнера внедрения зависимостей. Контейнер внедрения зависимостей предоставляет IHttpContextAccessor любым классам, которые объявляют его как зависимость в своих конструкторах:

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

} 
...