Session api review changes
This commit is contained in:
parent
15d8905ecc
commit
dab08ba7e9
|
|
@ -1,6 +1,10 @@
|
|||
using System;
|
||||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.Framework.Caching.Redis;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Logging;
|
||||
|
||||
|
|
@ -15,16 +19,24 @@ namespace SessionSample
|
|||
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
// Adds a default in-memory implementation of IDistributedCache
|
||||
services.AddCaching();
|
||||
|
||||
// Uncomment the following line to use the Redis implementation of IDistributedCache.
|
||||
// This will override any previously registered IDistributedCache service.
|
||||
//services.AddTransient<IDistributedCache, RedisCache>();
|
||||
|
||||
services.AddSession();
|
||||
|
||||
services.ConfigureSession(o =>
|
||||
{
|
||||
o.IdleTimeout = TimeSpan.FromSeconds(30);
|
||||
});
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app)
|
||||
{
|
||||
app.UseSession(o => {
|
||||
o.IdleTimeout = TimeSpan.FromSeconds(30); });
|
||||
// app.UseInMemorySession();
|
||||
// app.UseDistributedSession(new RedisCache(new RedisCacheOptions() { Configuration = "localhost" }));
|
||||
app.UseSession();
|
||||
|
||||
app.Map("/session", subApp =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
"webroot": "wwwroot",
|
||||
"exclude": "wwwroot/**/*.*",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Http.Extensions": "1.0.0-*",
|
||||
"Microsoft.AspNet.Server.IIS": "1.0.0-*",
|
||||
"Microsoft.AspNet.Server.WebListener" : "1.0.0-*",
|
||||
"Microsoft.AspNet.Server.WebListener": "1.0.0-*",
|
||||
"Microsoft.AspNet.Session": "1.0.0-*",
|
||||
"Microsoft.Framework.Caching.Memory": "1.0.0-*",
|
||||
"Microsoft.Framework.Caching.Redis": "1.0.0-*",
|
||||
"Microsoft.Framework.Logging.Console": "1.0.0-*"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.AspNet.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
using Microsoft.Framework.Caching.Distributed;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
|
@ -56,7 +56,7 @@ namespace Microsoft.AspNet.Session
|
|||
return _store.TryGetValue(new EncodedKey(key), out value);
|
||||
}
|
||||
|
||||
public void Set(string key, ArraySegment<byte> value)
|
||||
public void Set(string key, [NotNull] byte[] value)
|
||||
{
|
||||
var encodedKey = new EncodedKey(key);
|
||||
if (encodedKey.KeyBytes.Length > KeyLengthLimit)
|
||||
|
|
@ -64,10 +64,6 @@ namespace Microsoft.AspNet.Session
|
|||
throw new ArgumentOutOfRangeException(nameof(key),
|
||||
string.Format("The key cannot be longer than '{0}' when encoded with UTF-8.", KeyLengthLimit));
|
||||
}
|
||||
if (value.Array == null)
|
||||
{
|
||||
throw new ArgumentException("The ArraySegment<byte>.Array cannot be null.", nameof(value));
|
||||
}
|
||||
|
||||
Load();
|
||||
if (!_tryEstablishSession())
|
||||
|
|
@ -75,8 +71,8 @@ namespace Microsoft.AspNet.Session
|
|||
throw new InvalidOperationException("The session cannot be established after the response has started.");
|
||||
}
|
||||
_isModified = true;
|
||||
byte[] copy = new byte[value.Count];
|
||||
Buffer.BlockCopy(value.Array, value.Offset, copy, 0, value.Count);
|
||||
byte[] copy = new byte[value.Length];
|
||||
Buffer.BlockCopy(src: value, srcOffset: 0, dst: copy, dstOffset: 0, count: value.Length);
|
||||
_store[encodedKey] = copy;
|
||||
}
|
||||
|
||||
|
|
@ -93,12 +89,21 @@ namespace Microsoft.AspNet.Session
|
|||
_store.Clear();
|
||||
}
|
||||
|
||||
// TODO: This should throw if called directly, but most other places it should fail silently (e.g. TryGetValue should just return null).
|
||||
public void Load()
|
||||
private void Load()
|
||||
{
|
||||
if (!_loaded)
|
||||
{
|
||||
var data = _cache.Get(_sessionId);
|
||||
LoadAsync().GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This should throw if called directly, but most other places it should fail silently
|
||||
// (e.g. TryGetValue should just return null).
|
||||
public async Task LoadAsync()
|
||||
{
|
||||
if (!_loaded)
|
||||
{
|
||||
var data = await _cache.GetAsync(_sessionId);
|
||||
if (data != null)
|
||||
{
|
||||
Deserialize(new MemoryStream(data));
|
||||
|
|
@ -111,11 +116,11 @@ namespace Microsoft.AspNet.Session
|
|||
}
|
||||
}
|
||||
|
||||
public void Commit()
|
||||
public async Task CommitAsync()
|
||||
{
|
||||
if (_isModified)
|
||||
{
|
||||
var data = _cache.Get(_sessionId);
|
||||
var data = await _cache.GetAsync(_sessionId);
|
||||
if (_logger.IsEnabled(LogLevel.Information) && data == null)
|
||||
{
|
||||
_logger.LogInformation("Session {0} started", _sessionId);
|
||||
|
|
@ -124,7 +129,7 @@ namespace Microsoft.AspNet.Session
|
|||
|
||||
var stream = new MemoryStream();
|
||||
Serialize(stream);
|
||||
_cache.Set(
|
||||
await _cache.SetAsync(
|
||||
_sessionId,
|
||||
stream.ToArray(),
|
||||
new DistributedCacheEntryOptions().SetSlidingExpiration(_idleTimeout));
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Session
|
||||
{
|
||||
public class SessionFactory : ISessionFactory
|
||||
{
|
||||
private readonly string _sessionKey;
|
||||
private readonly ISessionStore _store;
|
||||
private readonly TimeSpan _idleTimeout;
|
||||
private readonly Func<bool> _tryEstablishSession;
|
||||
private readonly bool _isNewSessionKey;
|
||||
|
||||
public SessionFactory([NotNull] string sessionKey, [NotNull] ISessionStore store, TimeSpan idleTimeout, [NotNull] Func<bool> tryEstablishSession, bool isNewSessionKey)
|
||||
{
|
||||
_sessionKey = sessionKey;
|
||||
_store = store;
|
||||
_idleTimeout = idleTimeout;
|
||||
_tryEstablishSession = tryEstablishSession;
|
||||
_isNewSessionKey = isNewSessionKey;
|
||||
}
|
||||
|
||||
public bool IsAvailable
|
||||
{
|
||||
get { return _store.IsAvailable; }
|
||||
}
|
||||
|
||||
public ISession Create()
|
||||
{
|
||||
return _store.Create(_sessionKey, _idleTimeout, _tryEstablishSession, _isNewSessionKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,8 +7,6 @@ namespace Microsoft.AspNet.Session
|
|||
{
|
||||
public class SessionFeature : ISessionFeature
|
||||
{
|
||||
public ISessionFactory Factory { get; set; }
|
||||
|
||||
public ISession Session { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -23,36 +23,19 @@ namespace Microsoft.AspNet.Session
|
|||
private readonly RequestDelegate _next;
|
||||
private readonly SessionOptions _options;
|
||||
private readonly ILogger _logger;
|
||||
private readonly ISessionStore _sessionStore;
|
||||
|
||||
public SessionMiddleware(
|
||||
[NotNull] RequestDelegate next,
|
||||
[NotNull] ILoggerFactory loggerFactory,
|
||||
[NotNull] IEnumerable<ISessionStore> sessionStore,
|
||||
[NotNull] IOptions<SessionOptions> options,
|
||||
[NotNull] ConfigureOptions<SessionOptions> configureOptions)
|
||||
[NotNull] ISessionStore sessionStore,
|
||||
[NotNull] IOptions<SessionOptions> options)
|
||||
{
|
||||
_next = next;
|
||||
_logger = loggerFactory.CreateLogger<SessionMiddleware>();
|
||||
if (configureOptions != null)
|
||||
{
|
||||
_options = options.GetNamedOptions(configureOptions.Name);
|
||||
configureOptions.Configure(_options);
|
||||
}
|
||||
else
|
||||
{
|
||||
_options = options.Options;
|
||||
}
|
||||
|
||||
if (_options.Store == null)
|
||||
{
|
||||
_options.Store = sessionStore.FirstOrDefault();
|
||||
if (_options.Store == null)
|
||||
{
|
||||
throw new ArgumentException("ISessionStore must be specified.");
|
||||
}
|
||||
}
|
||||
|
||||
_options.Store.Connect();
|
||||
_options = options.Options;
|
||||
_sessionStore = sessionStore;
|
||||
_sessionStore.Connect();
|
||||
}
|
||||
|
||||
public async Task Invoke(HttpContext context)
|
||||
|
|
@ -72,8 +55,7 @@ namespace Microsoft.AspNet.Session
|
|||
}
|
||||
|
||||
var feature = new SessionFeature();
|
||||
feature.Factory = new SessionFactory(sessionKey, _options.Store, _options.IdleTimeout, tryEstablishSession, isNewSessionKey);
|
||||
feature.Session = feature.Factory.Create();
|
||||
feature.Session = _sessionStore.Create(sessionKey, _options.IdleTimeout, tryEstablishSession, isNewSessionKey);
|
||||
context.SetFeature<ISessionFeature>(feature);
|
||||
|
||||
try
|
||||
|
|
@ -88,7 +70,7 @@ namespace Microsoft.AspNet.Session
|
|||
{
|
||||
try
|
||||
{
|
||||
feature.Session.Commit();
|
||||
await feature.Session.CommitAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,45 +1,16 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNet.Session;
|
||||
using Microsoft.Framework.Caching.Distributed;
|
||||
using Microsoft.Framework.Caching.Memory;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.Logging;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Builder
|
||||
{
|
||||
public static class SessionMiddlewareExtensions
|
||||
{
|
||||
public static IApplicationBuilder UseInMemorySession([NotNull] this IApplicationBuilder app, IMemoryCache cache = null, Action<SessionOptions> configure = null)
|
||||
public static IApplicationBuilder UseSession([NotNull] this IApplicationBuilder app)
|
||||
{
|
||||
return app.UseDistributedSession(new LocalCache(cache ?? new MemoryCache(new MemoryCacheOptions())), configure);
|
||||
}
|
||||
|
||||
public static IApplicationBuilder UseDistributedSession([NotNull] this IApplicationBuilder app,
|
||||
IDistributedCache cache, Action<SessionOptions> configure = null)
|
||||
{
|
||||
var loggerFactory = app.ApplicationServices.GetRequiredService<ILoggerFactory>();
|
||||
return app.UseSession(options =>
|
||||
{
|
||||
options.Store = new DistributedSessionStore(cache, loggerFactory);
|
||||
if (configure != null)
|
||||
{
|
||||
configure(options);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static IApplicationBuilder UseSession([NotNull] this IApplicationBuilder app, Action<SessionOptions> configure = null)
|
||||
{
|
||||
return app.UseMiddleware<SessionMiddleware>(
|
||||
new ConfigureOptions<SessionOptions>(configure ?? (o => { }))
|
||||
{
|
||||
Name = string.Empty
|
||||
});
|
||||
return app.UseMiddleware<SessionMiddleware>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -34,10 +34,5 @@ namespace Microsoft.AspNet.Session
|
|||
/// resets the timeout. Note this only applies to the content of the session, not the cookie.
|
||||
/// </summary>
|
||||
public TimeSpan IdleTimeout { get; set; } = TimeSpan.FromMinutes(20);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the session storage manager. This overrides any session store passed into the middleware constructor.
|
||||
/// </summary>
|
||||
public ISessionStore Store { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -11,19 +11,16 @@ namespace Microsoft.Framework.DependencyInjection
|
|||
{
|
||||
public static IServiceCollection AddSession([NotNull] this IServiceCollection services)
|
||||
{
|
||||
return services.AddSession(configure: null);
|
||||
services.AddOptions();
|
||||
services.AddTransient<ISessionStore, DistributedSessionStore>();
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddSession([NotNull] this IServiceCollection services, Action<SessionOptions> configure)
|
||||
public static void ConfigureSession(
|
||||
[NotNull] this IServiceCollection services,
|
||||
[NotNull] Action<SessionOptions> configure)
|
||||
{
|
||||
services.AddTransient<ISessionStore, DistributedSessionStore>();
|
||||
|
||||
if (configure != null)
|
||||
{
|
||||
services.Configure(configure);
|
||||
}
|
||||
|
||||
return services;
|
||||
services.Configure(configure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,11 @@
|
|||
"version": "1.0.0-*",
|
||||
"description": "ASP.NET 5 session state middleware.",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Http.Extensions": "1.0.0-*",
|
||||
"Microsoft.Framework.Caching.Memory": "1.0.0-*",
|
||||
"Microsoft.AspNet.Http.Abstractions": "1.0.0-*",
|
||||
"Microsoft.Framework.Caching.Abstractions": "1.0.0-*",
|
||||
"Microsoft.Framework.Logging.Abstractions": "1.0.0-*",
|
||||
"Microsoft.Framework.NotNullAttribute.Sources": { "type": "build", "version": "1.0.0-*" }
|
||||
"Microsoft.Framework.NotNullAttribute.Sources": { "type": "build", "version": "1.0.0-*" },
|
||||
"Microsoft.Framework.OptionsModel": "1.0.0-*"
|
||||
},
|
||||
"compilationOptions": {
|
||||
"allowUnsafe": true
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Builder;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Session;
|
||||
using Microsoft.AspNet.TestHost;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.Logging;
|
||||
|
|
@ -24,14 +25,19 @@ namespace Microsoft.AspNet.Session
|
|||
{
|
||||
using (var server = TestServer.Create(app =>
|
||||
{
|
||||
app.UseInMemorySession();
|
||||
app.UseSession();
|
||||
|
||||
app.Run(context =>
|
||||
{
|
||||
Assert.Null(context.Session.GetString("NotFound"));
|
||||
return Task.FromResult(0);
|
||||
});
|
||||
},
|
||||
services => services.AddOptions()))
|
||||
services =>
|
||||
{
|
||||
services.AddCaching();
|
||||
services.AddSession();
|
||||
}))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync(string.Empty);
|
||||
|
|
@ -46,7 +52,7 @@ namespace Microsoft.AspNet.Session
|
|||
{
|
||||
using (var server = TestServer.Create(app =>
|
||||
{
|
||||
app.UseInMemorySession();
|
||||
app.UseSession();
|
||||
app.Run(context =>
|
||||
{
|
||||
Assert.Null(context.Session.GetString("Key"));
|
||||
|
|
@ -55,7 +61,11 @@ namespace Microsoft.AspNet.Session
|
|||
return Task.FromResult(0);
|
||||
});
|
||||
},
|
||||
services => services.AddOptions()))
|
||||
services =>
|
||||
{
|
||||
services.AddCaching();
|
||||
services.AddSession();
|
||||
}))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync(string.Empty);
|
||||
|
|
@ -72,7 +82,7 @@ namespace Microsoft.AspNet.Session
|
|||
{
|
||||
using (var server = TestServer.Create(app =>
|
||||
{
|
||||
app.UseInMemorySession();
|
||||
app.UseSession();
|
||||
app.Run(context =>
|
||||
{
|
||||
int? value = context.Session.GetInt32("Key");
|
||||
|
|
@ -86,7 +96,11 @@ namespace Microsoft.AspNet.Session
|
|||
return context.Response.WriteAsync(value.Value.ToString());
|
||||
});
|
||||
},
|
||||
services => services.AddOptions()))
|
||||
services =>
|
||||
{
|
||||
services.AddCaching();
|
||||
services.AddSession();
|
||||
}))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync("first");
|
||||
|
|
@ -107,7 +121,7 @@ namespace Microsoft.AspNet.Session
|
|||
{
|
||||
using (var server = TestServer.Create(app =>
|
||||
{
|
||||
app.UseInMemorySession();
|
||||
app.UseSession();
|
||||
app.Run(context =>
|
||||
{
|
||||
int? value = context.Session.GetInt32("Key");
|
||||
|
|
@ -131,7 +145,11 @@ namespace Microsoft.AspNet.Session
|
|||
return context.Response.WriteAsync(value.Value.ToString());
|
||||
});
|
||||
},
|
||||
services => services.AddOptions()))
|
||||
services =>
|
||||
{
|
||||
services.AddCaching();
|
||||
services.AddSession();
|
||||
}))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync("first");
|
||||
|
|
@ -151,7 +169,7 @@ namespace Microsoft.AspNet.Session
|
|||
{
|
||||
using (var server = TestServer.Create(app =>
|
||||
{
|
||||
app.UseInMemorySession();
|
||||
app.UseSession();
|
||||
app.Run(context =>
|
||||
{
|
||||
int? value = context.Session.GetInt32("Key");
|
||||
|
|
@ -175,7 +193,11 @@ namespace Microsoft.AspNet.Session
|
|||
return context.Response.WriteAsync(value.Value.ToString());
|
||||
});
|
||||
},
|
||||
services => services.AddOptions()))
|
||||
services =>
|
||||
{
|
||||
services.AddCaching();
|
||||
services.AddSession();
|
||||
}))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
var response = await client.GetAsync("first");
|
||||
|
|
@ -197,7 +219,7 @@ namespace Microsoft.AspNet.Session
|
|||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
using (var server = TestServer.Create(app =>
|
||||
{
|
||||
app.UseInMemorySession();
|
||||
app.UseSession();
|
||||
app.Run(context =>
|
||||
{
|
||||
context.Session.SetString("Key", "Value");
|
||||
|
|
@ -206,8 +228,9 @@ namespace Microsoft.AspNet.Session
|
|||
},
|
||||
services =>
|
||||
{
|
||||
services.AddOptions();
|
||||
services.AddInstance(typeof(ILoggerFactory), loggerFactory);
|
||||
services.AddCaching();
|
||||
services.AddSession();
|
||||
}))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
|
|
@ -226,9 +249,7 @@ namespace Microsoft.AspNet.Session
|
|||
var loggerFactory = new TestLoggerFactory(sink, enabled: true);
|
||||
using (var server = TestServer.Create(app =>
|
||||
{
|
||||
app.UseInMemorySession(configure: o => {
|
||||
o.IdleTimeout = TimeSpan.FromMilliseconds(30);
|
||||
});
|
||||
app.UseSession();
|
||||
app.Run(context =>
|
||||
{
|
||||
int? value = context.Session.GetInt32("Key");
|
||||
|
|
@ -248,8 +269,10 @@ namespace Microsoft.AspNet.Session
|
|||
},
|
||||
services =>
|
||||
{
|
||||
services.AddOptions();
|
||||
services.AddInstance(typeof(ILoggerFactory), loggerFactory);
|
||||
services.AddCaching();
|
||||
services.AddSession();
|
||||
services.ConfigureSession(o => o.IdleTimeout = TimeSpan.FromMilliseconds(30));
|
||||
}))
|
||||
{
|
||||
var client = server.CreateClient();
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Session": "1.0.0-*",
|
||||
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
||||
"Microsoft.Framework.Logging.Testing": "1.0.0-*",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
},
|
||||
"commands": {
|
||||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnx451": {}
|
||||
}
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Session": "1.0.0-*",
|
||||
"Microsoft.AspNet.TestHost": "1.0.0-*",
|
||||
"Microsoft.Framework.Caching.Memory": "1.0.0-*",
|
||||
"Microsoft.Framework.Logging.Testing": "1.0.0-*",
|
||||
"xunit.runner.aspnet": "2.0.0-aspnet-*"
|
||||
},
|
||||
"commands": {
|
||||
"test": "xunit.runner.aspnet"
|
||||
},
|
||||
"frameworks": {
|
||||
"dnx451": { }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue