.Net Core MVC 2.1中是否有等效的会话启动?

时间:2018-09-27 09:33:23

标签: asp.net-mvc .net-core asp.net-core-mvc

在MVC 5中,您可以在会话启动时在global.asx中为会话分配一个值。您是否可以在.Net Core MVC中做到这一点?我已经配置了会话,但是在中间件中,似乎每次请求都调用它。

2 个答案:

答案 0 :(得分:2)

我在一个实时项目中使用它。它可以正常工作。如果您想在应用程序停止时保留它。您应该使用DistributedCache。例如,我正在使用DistributedRedisCache。

添加此代码以启动;

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSession(options =>
        {
            options.IdleTimeout = TimeSpan.FromMinutes(60);
            options.Cookie.HttpOnly = true;
        });
// for redis distributed cache

//services.AddDistributedRedisCache(options =>
            //    {
                 //   options.InstanceName = $"{Configuration["DistributedRedisCacheInstance"]}";
                 //   options.Configuration = $"{Configuration["DistributedRedisCacheHost"]}";
              //  });
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, IHttpContextAccessor acc)
    {
        app.UseSession();

    }

并添加新的会话扩展;

using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System.Text;

namespace SampleApp
{
    public static class SessionExtensions
    {
        public static void SetObjectAsJson<T>(this ISession session, string key, T value)
        {
            session.Set(key, Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value)));
        }

        public static T GetObjectFromJson<T>(this ISession session, string key)
        {
            session.TryGetValue(key, out byte[] dataByte);
            string data = dataByte != null ? Encoding.UTF8.GetString(dataByte) : null;

            return data == null ? default(T) : JsonConvert.DeserializeObject<T>(data);
        }
    }
}

并使用get或set设置;

var sessionItem = httpContext.Session.GetObjectFromJson<string>("sessionItem");
//or


ContextProviderExtension.HttpContextAccessor.HttpContext.Session.SetObjectAsJson("sessionItem", sessionItem);

您需要此扩展程序;

using Microsoft.AspNetCore.Http;
using System;

namespace SampleApp
{
    public static class ContextProviderExtension
    {
        static IHttpContextAccessor httpContextAccessor = null;
        public static IHttpContextAccessor HttpContextAccessor
        {
            get { return httpContextAccessor; }
            set
            {
                if (httpContextAccessor != null)
                {
                    throw new Exception("");
                }
                httpContextAccessor = value;
            }
        }
    }
}

我想它会起作用。

 using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;


namespace SampleApp
{
    public class SessionMiddleware
    {
        private readonly RequestDelegate _next;

        public SessionMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext httpContext)
        {
            var sessionItem = httpContext.Session.GetObjectFromJson<string>("test");
            if (sessionItem == null)
                httpContext.Session.SetObjectAsJson<string>("test", httpContext.Session.Id);//httpContext.Session.Id or set a value
            await _next.Invoke(httpContext);
        }
    }

    public static class SessionMiddlewareExtensions
    {
        public static IApplicationBuilder UseSessionMiddleware(this IApplicationBuilder app)
        {
            return app.UseMiddleware<SessionMiddleware>();
        }
    }
}

并在app.UseSession()之后添加startup.cs Configure方法;

app.UseSessionMiddleware();

答案 1 :(得分:1)

nercan的解决方案可以使用,但是我认为我发现了一种需要较少代码并可能具有其他优点的解决方案。

首先,像这样包装DistributedSessionStore:

using System;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Session;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;

public interface IStartSession
{
    void StartSession(ISession session);
}

public class DistributedSessionStoreWithStart : ISessionStore
{
    DistributedSessionStore innerStore;
    IStartSession startSession;
    public DistributedSessionStoreWithStart(IDistributedCache cache, 
        ILoggerFactory loggerFactory, IStartSession startSession)
    {
        innerStore = new DistributedSessionStore(cache, loggerFactory);
        this.startSession = startSession;
    }

    public ISession Create(string sessionKey, TimeSpan idleTimeout, 
        TimeSpan ioTimeout, Func<bool> tryEstablishSession, 
        bool isNewSessionKey)
    {
        ISession session = innerStore.Create(sessionKey, idleTimeout, ioTimeout,
             tryEstablishSession, isNewSessionKey);
        if (isNewSessionKey)
        {
            startSession.StartSession(session);
        }
        return session;
    }
}

然后在Startup.cs中注册这个新类:

class InitSession : IStartSession
{
    public void StartSession(ISession session)
    {
        session.SetString("Hello", "World");
    }
}

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        ...
        services.AddSingleton<IStartSession, InitSession>();
        services.AddSingleton<ISessionStore, DistributedSessionStoreWithStart>();
        services.AddSession();
        ...
    }

完整代码在这里: https://github.com/SurferJeffAtGoogle/scratch/tree/master/StartSession/MVC