Adding GetFormAsync on HttpRequest to read form data

This commit is contained in:
Pranav K 2014-02-25 12:52:00 -08:00
parent fe15f4a849
commit 09cc1964e7
5 changed files with 139 additions and 0 deletions

View File

@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace Microsoft.AspNet.Abstractions
{
@ -58,6 +59,12 @@ namespace Microsoft.AspNet.Abstractions
/// <returns>The query value collection parsed from owin.RequestQueryString.</returns>
public abstract IReadableStringCollection Query { get; }
/// <summary>
/// Gets the query value collection form collection.
/// </summary>
/// <returns>The form collection parsed from the request body.</returns>
public abstract Task<IReadableStringCollection> GetFormAsync();
/// <summary>
/// Gets or set the owin.RequestProtocol.
/// </summary>

View File

@ -0,0 +1,42 @@
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.FeatureModel;
using Microsoft.AspNet.HttpFeature;
using Microsoft.AspNet.PipelineCore.Collections;
using Microsoft.AspNet.PipelineCore.Infrastructure;
namespace Microsoft.AspNet.PipelineCore
{
public class DefaultCanHasForm : ICanHasForm
{
private readonly IFeatureCollection _features;
private readonly FeatureReference<IHttpRequestInformation> _request = FeatureReference<IHttpRequestInformation>.Default;
private Stream _bodyStream;
private IReadableStringCollection _form;
public DefaultCanHasForm(IFeatureCollection features)
{
_features = features;
}
public async Task<IReadableStringCollection> GetFormAsync()
{
var body = _request.Fetch(_features).Body;
if (_bodyStream == null || _bodyStream != body)
{
_bodyStream = body;
using (var streamReader = new StreamReader(body, Encoding.UTF8,
detectEncodingFromByteOrderMarks: true,
bufferSize: 1024, leaveOpen: true))
{
string formQuery = await streamReader.ReadToEndAsync();
_form = new ReadableStringCollection(ParsingHelpers.GetQuery(formQuery));
}
}
return _form;
}
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.Abstractions;
using Microsoft.AspNet.FeatureModel;
using Microsoft.AspNet.HttpFeature;
@ -18,6 +19,7 @@ namespace Microsoft.AspNet.PipelineCore
private FeatureReference<IHttpConnection> _connection = FeatureReference<IHttpConnection>.Default;
private FeatureReference<IHttpTransportLayerSecurity> _transportLayerSecurity = FeatureReference<IHttpTransportLayerSecurity>.Default;
private FeatureReference<ICanHasQuery> _canHasQuery = FeatureReference<ICanHasQuery>.Default;
private FeatureReference<ICanHasForm> _canHasForm = FeatureReference<ICanHasForm>.Default;
private FeatureReference<ICanHasRequestCookies> _canHasCookies = FeatureReference<ICanHasRequestCookies>.Default;
public DefaultHttpRequest(DefaultHttpContext context, IFeatureCollection features)
@ -46,6 +48,11 @@ namespace Microsoft.AspNet.PipelineCore
get { return _canHasQuery.Fetch(_features) ?? _canHasQuery.Update(_features, new DefaultCanHasQuery(_features)); }
}
private ICanHasForm CanHasForm
{
get { return _canHasForm.Fetch(_features) ?? _canHasForm.Update(_features, new DefaultCanHasForm(_features)); }
}
private ICanHasRequestCookies CanHasRequestCookies
{
get { return _canHasCookies.Fetch(_features) ?? _canHasCookies.Update(_features, new DefaultCanHasRequestCookies(_features)); }
@ -112,6 +119,11 @@ namespace Microsoft.AspNet.PipelineCore
get { return CanHasQuery.Query; }
}
public override Task<IReadableStringCollection> GetFormAsync()
{
return CanHasForm.GetFormAsync();
}
public override string Protocol
{
get { return HttpRequestInformation.Protocol; }

View File

@ -0,0 +1,10 @@
using System.Threading.Tasks;
using Microsoft.AspNet.Abstractions;
namespace Microsoft.AspNet.PipelineCore
{
public interface ICanHasForm
{
Task<IReadableStringCollection> GetFormAsync();
}
}

View File

@ -0,0 +1,68 @@
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNet.FeatureModel;
using Microsoft.AspNet.HttpFeature;
using Moq;
using Xunit;
namespace Microsoft.AspNet.PipelineCore.Tests
{
public class DefaultCanHasFormTests
{
[Fact]
public async Task GetFormAsync_ReturnsParsedFormCollection()
{
// Arrange
var formContent = Encoding.UTF8.GetBytes("foo=bar&baz=2");
var features = new Mock<IFeatureCollection>();
var request = new Mock<IHttpRequestInformation>();
request.SetupGet(r => r.Body).Returns(new MemoryStream(formContent));
object value = request.Object;
features.Setup(f => f.TryGetValue(typeof(IHttpRequestInformation), out value))
.Returns(true);
var provider = new DefaultCanHasForm(features.Object);
// Act
var formCollection = await provider.GetFormAsync();
// Assert
Assert.Equal("bar", formCollection["foo"]);
Assert.Equal("2", formCollection["baz"]);
}
[Fact]
public async Task GetFormAsync_CachesFormCollectionPerBodyStream()
{
// Arrange
var formContent1 = Encoding.UTF8.GetBytes("foo=bar&baz=2");
var formContent2 = Encoding.UTF8.GetBytes("collection2=value");
var features = new Mock<IFeatureCollection>();
var request = new Mock<IHttpRequestInformation>();
request.SetupGet(r => r.Body).Returns(new MemoryStream(formContent1));
object value = request.Object;
features.Setup(f => f.TryGetValue(typeof(IHttpRequestInformation), out value))
.Returns(true);
var provider = new DefaultCanHasForm(features.Object);
// Act - 1
var formCollection = await provider.GetFormAsync();
// Assert - 1
Assert.Equal("bar", formCollection["foo"]);
Assert.Equal("2", formCollection["baz"]);
Assert.Same(formCollection, await provider.GetFormAsync());
// Act - 2
request.SetupGet(r => r.Body).Returns(new MemoryStream(formContent2));
formCollection = await provider.GetFormAsync();
// Assert - 2
Assert.Equal("value", formCollection["collection2"]);
}
}
}