#367 Add HttpContext.Features, move Get/SetFeature. Take 1.

This commit is contained in:
Chris R 2015-08-30 21:55:22 -07:00
parent 59b44a4c24
commit f475e53ad2
11 changed files with 69 additions and 34 deletions

View File

@ -12,6 +12,8 @@ namespace Microsoft.AspNet.Http
{ {
public abstract class HttpContext : IDisposable public abstract class HttpContext : IDisposable
{ {
public abstract IFeatureCollection Features { get; }
public abstract HttpRequest Request { get; } public abstract HttpRequest Request { get; }
public abstract HttpResponse Response { get; } public abstract HttpResponse Response { get; }

View File

@ -22,7 +22,7 @@ namespace Microsoft.AspNet.Http
/// <returns>True if sendfile feature exists in the response.</returns> /// <returns>True if sendfile feature exists in the response.</returns>
public static bool SupportsSendFile([NotNull] this HttpResponse response) public static bool SupportsSendFile([NotNull] this HttpResponse response)
{ {
return response.HttpContext.GetFeature<IHttpSendFileFeature>() != null; return response.HttpContext.Features.Get<IHttpSendFileFeature>() != null;
} }
/// <summary> /// <summary>
@ -47,7 +47,7 @@ namespace Microsoft.AspNet.Http
/// <returns></returns> /// <returns></returns>
public static Task SendFileAsync([NotNull] this HttpResponse response, [NotNull] string fileName, long offset, long? count, CancellationToken cancellationToken) public static Task SendFileAsync([NotNull] this HttpResponse response, [NotNull] string fileName, long offset, long? count, CancellationToken cancellationToken)
{ {
var sendFile = response.HttpContext.GetFeature<IHttpSendFileFeature>(); var sendFile = response.HttpContext.Features.Get<IHttpSendFileFeature>();
if (sendFile == null) if (sendFile == null)
{ {
throw new NotSupportedException(Resources.Exception_SendFileNotSupported); throw new NotSupportedException(Resources.Exception_SendFileNotSupported);

View File

@ -0,0 +1,30 @@
// 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 static class FeatureCollectionExtensions
{
/// <summary>
/// Retrieves the requested feature from the collection.
/// </summary>
/// <typeparam name="TFeature">The feature key.</typeparam>
/// <param name="features">The collection.</param>
/// <returns>The requested feature, or null if it is not present.</returns>
public static TFeature Get<TFeature>(this IFeatureCollection features)
{
return (TFeature)features[typeof(TFeature)];
}
/// <summary>
/// Sets the given feature in the collection.
/// </summary>
/// <typeparam name="TFeature">The feature key.</typeparam>
/// <param name="features">The collection.</param>
/// <param name="instance">The feature value.</param>
public static void Set<TFeature>(this IFeatureCollection features, TFeature instance)
{
features[typeof(TFeature)] = instance;
}
}
}

View File

@ -32,8 +32,8 @@ namespace Microsoft.AspNet.Http.Internal
public DefaultHttpContext() public DefaultHttpContext()
: this(new FeatureCollection()) : this(new FeatureCollection())
{ {
SetFeature<IHttpRequestFeature>(new HttpRequestFeature()); _features.Set<IHttpRequestFeature>(new HttpRequestFeature());
SetFeature<IHttpResponseFeature>(new HttpResponseFeature()); _features.Set<IHttpResponseFeature>(new HttpResponseFeature());
} }
public DefaultHttpContext(IFeatureCollection features) public DefaultHttpContext(IFeatureCollection features)
@ -76,6 +76,8 @@ namespace Microsoft.AspNet.Http.Internal
get { return _session.Fetch(_features); } get { return _session.Fetch(_features); }
} }
public override IFeatureCollection Features { get { return _features; } }
public override HttpRequest Request { get { return _request; } } public override HttpRequest Request { get { return _request; } }
public override HttpResponse Response { get { return _response; } } public override HttpResponse Response { get { return _response; } }

View File

@ -37,11 +37,11 @@ namespace Microsoft.AspNet.Owin
public OwinEnvironment(HttpContext context) public OwinEnvironment(HttpContext context)
{ {
if (context.GetFeature<IHttpRequestFeature>() == null) if (context.Features.Get<IHttpRequestFeature>() == null)
{ {
throw new ArgumentException("Missing required feature: " + nameof(IHttpRequestFeature) + ".", nameof(context)); throw new ArgumentException("Missing required feature: " + nameof(IHttpRequestFeature) + ".", nameof(context));
} }
if (context.GetFeature<IHttpResponseFeature>() == null) if (context.Features.Get<IHttpResponseFeature>() == null)
{ {
throw new ArgumentException("Missing required feature: " + nameof(IHttpResponseFeature) + ".", nameof(context)); throw new ArgumentException("Missing required feature: " + nameof(IHttpResponseFeature) + ".", nameof(context));
} }
@ -100,7 +100,7 @@ namespace Microsoft.AspNet.Owin
}; };
// owin.CallCancelled is required but the feature may not be present. // owin.CallCancelled is required but the feature may not be present.
if (context.GetFeature<IHttpRequestLifetimeFeature>() != null) if (context.Features.Get<IHttpRequestLifetimeFeature>() != null)
{ {
_entries[OwinConstants.CallCancelled] = new FeatureMap<IHttpRequestLifetimeFeature>(feature => feature.RequestAborted); _entries[OwinConstants.CallCancelled] = new FeatureMap<IHttpRequestLifetimeFeature>(feature => feature.RequestAborted);
} }
@ -334,7 +334,7 @@ namespace Microsoft.AspNet.Owin
internal bool TryGet(HttpContext context, out object value) internal bool TryGet(HttpContext context, out object value)
{ {
object featureInstance = context.GetFeature(FeatureInterface); object featureInstance = context.Features[FeatureInterface];
if (featureInstance == null) if (featureInstance == null)
{ {
value = null; value = null;
@ -350,7 +350,7 @@ namespace Microsoft.AspNet.Owin
internal void Set(HttpContext context, object value) internal void Set(HttpContext context, object value)
{ {
var feature = context.GetFeature(FeatureInterface); var feature = context.Features[FeatureInterface];
if (feature == null) if (feature == null)
{ {
if (FeatureFactory == null) if (FeatureFactory == null)
@ -360,7 +360,7 @@ namespace Microsoft.AspNet.Owin
else else
{ {
feature = FeatureFactory(); feature = FeatureFactory();
context.SetFeature(FeatureInterface, feature); context.Features[FeatureInterface] = feature;
} }
} }
Setter(feature, value); Setter(feature, value);

View File

@ -39,7 +39,7 @@ namespace Microsoft.AspNet.Builder
{ {
// Use the existing OWIN env if there is one. // Use the existing OWIN env if there is one.
IDictionary<string, object> env; IDictionary<string, object> env;
var owinEnvFeature = httpContext.GetFeature<IOwinEnvironmentFeature>(); var owinEnvFeature = httpContext.Features.Get<IOwinEnvironmentFeature>();
if (owinEnvFeature != null) if (owinEnvFeature != null)
{ {
env = owinEnvFeature.Environment; env = owinEnvFeature.Environment;
@ -87,7 +87,7 @@ namespace Microsoft.AspNet.Builder
{ {
var app = middleware(httpContext => var app = middleware(httpContext =>
{ {
return next(httpContext.GetFeature<IOwinEnvironmentFeature>().Environment); return next(httpContext.Features.Get<IOwinEnvironmentFeature>().Environment);
}); });
return env => return env =>
@ -98,7 +98,7 @@ namespace Microsoft.AspNet.Builder
if (env.TryGetValue(typeof(HttpContext).FullName, out obj)) if (env.TryGetValue(typeof(HttpContext).FullName, out obj))
{ {
context = (HttpContext)obj; context = (HttpContext)obj;
context.SetFeature<IOwinEnvironmentFeature>(new OwinEnvironmentFeature() { Environment = env }); context.Features.Set<IOwinEnvironmentFeature>(new OwinEnvironmentFeature() { Environment = env });
} }
else else
{ {

View File

@ -17,7 +17,7 @@ namespace Microsoft.AspNet.Http.Extensions.Tests
var context = new DefaultHttpContext(); var context = new DefaultHttpContext();
var response = context.Response; var response = context.Response;
Assert.False(response.SupportsSendFile()); Assert.False(response.SupportsSendFile());
context.SetFeature<IHttpSendFileFeature>(new FakeSendFileFeature()); context.Features.Set<IHttpSendFileFeature>(new FakeSendFileFeature());
Assert.True(response.SupportsSendFile()); Assert.True(response.SupportsSendFile());
} }
@ -34,7 +34,7 @@ namespace Microsoft.AspNet.Http.Extensions.Tests
var context = new DefaultHttpContext(); var context = new DefaultHttpContext();
var response = context.Response; var response = context.Response;
var fakeFeature = new FakeSendFileFeature(); var fakeFeature = new FakeSendFileFeature();
context.SetFeature<IHttpSendFileFeature>(fakeFeature); context.Features.Set<IHttpSendFileFeature>(fakeFeature);
await response.SendFileAsync("bob", 1, 3, CancellationToken.None); await response.SendFileAsync("bob", 1, 3, CancellationToken.None);

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Security.Claims; using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Http.Features;
using Microsoft.AspNet.Http.Features.Authentication; using Microsoft.AspNet.Http.Features.Authentication;
using Microsoft.AspNet.Http.Features.Authentication.Internal; using Microsoft.AspNet.Http.Features.Authentication.Internal;
using Microsoft.AspNet.Http.Internal; using Microsoft.AspNet.Http.Internal;
@ -50,7 +51,7 @@ namespace Microsoft.AspNet.Http.Authentication.Internal
{ {
var context = CreateContext(); var context = CreateContext();
var handler = new AuthHandler(); var handler = new AuthHandler();
context.SetFeature<IHttpAuthenticationFeature>(new HttpAuthenticationFeature() { Handler = handler }); context.Features.Set<IHttpAuthenticationFeature>(new HttpAuthenticationFeature() { Handler = handler });
var user = new ClaimsPrincipal(); var user = new ClaimsPrincipal();
await context.Authentication.SignInAsync("ignored", user); await context.Authentication.SignInAsync("ignored", user);
Assert.True(handler.SignedIn); Assert.True(handler.SignedIn);

View File

@ -35,7 +35,7 @@ namespace Microsoft.AspNet.Http.Internal
session.Set("key2", null); session.Set("key2", null);
var feature = new BlahSessionFeature(); var feature = new BlahSessionFeature();
feature.Session = session; feature.Session = session;
context.SetFeature<ISessionFeature>(feature); context.Features.Set<ISessionFeature>(feature);
// Act & Assert // Act & Assert
Assert.Same(session, context.Session); Assert.Same(session, context.Session);
@ -67,7 +67,7 @@ namespace Microsoft.AspNet.Http.Internal
session.Set("key2", null); session.Set("key2", null);
var feature = new BlahSessionFeature(); var feature = new BlahSessionFeature();
feature.Session = session; feature.Session = session;
context.SetFeature<ISessionFeature>(feature); context.Features.Set<ISessionFeature>(feature);
// Act // Act
context.Session = new TestSession(); context.Session = new TestSession();
@ -109,9 +109,9 @@ namespace Microsoft.AspNet.Http.Internal
public void GetItems_DefaultCollectionProvided() public void GetItems_DefaultCollectionProvided()
{ {
var context = new DefaultHttpContext(new FeatureCollection()); var context = new DefaultHttpContext(new FeatureCollection());
Assert.Null(context.GetFeature<IItemsFeature>()); Assert.Null(context.Features.Get<IItemsFeature>());
var items = context.Items; var items = context.Items;
Assert.NotNull(context.GetFeature<IItemsFeature>()); Assert.NotNull(context.Features.Get<IItemsFeature>());
Assert.NotNull(items); Assert.NotNull(items);
Assert.Same(items, context.Items); Assert.Same(items, context.Items);
var item = new object(); var item = new object();
@ -123,10 +123,10 @@ namespace Microsoft.AspNet.Http.Internal
public void SetItems_NewCollectionUsed() public void SetItems_NewCollectionUsed()
{ {
var context = new DefaultHttpContext(new FeatureCollection()); var context = new DefaultHttpContext(new FeatureCollection());
Assert.Null(context.GetFeature<IItemsFeature>()); Assert.Null(context.Features.Get<IItemsFeature>());
var items = new Dictionary<object, object>(); var items = new Dictionary<object, object>();
context.Items = items; context.Items = items;
Assert.NotNull(context.GetFeature<IItemsFeature>()); Assert.NotNull(context.Features.Get<IItemsFeature>());
Assert.Same(items, context.Items); Assert.Same(items, context.Items);
var item = new object(); var item = new object();
items["foo"] = item; items["foo"] = item;

View File

@ -136,7 +136,7 @@ namespace Microsoft.AspNet.Http.Internal
public void Query_GetAndSet() public void Query_GetAndSet()
{ {
var request = new DefaultHttpContext().Request; var request = new DefaultHttpContext().Request;
var requestFeature = request.HttpContext.GetFeature<IHttpRequestFeature>(); var requestFeature = request.HttpContext.Features.Get<IHttpRequestFeature>();
Assert.Equal(string.Empty, requestFeature.QueryString); Assert.Equal(string.Empty, requestFeature.QueryString);
Assert.Equal(QueryString.Empty, request.QueryString); Assert.Equal(QueryString.Empty, request.QueryString);
var query0 = request.Query; var query0 = request.Query;
@ -191,7 +191,7 @@ namespace Microsoft.AspNet.Http.Internal
private static HttpRequest CreateRequest(IDictionary<string, StringValues> headers) private static HttpRequest CreateRequest(IDictionary<string, StringValues> headers)
{ {
var context = new DefaultHttpContext(); var context = new DefaultHttpContext();
context.GetFeature<IHttpRequestFeature>().Headers = headers; context.Features.Get<IHttpRequestFeature>().Headers = headers;
return context.Request; return context.Request;
} }

View File

@ -23,7 +23,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
context.Request.Body = new MemoryStream(formContent); context.Request.Body = new MemoryStream(formContent);
// Not cached yet // Not cached yet
var formFeature = context.GetFeature<IFormFeature>(); var formFeature = context.Features.Get<IFormFeature>();
Assert.Null(formFeature); Assert.Null(formFeature);
// Act // Act
@ -34,7 +34,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
Assert.Equal("2", formCollection["baz"]); Assert.Equal("2", formCollection["baz"]);
// Cached // Cached
formFeature = context.GetFeature<IFormFeature>(); formFeature = context.Features.Get<IFormFeature>();
Assert.NotNull(formFeature); Assert.NotNull(formFeature);
Assert.NotNull(formFeature.Form); Assert.NotNull(formFeature.Form);
Assert.Same(formFeature.Form, formCollection); Assert.Same(formFeature.Form, formCollection);
@ -132,7 +132,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
context.Request.Body = new MemoryStream(formContent); context.Request.Body = new MemoryStream(formContent);
// Not cached yet // Not cached yet
var formFeature = context.GetFeature<IFormFeature>(); var formFeature = context.Features.Get<IFormFeature>();
Assert.Null(formFeature); Assert.Null(formFeature);
var formCollection = context.Request.Form; var formCollection = context.Request.Form;
@ -140,7 +140,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
Assert.NotNull(formCollection); Assert.NotNull(formCollection);
// Cached // Cached
formFeature = context.GetFeature<IFormFeature>(); formFeature = context.Features.Get<IFormFeature>();
Assert.NotNull(formFeature); Assert.NotNull(formFeature);
Assert.NotNull(formFeature.Form); Assert.NotNull(formFeature.Form);
Assert.Same(formCollection, formFeature.Form); Assert.Same(formCollection, formFeature.Form);
@ -161,7 +161,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
context.Request.Body = new MemoryStream(formContent); context.Request.Body = new MemoryStream(formContent);
// Not cached yet // Not cached yet
var formFeature = context.GetFeature<IFormFeature>(); var formFeature = context.Features.Get<IFormFeature>();
Assert.Null(formFeature); Assert.Null(formFeature);
var formCollection = context.Request.Form; var formCollection = context.Request.Form;
@ -169,7 +169,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
Assert.NotNull(formCollection); Assert.NotNull(formCollection);
// Cached // Cached
formFeature = context.GetFeature<IFormFeature>(); formFeature = context.Features.Get<IFormFeature>();
Assert.NotNull(formFeature); Assert.NotNull(formFeature);
Assert.NotNull(formFeature.Form); Assert.NotNull(formFeature.Form);
Assert.Same(formCollection, formFeature.Form); Assert.Same(formCollection, formFeature.Form);
@ -192,7 +192,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
context.Request.Body = new MemoryStream(formContent); context.Request.Body = new MemoryStream(formContent);
// Not cached yet // Not cached yet
var formFeature = context.GetFeature<IFormFeature>(); var formFeature = context.Features.Get<IFormFeature>();
Assert.Null(formFeature); Assert.Null(formFeature);
var formCollection = await context.Request.ReadFormAsync(); var formCollection = await context.Request.ReadFormAsync();
@ -200,7 +200,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
Assert.NotNull(formCollection); Assert.NotNull(formCollection);
// Cached // Cached
formFeature = context.GetFeature<IFormFeature>(); formFeature = context.Features.Get<IFormFeature>();
Assert.NotNull(formFeature); Assert.NotNull(formFeature);
Assert.NotNull(formFeature.Form); Assert.NotNull(formFeature.Form);
Assert.Same(formFeature.Form, formCollection); Assert.Same(formFeature.Form, formCollection);
@ -232,7 +232,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
context.Request.Body = new MemoryStream(formContent); context.Request.Body = new MemoryStream(formContent);
// Not cached yet // Not cached yet
var formFeature = context.GetFeature<IFormFeature>(); var formFeature = context.Features.Get<IFormFeature>();
Assert.Null(formFeature); Assert.Null(formFeature);
var formCollection = await context.Request.ReadFormAsync(); var formCollection = await context.Request.ReadFormAsync();
@ -240,7 +240,7 @@ namespace Microsoft.AspNet.Http.Features.Internal
Assert.NotNull(formCollection); Assert.NotNull(formCollection);
// Cached // Cached
formFeature = context.GetFeature<IFormFeature>(); formFeature = context.Features.Get<IFormFeature>();
Assert.NotNull(formFeature); Assert.NotNull(formFeature);
Assert.NotNull(formFeature.Form); Assert.NotNull(formFeature.Form);
Assert.Same(formFeature.Form, formCollection); Assert.Same(formFeature.Form, formCollection);