#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 IFeatureCollection Features { get; }
public abstract HttpRequest Request { 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>
public static bool SupportsSendFile([NotNull] this HttpResponse response)
{
return response.HttpContext.GetFeature<IHttpSendFileFeature>() != null;
return response.HttpContext.Features.Get<IHttpSendFileFeature>() != null;
}
/// <summary>
@ -47,7 +47,7 @@ namespace Microsoft.AspNet.Http
/// <returns></returns>
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)
{
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()
: this(new FeatureCollection())
{
SetFeature<IHttpRequestFeature>(new HttpRequestFeature());
SetFeature<IHttpResponseFeature>(new HttpResponseFeature());
_features.Set<IHttpRequestFeature>(new HttpRequestFeature());
_features.Set<IHttpResponseFeature>(new HttpResponseFeature());
}
public DefaultHttpContext(IFeatureCollection features)
@ -76,6 +76,8 @@ namespace Microsoft.AspNet.Http.Internal
get { return _session.Fetch(_features); }
}
public override IFeatureCollection Features { get { return _features; } }
public override HttpRequest Request { get { return _request; } }
public override HttpResponse Response { get { return _response; } }

View File

@ -37,11 +37,11 @@ namespace Microsoft.AspNet.Owin
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));
}
if (context.GetFeature<IHttpResponseFeature>() == null)
if (context.Features.Get<IHttpResponseFeature>() == null)
{
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.
if (context.GetFeature<IHttpRequestLifetimeFeature>() != null)
if (context.Features.Get<IHttpRequestLifetimeFeature>() != null)
{
_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)
{
object featureInstance = context.GetFeature(FeatureInterface);
object featureInstance = context.Features[FeatureInterface];
if (featureInstance == null)
{
value = null;
@ -350,7 +350,7 @@ namespace Microsoft.AspNet.Owin
internal void Set(HttpContext context, object value)
{
var feature = context.GetFeature(FeatureInterface);
var feature = context.Features[FeatureInterface];
if (feature == null)
{
if (FeatureFactory == null)
@ -360,7 +360,7 @@ namespace Microsoft.AspNet.Owin
else
{
feature = FeatureFactory();
context.SetFeature(FeatureInterface, feature);
context.Features[FeatureInterface] = feature;
}
}
Setter(feature, value);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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