Session API review changes.
This commit is contained in:
parent
ed339a35d2
commit
6407a1672d
|
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
|||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using Microsoft.AspNet.Http.Authentication;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
|
||||
namespace Microsoft.AspNet.Http
|
||||
{
|
||||
|
|
@ -31,7 +32,7 @@ namespace Microsoft.AspNet.Http
|
|||
|
||||
public abstract CancellationToken RequestAborted { get; set; }
|
||||
|
||||
public abstract ISessionCollection Session { get; }
|
||||
public abstract ISession Session { get; set; }
|
||||
|
||||
public abstract void Abort();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +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 System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Http
|
||||
{
|
||||
public interface ISessionCollection : IEnumerable<KeyValuePair<string, byte[]>>
|
||||
{
|
||||
byte[] this[string key] { get; set; }
|
||||
|
||||
bool TryGetValue(string key, out byte[] value);
|
||||
|
||||
void Set(string key, ArraySegment<byte> value);
|
||||
|
||||
void Remove(string key);
|
||||
|
||||
void Clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
"version": "1.0.0-*",
|
||||
"description": "ASP.NET 5 HTTP object model. HttpContext and family.",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Http.Features": "1.0.0-*",
|
||||
"Microsoft.Framework.ActivatorUtilities.Sources": { "type": "build", "version": "1.0.0-*" },
|
||||
"Microsoft.Framework.NotNullAttribute.Sources": { "type": "build", "version": "1.0.0-*" },
|
||||
"Microsoft.Framework.WebEncoders.Core": "1.0.0-*"
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
// 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 System.Text;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
|
||||
namespace Microsoft.AspNet.Http
|
||||
{
|
||||
public static class SessionCollectionExtensions
|
||||
public static class SessionExtensions
|
||||
{
|
||||
public static void SetInt32(this ISessionCollection session, string key, int value)
|
||||
public static void SetInt32(this ISession session, string key, int value)
|
||||
{
|
||||
var bytes = new byte[]
|
||||
{
|
||||
|
|
@ -20,7 +20,7 @@ namespace Microsoft.AspNet.Http
|
|||
session.Set(key, bytes);
|
||||
}
|
||||
|
||||
public static int? GetInt32(this ISessionCollection session, string key)
|
||||
public static int? GetInt32(this ISession session, string key)
|
||||
{
|
||||
var data = session.Get(key);
|
||||
if (data == null || data.Length < 4)
|
||||
|
|
@ -30,12 +30,12 @@ namespace Microsoft.AspNet.Http
|
|||
return data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
||||
}
|
||||
|
||||
public static void SetString(this ISessionCollection session, string key, string value)
|
||||
public static void SetString(this ISession session, string key, string value)
|
||||
{
|
||||
session.Set(key, Encoding.UTF8.GetBytes(value));
|
||||
}
|
||||
|
||||
public static string GetString(this ISessionCollection session, string key)
|
||||
public static string GetString(this ISession session, string key)
|
||||
{
|
||||
var data = session.Get(key);
|
||||
if (data == null)
|
||||
|
|
@ -45,16 +45,11 @@ namespace Microsoft.AspNet.Http
|
|||
return Encoding.UTF8.GetString(data);
|
||||
}
|
||||
|
||||
public static byte[] Get(this ISessionCollection session, string key)
|
||||
public static byte[] Get(this ISession session, string key)
|
||||
{
|
||||
byte[] value = null;
|
||||
session.TryGetValue(key, out value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void Set(this ISessionCollection session, string key, byte[] value)
|
||||
{
|
||||
session.Set(key, new ArraySegment<byte>(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
"description": "ASP.NET 5 common extension methods for HTTP abstractions and IApplicationBuilder.",
|
||||
"dependencies": {
|
||||
"Microsoft.AspNet.Http.Abstractions": "1.0.0-*",
|
||||
"Microsoft.AspNet.Http.Features": "1.0.0-*",
|
||||
"Microsoft.Framework.NotNullAttribute.Sources": { "type": "build", "version": "1.0.0-*" },
|
||||
"Microsoft.Framework.WebEncoders.Core": "1.0.0-*",
|
||||
"Microsoft.Net.Http.Headers": "1.0.0-*"
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.AspNet.Http.Features
|
||||
{
|
||||
public interface ISession
|
||||
{
|
||||
void Load();
|
||||
Task LoadAsync();
|
||||
|
||||
void Commit();
|
||||
Task CommitAsync();
|
||||
|
||||
bool TryGetValue(string key, out byte[] value);
|
||||
|
||||
void Set(string key, ArraySegment<byte> value);
|
||||
void Set(string key, byte[] value);
|
||||
|
||||
void Remove(string key);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +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.
|
||||
|
||||
namespace Microsoft.AspNet.Http.Features
|
||||
{
|
||||
public interface ISessionFactory
|
||||
{
|
||||
bool IsAvailable { get; }
|
||||
|
||||
ISession Create();
|
||||
}
|
||||
}
|
||||
|
|
@ -3,11 +3,8 @@
|
|||
|
||||
namespace Microsoft.AspNet.Http.Features
|
||||
{
|
||||
// TODO: Is there any reason not to flatten the Factory down into the Feature?
|
||||
public interface ISessionFeature
|
||||
{
|
||||
ISessionFactory Factory { get; set; }
|
||||
|
||||
ISession Session { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.
|
||||
|
||||
namespace Microsoft.AspNet.Http.Features
|
||||
|
|
|
|||
|
|
@ -124,24 +124,27 @@ namespace Microsoft.AspNet.Http.Internal
|
|||
set { LifetimeFeature.RequestAborted = value; }
|
||||
}
|
||||
|
||||
public override ISessionCollection Session
|
||||
public override ISession Session
|
||||
{
|
||||
get
|
||||
{
|
||||
var feature = SessionFeature;
|
||||
if (feature == null)
|
||||
{
|
||||
throw new InvalidOperationException("Session has not been configured for this application or request.");
|
||||
throw new InvalidOperationException("Session has not been configured for this application " +
|
||||
"or request.");
|
||||
}
|
||||
if (feature.Session == null)
|
||||
return feature.Session;
|
||||
}
|
||||
set
|
||||
{
|
||||
var feature = SessionFeature;
|
||||
if (feature == null)
|
||||
{
|
||||
if (feature.Factory == null)
|
||||
{
|
||||
throw new InvalidOperationException("No ISessionFactory available to create the ISession.");
|
||||
}
|
||||
feature.Session = feature.Factory.Create();
|
||||
feature = new DefaultSessionFeature();
|
||||
_session.Update(_features, feature);
|
||||
}
|
||||
return new SessionCollection(feature.Session);
|
||||
feature.Session = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
// 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.
|
||||
|
||||
namespace Microsoft.AspNet.Http.Features.Internal
|
||||
{
|
||||
/// <summary>
|
||||
/// This type exists only for the purpose of unit testing where the user can directly set the
|
||||
/// <see cref="HttpContext.Session"/> property without the need for creating a <see cref="ISessionFeature"/>.
|
||||
/// </summary>
|
||||
public class DefaultSessionFeature : ISessionFeature
|
||||
{
|
||||
public ISession Session { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,74 +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 System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
|
||||
namespace Microsoft.AspNet.Http.Internal
|
||||
{
|
||||
public class SessionCollection : ISessionCollection
|
||||
{
|
||||
private readonly ISession _session;
|
||||
|
||||
public SessionCollection(ISession session)
|
||||
{
|
||||
_session = session;
|
||||
}
|
||||
|
||||
public byte[] this[string key]
|
||||
{
|
||||
get
|
||||
{
|
||||
byte[] value;
|
||||
TryGetValue(key, out value);
|
||||
return value;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
Remove(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
Set(key, new ArraySegment<byte>(value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, out byte[] value)
|
||||
{
|
||||
return _session.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
public void Set(string key, ArraySegment<byte> value)
|
||||
{
|
||||
_session.Set(key, value);
|
||||
}
|
||||
|
||||
public void Remove(string key)
|
||||
{
|
||||
_session.Remove(key);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_session.Clear();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<string, byte[]>> GetEnumerator()
|
||||
{
|
||||
foreach (var key in _session.Keys)
|
||||
{
|
||||
yield return new KeyValuePair<string, byte[]>(key, this[key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,6 @@
|
|||
"dependencies": {
|
||||
"Microsoft.AspNet.FeatureModel": "1.0.0-*",
|
||||
"Microsoft.AspNet.Http.Abstractions": "1.0.0-*",
|
||||
"Microsoft.AspNet.Http.Features": "1.0.0-*",
|
||||
"Microsoft.AspNet.WebUtilities": "1.0.0-*",
|
||||
"Microsoft.Framework.NotNullAttribute.Sources": { "type": "build", "version": "1.0.0-*" },
|
||||
"Microsoft.Net.Http.Headers": "1.0.0-*"
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
// 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 System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.FeatureModel;
|
||||
using Microsoft.AspNet.Http.Features;
|
||||
using Microsoft.AspNet.Http.Features.Internal;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -12,6 +15,69 @@ namespace Microsoft.AspNet.Http.Internal
|
|||
{
|
||||
public class DefaultHttpContextTests
|
||||
{
|
||||
[Fact]
|
||||
public void GetOnSessionProperty_ThrowsOnMissingSessionFeature()
|
||||
{
|
||||
// Arrange
|
||||
var context = new DefaultHttpContext();
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => context.Session);
|
||||
Assert.Equal("Session has not been configured for this application or request.", exception.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetOnSessionProperty_ReturnsAvailableSession()
|
||||
{
|
||||
// Arrange
|
||||
var context = new DefaultHttpContext();
|
||||
var session = new TestSession();
|
||||
session.Set("key1", null);
|
||||
session.Set("key2", null);
|
||||
var feature = new BlahSessionFeature();
|
||||
feature.Session = session;
|
||||
context.SetFeature<ISessionFeature>(feature);
|
||||
|
||||
// Act & Assert
|
||||
Assert.Same(session, context.Session);
|
||||
context.Session.Set("key3", null);
|
||||
Assert.Equal(3, context.Session.Keys.Count());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AllowsSettingSession_WithoutSettingUpSessionFeature_Upfront()
|
||||
{
|
||||
// Arrange
|
||||
var session = new TestSession();
|
||||
var context = new DefaultHttpContext();
|
||||
|
||||
// Act
|
||||
context.Session = session;
|
||||
|
||||
// Assert
|
||||
Assert.Same(session, context.Session);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SettingSession_OverridesAvailableSession()
|
||||
{
|
||||
// Arrange
|
||||
var context = new DefaultHttpContext();
|
||||
var session = new TestSession();
|
||||
session.Set("key1", null);
|
||||
session.Set("key2", null);
|
||||
var feature = new BlahSessionFeature();
|
||||
feature.Session = session;
|
||||
context.SetFeature<ISessionFeature>(feature);
|
||||
|
||||
// Act
|
||||
context.Session = new TestSession();
|
||||
|
||||
// Assert
|
||||
Assert.NotSame(session, context.Session);
|
||||
Assert.Empty(context.Session.Keys);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmptyUserIsNeverNull()
|
||||
{
|
||||
|
|
@ -73,5 +139,48 @@ namespace Microsoft.AspNet.Http.Internal
|
|||
var context = new DefaultHttpContext();
|
||||
return context;
|
||||
}
|
||||
|
||||
private class TestSession : ISession
|
||||
{
|
||||
private Dictionary<string, byte[]> _store
|
||||
= new Dictionary<string, byte[]>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public IEnumerable<string> Keys { get { return _store.Keys; } }
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_store.Clear();
|
||||
}
|
||||
|
||||
public Task CommitAsync()
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task LoadAsync()
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public void Remove(string key)
|
||||
{
|
||||
_store.Remove(key);
|
||||
}
|
||||
|
||||
public void Set(string key, byte[] value)
|
||||
{
|
||||
_store[key] = value;
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, out byte[] value)
|
||||
{
|
||||
return _store.TryGetValue(key, out value);
|
||||
}
|
||||
}
|
||||
|
||||
private class BlahSessionFeature : ISessionFeature
|
||||
{
|
||||
public ISession Session { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue