Skip to content
This repository was archived by the owner on Nov 20, 2018. It is now read-only.

Commit 5f75c07

Browse files
authored
Add RoutesValues to HttpRequest (#1042)
1 parent e8d5a85 commit 5f75c07

File tree

4 files changed

+105
-0
lines changed

4 files changed

+105
-0
lines changed

src/Microsoft.AspNetCore.Http.Abstractions/HttpRequest.cs

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.IO;
55
using System.Threading;
66
using System.Threading.Tasks;
7+
using Microsoft.AspNetCore.Routing;
78

89
namespace Microsoft.AspNetCore.Http
910
{
@@ -117,5 +118,11 @@ public abstract class HttpRequest
117118
/// </summary>
118119
/// <returns></returns>
119120
public abstract Task<IFormCollection> ReadFormAsync(CancellationToken cancellationToken = new CancellationToken());
121+
122+
/// <summary>
123+
/// Gets the collection of route values for this request.
124+
/// </summary>
125+
/// <returns>The collection of route values for this request.</returns>
126+
public virtual RouteValueDictionary RouteValues { get; set; }
120127
}
121128
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright (c) .NET Foundation. All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
4+
using Microsoft.AspNetCore.Routing;
5+
6+
namespace Microsoft.AspNetCore.Http.Features
7+
{
8+
/// <summary>
9+
/// A feature for routing values. Use <see cref="HttpContext.Features"/>
10+
/// to access the values associated with the current request.
11+
/// </summary>
12+
public class RouteValuesFeature : IRouteValuesFeature
13+
{
14+
private RouteValueDictionary _routeValues;
15+
16+
/// <summary>
17+
/// Gets or sets the <see cref="RouteValueDictionary"/> associated with the currrent
18+
/// request.
19+
/// </summary>
20+
public RouteValueDictionary RouteValues
21+
{
22+
get
23+
{
24+
if (_routeValues == null)
25+
{
26+
_routeValues = new RouteValueDictionary();
27+
}
28+
29+
return _routeValues;
30+
}
31+
set => _routeValues = value;
32+
}
33+
}
34+
}

src/Microsoft.AspNetCore.Http/Internal/DefaultHttpRequest.cs

+12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Threading;
77
using System.Threading.Tasks;
88
using Microsoft.AspNetCore.Http.Features;
9+
using Microsoft.AspNetCore.Routing;
910
using Microsoft.Net.Http.Headers;
1011

1112
namespace Microsoft.AspNetCore.Http.Internal
@@ -17,6 +18,7 @@ public class DefaultHttpRequest : HttpRequest
1718
private readonly static Func<IFeatureCollection, IQueryFeature> _newQueryFeature = f => new QueryFeature(f);
1819
private readonly static Func<HttpRequest, IFormFeature> _newFormFeature = r => new FormFeature(r);
1920
private readonly static Func<IFeatureCollection, IRequestCookiesFeature> _newRequestCookiesFeature = f => new RequestCookiesFeature(f);
21+
private readonly static Func<IFeatureCollection, IRouteValuesFeature> _newRouteValuesFeature = f => new RouteValuesFeature();
2022

2123
private HttpContext _context;
2224
private FeatureReferences<FeatureInterfaces> _features;
@@ -52,6 +54,9 @@ public virtual void Uninitialize()
5254
private IRequestCookiesFeature RequestCookiesFeature =>
5355
_features.Fetch(ref _features.Cache.Cookies, _newRequestCookiesFeature);
5456

57+
private IRouteValuesFeature RouteValuesFeature =>
58+
_features.Fetch(ref _features.Cache.RouteValues, _newRouteValuesFeature);
59+
5560
public override PathString PathBase
5661
{
5762
get { return new PathString(HttpRequestFeature.PathBase); }
@@ -151,12 +156,19 @@ public override Task<IFormCollection> ReadFormAsync(CancellationToken cancellati
151156
return FormFeature.ReadFormAsync(cancellationToken);
152157
}
153158

159+
public override RouteValueDictionary RouteValues
160+
{
161+
get { return RouteValuesFeature.RouteValues; }
162+
set { RouteValuesFeature.RouteValues = value; }
163+
}
164+
154165
struct FeatureInterfaces
155166
{
156167
public IHttpRequestFeature Request;
157168
public IQueryFeature Query;
158169
public IFormFeature Form;
159170
public IRequestCookiesFeature Cookies;
171+
public IRouteValuesFeature RouteValues;
160172
}
161173
}
162174
}

test/Microsoft.AspNetCore.Http.Tests/Internal/DefaultHttpRequestTests.cs

+52
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Generic;
66
using System.Globalization;
77
using Microsoft.AspNetCore.Http.Features;
8+
using Microsoft.AspNetCore.Routing;
89
using Microsoft.Extensions.Primitives;
910
using Xunit;
1011

@@ -194,6 +195,57 @@ public void Cookies_GetAndSet()
194195
Assert.Equal(new[] { "name2=value2" }, cookieHeaders);
195196
}
196197

198+
[Fact]
199+
public void RouteValues_GetAndSet()
200+
{
201+
var context = new DefaultHttpContext();
202+
var request = context.Request;
203+
204+
var routeValuesFeature = context.Features.Get<IRouteValuesFeature>();
205+
// No feature set for initial DefaultHttpRequest
206+
Assert.Null(routeValuesFeature);
207+
208+
// Route values returns empty collection by default
209+
Assert.Empty(request.RouteValues);
210+
211+
// Get and set value on request route values
212+
request.RouteValues["new"] = "setvalue";
213+
Assert.Equal("setvalue", request.RouteValues["new"]);
214+
215+
routeValuesFeature = context.Features.Get<IRouteValuesFeature>();
216+
// Accessing DefaultHttpRequest.RouteValues creates feature
217+
Assert.NotNull(routeValuesFeature);
218+
219+
request.RouteValues = new RouteValueDictionary(new { key = "value" });
220+
// Can set DefaultHttpRequest.RouteValues
221+
Assert.NotNull(request.RouteValues);
222+
Assert.Equal("value", request.RouteValues["key"]);
223+
224+
// DefaultHttpRequest.RouteValues uses feature
225+
Assert.Equal(routeValuesFeature.RouteValues, request.RouteValues);
226+
227+
// Setting route values to null sets empty collection on request
228+
routeValuesFeature.RouteValues = null;
229+
Assert.Empty(request.RouteValues);
230+
231+
var customRouteValuesFeature = new CustomRouteValuesFeature
232+
{
233+
RouteValues = new RouteValueDictionary(new { key = "customvalue" })
234+
};
235+
context.Features.Set<IRouteValuesFeature>(customRouteValuesFeature);
236+
// Can override DefaultHttpRequest.RouteValues with custom feature
237+
Assert.Equal(customRouteValuesFeature.RouteValues, request.RouteValues);
238+
239+
// Can clear feature
240+
context.Features.Set<IRouteValuesFeature>(null);
241+
Assert.Empty(request.RouteValues);
242+
}
243+
244+
private class CustomRouteValuesFeature : IRouteValuesFeature
245+
{
246+
public RouteValueDictionary RouteValues { get; set; }
247+
}
248+
197249
private static HttpRequest CreateRequest(IHeaderDictionary headers)
198250
{
199251
var context = new DefaultHttpContext();

0 commit comments

Comments
 (0)