Adding API for consuming url generation
This commit is contained in:
parent
89eb6e6445
commit
cd73fac433
|
|
@ -50,5 +50,10 @@ namespace RoutingSample
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RouteBindResult Bind(RouteBindContext context)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,11 @@ namespace RoutingSample
|
||||||
var endpoint1 = new HttpContextRouteEndpoint(async (context) => await context.Response.WriteAsync("match1"));
|
var endpoint1 = new HttpContextRouteEndpoint(async (context) => await context.Response.WriteAsync("match1"));
|
||||||
var endpoint2 = new HttpContextRouteEndpoint(async (context) => await context.Response.WriteAsync("Hello, World!"));
|
var endpoint2 = new HttpContextRouteEndpoint(async (context) => await context.Response.WriteAsync("Hello, World!"));
|
||||||
|
|
||||||
var rb1 = new RouteBuilder(endpoint1, routes);
|
var rb1 = new RouteBuilder(endpoint1, routes.Routes);
|
||||||
rb1.AddPrefixRoute("api/store");
|
rb1.AddPrefixRoute("api/store");
|
||||||
rb1.AddTemplateRoute("api/{controller}/{*extra}", new { controller = "Store" });
|
rb1.AddTemplateRoute("api/{controller}/{*extra}", new { controller = "Store" });
|
||||||
|
|
||||||
var rb2 = new RouteBuilder(endpoint2, routes);
|
var rb2 = new RouteBuilder(endpoint2, routes.Routes);
|
||||||
rb2.AddPrefixRoute("hello/world");
|
rb2.AddPrefixRoute("hello/world");
|
||||||
rb2.AddPrefixRoute("");
|
rb2.AddPrefixRoute("");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Abstractions;
|
using Microsoft.AspNet.Abstractions;
|
||||||
|
|
||||||
|
|
@ -20,13 +21,13 @@ namespace Microsoft.AspNet.Routing
|
||||||
|
|
||||||
public async Task<bool> Invoke(HttpContext context)
|
public async Task<bool> Invoke(HttpContext context)
|
||||||
{
|
{
|
||||||
RouteContext routeContext = new RouteContext(context);
|
var routeContext = new RouteContext(context);
|
||||||
|
|
||||||
for (int i = 0; i < Routes.Count; i++)
|
for (var i = 0; i < Routes.Count; i++)
|
||||||
{
|
{
|
||||||
IRoute route = Routes[i];
|
var route = Routes[i];
|
||||||
|
|
||||||
RouteMatch match = route.Match(routeContext);
|
var match = route.Match(routeContext);
|
||||||
if (match != null)
|
if (match != null)
|
||||||
{
|
{
|
||||||
context.SetFeature<IRouteValues>(new RouteValues(match.Values));
|
context.SetFeature<IRouteValues>(new RouteValues(match.Values));
|
||||||
|
|
@ -41,5 +42,23 @@ namespace Microsoft.AspNet.Routing
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetUrl(HttpContext context, IDictionary<string, object> values)
|
||||||
|
{
|
||||||
|
var routeBindContext = new RouteBindContext(context, values);
|
||||||
|
|
||||||
|
for (var i = 0; i < Routes.Count; i++)
|
||||||
|
{
|
||||||
|
var route = Routes[i];
|
||||||
|
|
||||||
|
var result = route.Bind(routeBindContext);
|
||||||
|
if (result != null)
|
||||||
|
{
|
||||||
|
return result.Url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,7 @@ namespace Microsoft.AspNet.Routing
|
||||||
public interface IRoute
|
public interface IRoute
|
||||||
{
|
{
|
||||||
RouteMatch Match(RouteContext context);
|
RouteMatch Match(RouteContext context);
|
||||||
|
|
||||||
|
RouteBindResult Bind(RouteBindContext context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Abstractions;
|
using Microsoft.AspNet.Abstractions;
|
||||||
|
|
||||||
|
|
@ -7,6 +8,10 @@ namespace Microsoft.AspNet.Routing
|
||||||
{
|
{
|
||||||
public interface IRouteEngine
|
public interface IRouteEngine
|
||||||
{
|
{
|
||||||
|
IRouteCollection Routes { get; }
|
||||||
|
|
||||||
Task<bool> Invoke(HttpContext context);
|
Task<bool> Invoke(HttpContext context);
|
||||||
|
|
||||||
|
string GetUrl(HttpContext context, IDictionary<string, object> values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,14 +6,14 @@ namespace Microsoft.AspNet.Routing.Owin
|
||||||
{
|
{
|
||||||
public static class BuilderExtensions
|
public static class BuilderExtensions
|
||||||
{
|
{
|
||||||
public static IRouteCollection UseRouter(this IBuilder builder)
|
public static IRouteEngine UseRouter(this IBuilder builder)
|
||||||
{
|
{
|
||||||
var routes = new DefaultRouteCollection();
|
var routes = new DefaultRouteCollection();
|
||||||
var engine = new DefaultRouteEngine(routes);
|
var engine = new DefaultRouteEngine(routes);
|
||||||
|
|
||||||
builder.Use((next) => new RouterMiddleware(next, engine).Invoke);
|
builder.Use((next) => new RouterMiddleware(next, engine).Invoke);
|
||||||
|
|
||||||
return routes;
|
return engine;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNet.Abstractions;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Routing
|
||||||
|
{
|
||||||
|
public class RouteBindContext
|
||||||
|
{
|
||||||
|
public RouteBindContext(HttpContext context, IDictionary<string, object> values)
|
||||||
|
{
|
||||||
|
Context = context;
|
||||||
|
Values = values;
|
||||||
|
|
||||||
|
if (Context != null)
|
||||||
|
{
|
||||||
|
var ambientValues = context.GetFeature<IRouteValues>();
|
||||||
|
AmbientValues = ambientValues == null ? null : ambientValues.Values;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDictionary<string, object> AmbientValues { get; private set; }
|
||||||
|
|
||||||
|
public HttpContext Context { get; private set; }
|
||||||
|
|
||||||
|
public IDictionary<string, object> Values { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Routing
|
||||||
|
{
|
||||||
|
public class RouteBindResult
|
||||||
|
{
|
||||||
|
public RouteBindResult(string url)
|
||||||
|
{
|
||||||
|
Url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Url { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -12,9 +12,6 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
{
|
{
|
||||||
private const string SeparatorString = "/";
|
private const string SeparatorString = "/";
|
||||||
|
|
||||||
private readonly TemplateMatcher _matcher;
|
|
||||||
private readonly TemplateBinder _binder;
|
|
||||||
|
|
||||||
public Template(List<TemplateSegment> segments)
|
public Template(List<TemplateSegment> segments)
|
||||||
{
|
{
|
||||||
if (segments == null)
|
if (segments == null)
|
||||||
|
|
@ -37,20 +34,12 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_matcher = new TemplateMatcher(this);
|
|
||||||
_binder = new TemplateBinder(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TemplatePart> Parameters { get; private set; }
|
public List<TemplatePart> Parameters { get; private set; }
|
||||||
|
|
||||||
public List<TemplateSegment> Segments { get; private set; }
|
public List<TemplateSegment> Segments { get; private set; }
|
||||||
|
|
||||||
public IDictionary<string, object> Match(string requestPath, IDictionary<string, object> defaults)
|
|
||||||
{
|
|
||||||
return _matcher.Match(requestPath, defaults);
|
|
||||||
}
|
|
||||||
|
|
||||||
private string DebuggerToString()
|
private string DebuggerToString()
|
||||||
{
|
{
|
||||||
return string.Join(SeparatorString, Segments.Select(s => s.DebuggerToString()));
|
return string.Join(SeparatorString, Segments.Select(s => s.DebuggerToString()));
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
|
|
||||||
public Template Template { get; private set; }
|
public Template Template { get; private set; }
|
||||||
|
|
||||||
public BoundRouteTemplate Bind(IDictionary<string, object> defaults, IDictionary<string, object> ambientValues, IDictionary<string, object> values)
|
public string Bind(IDictionary<string, object> defaults, IDictionary<string, object> ambientValues, IDictionary<string, object> values)
|
||||||
{
|
{
|
||||||
if (values == null)
|
if (values == null)
|
||||||
{
|
{
|
||||||
|
|
@ -184,7 +184,7 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2: If the route is a match generate the appropriate URI
|
// Step 2: If the route is a match generate the appropriate URI
|
||||||
private BoundRouteTemplate BindValues(TemplateBindingContext bindingContext)
|
private string BindValues(TemplateBindingContext bindingContext)
|
||||||
{
|
{
|
||||||
var context = new UriBuildingContext();
|
var context = new UriBuildingContext();
|
||||||
|
|
||||||
|
|
@ -261,10 +261,7 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
encoded.Append(Uri.EscapeDataString(converted));
|
encoded.Append(Uri.EscapeDataString(converted));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new BoundRouteTemplate()
|
return encoded.ToString();
|
||||||
{
|
|
||||||
Path = encoded.ToString(),
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string UriEncode(string str)
|
private static string UriEncode(string str)
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,10 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
{
|
{
|
||||||
values.Add(part.Name, defaultValue);
|
values.Add(part.Name, defaultValue);
|
||||||
}
|
}
|
||||||
|
else if (part.IsOptional)
|
||||||
|
{
|
||||||
|
// This is optional (with no default value) - there's nothing to capture here, so just move on.
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// There's no default for this parameter
|
// There's no default for this parameter
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
private readonly IRouteEndpoint _endpoint;
|
private readonly IRouteEndpoint _endpoint;
|
||||||
private readonly Template _parsedTemplate;
|
private readonly Template _parsedTemplate;
|
||||||
private readonly string _routeTemplate;
|
private readonly string _routeTemplate;
|
||||||
|
private readonly TemplateMatcher _matcher;
|
||||||
|
private readonly TemplateBinder _binder;
|
||||||
|
|
||||||
public TemplateRoute(IRouteEndpoint endpoint, string routeTemplate)
|
public TemplateRoute(IRouteEndpoint endpoint, string routeTemplate)
|
||||||
: this(endpoint, routeTemplate, null)
|
: this(endpoint, routeTemplate, null)
|
||||||
|
|
@ -25,11 +27,14 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
}
|
}
|
||||||
|
|
||||||
_endpoint = endpoint;
|
_endpoint = endpoint;
|
||||||
_routeTemplate = routeTemplate ?? String.Empty;
|
_routeTemplate = routeTemplate ?? string.Empty;
|
||||||
_defaults = defaults ?? new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
_defaults = defaults ?? new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
// The parser will throw for invalid routes.
|
// The parser will throw for invalid routes.
|
||||||
_parsedTemplate = TemplateParser.Parse(RouteTemplate);
|
_parsedTemplate = TemplateParser.Parse(RouteTemplate);
|
||||||
|
|
||||||
|
_matcher = new TemplateMatcher(_parsedTemplate);
|
||||||
|
_binder = new TemplateBinder(_parsedTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDictionary<string, object> Defaults
|
public IDictionary<string, object> Defaults
|
||||||
|
|
@ -55,12 +60,12 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
}
|
}
|
||||||
|
|
||||||
var requestPath = context.RequestPath;
|
var requestPath = context.RequestPath;
|
||||||
if (!String.IsNullOrEmpty(requestPath) && requestPath[0] == '/')
|
if (!string.IsNullOrEmpty(requestPath) && requestPath[0] == '/')
|
||||||
{
|
{
|
||||||
requestPath = requestPath.Substring(1);
|
requestPath = requestPath.Substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
IDictionary<string, object> values = _parsedTemplate.Match(requestPath, _defaults);
|
var values = _matcher.Match(requestPath, _defaults);
|
||||||
if (values == null)
|
if (values == null)
|
||||||
{
|
{
|
||||||
// If we got back a null value set, that means the URI did not match
|
// If we got back a null value set, that means the URI did not match
|
||||||
|
|
@ -71,5 +76,11 @@ namespace Microsoft.AspNet.Routing.Template
|
||||||
return new RouteMatch(_endpoint, values);
|
return new RouteMatch(_endpoint, values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RouteBindResult Bind(RouteBindContext context)
|
||||||
|
{
|
||||||
|
var path = _binder.Bind(_defaults, context.AmbientValues, context.Values);
|
||||||
|
return path == null ? null : new RouteBindResult(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Routing.Template.Tests
|
|
||||||
{
|
|
||||||
// This is just a placeholder
|
|
||||||
public class RouteValueDictionary : Dictionary<string, object>
|
|
||||||
{
|
|
||||||
public RouteValueDictionary()
|
|
||||||
: base(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public RouteValueDictionary(object obj)
|
|
||||||
: base(StringComparer.OrdinalIgnoreCase)
|
|
||||||
{
|
|
||||||
if (obj != null)
|
|
||||||
{
|
|
||||||
foreach (var property in obj.GetType().GetTypeInfo().GetProperties())
|
|
||||||
{
|
|
||||||
Add(property.Name, property.GetValue(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -139,7 +139,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Assert.NotNull(boundTemplate);
|
Assert.NotNull(boundTemplate);
|
||||||
Assert.Equal(expected, boundTemplate.Path);
|
Assert.Equal(expected, boundTemplate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -989,7 +989,7 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
||||||
|
|
||||||
// We want to chop off the query string and compare that using an unordered comparison
|
// We want to chop off the query string and compare that using an unordered comparison
|
||||||
var expectedParts = new PathAndQuery(expected);
|
var expectedParts = new PathAndQuery(expected);
|
||||||
var actualParts = new PathAndQuery(boundTemplate.Path);
|
var actualParts = new PathAndQuery(boundTemplate);
|
||||||
|
|
||||||
Assert.Equal(expectedParts.Path, actualParts.Path);
|
Assert.Equal(expectedParts.Path, actualParts.Path);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -733,6 +733,37 @@ namespace Microsoft.AspNet.Routing.Template.Tests
|
||||||
Assert.False(match.ContainsKey("action"));
|
Assert.False(match.ContainsKey("action"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MatchDoesNotSetOptionalParameter_EmptyString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var route = CreateMatcher("{controller?}");
|
||||||
|
var url = "";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var match = route.Match(url, null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(match);
|
||||||
|
Assert.Equal(0, match.Values.Count);
|
||||||
|
Assert.False(match.ContainsKey("controller"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Match_EmptyRouteWith_EmptyString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var route = CreateMatcher("");
|
||||||
|
var url = "";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var match = route.Match(url, null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(match);
|
||||||
|
Assert.Equal(0, match.Values.Count);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void MatchMultipleOptionalParameters()
|
public void MatchMultipleOptionalParameters()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,172 @@
|
||||||
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNet.Abstractions;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Routing.Template.Tests
|
||||||
|
{
|
||||||
|
public class TemplateRouteTests
|
||||||
|
{
|
||||||
|
#region Route Matching
|
||||||
|
|
||||||
|
// PathString in HttpAbstractions guarantees a leading slash - so no value in testing other cases.
|
||||||
|
[Fact]
|
||||||
|
public void Match_Success_LeadingSlash()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var route = CreateRoute("{controller}/{action}");
|
||||||
|
var context = CreateRouteContext("/Home/Index");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var match = route.Match(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(match);
|
||||||
|
Assert.Equal(2, match.Values.Count);
|
||||||
|
Assert.Equal("Home", match.Values["controller"]);
|
||||||
|
Assert.Equal("Index", match.Values["action"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Match_Success_RootUrl()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var route = CreateRoute("");
|
||||||
|
var context = CreateRouteContext("/");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var match = route.Match(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(match);
|
||||||
|
Assert.Equal(0, match.Values.Count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Match_Success_Defaults()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var route = CreateRoute("{controller}/{action}", new { action = "Index" });
|
||||||
|
var context = CreateRouteContext("/Home");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var match = route.Match(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(match);
|
||||||
|
Assert.Equal(2, match.Values.Count);
|
||||||
|
Assert.Equal("Home", match.Values["controller"]);
|
||||||
|
Assert.Equal("Index", match.Values["action"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Match_Fails()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var route = CreateRoute("{controller}/{action}");
|
||||||
|
var context = CreateRouteContext("/Home");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var match = route.Match(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Null(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RouteContext CreateRouteContext(string requestPath)
|
||||||
|
{
|
||||||
|
var request = new Mock<HttpRequest>(MockBehavior.Strict);
|
||||||
|
request.SetupGet(r => r.Path).Returns(new PathString(requestPath));
|
||||||
|
|
||||||
|
var context = new Mock<HttpContext>(MockBehavior.Strict);
|
||||||
|
context.SetupGet(c => c.Request).Returns(request.Object);
|
||||||
|
|
||||||
|
return new RouteContext(context.Object);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Route Binding
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Bind_Success()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var route = CreateRoute("{controller}");
|
||||||
|
var context = CreateRouteBindContext(new {controller = "Home"});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var bind = route.Bind(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(bind);
|
||||||
|
Assert.Equal("Home", bind.Url);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Bind_Fail()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var route = CreateRoute("{controller}/{action}");
|
||||||
|
var context = CreateRouteBindContext(new { controller = "Home" });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var bind = route.Bind(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Null(bind);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Bind_Success_AmbientValues()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var route = CreateRoute("{controller}/{action}");
|
||||||
|
var context = CreateRouteBindContext(new { action = "Index"}, new { controller = "Home" });
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var bind = route.Bind(context);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.NotNull(bind);
|
||||||
|
Assert.Equal("Home/Index", bind.Url);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RouteBindContext CreateRouteBindContext(object values)
|
||||||
|
{
|
||||||
|
return CreateRouteBindContext(new RouteValueDictionary(values), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RouteBindContext CreateRouteBindContext(object values, object ambientValues)
|
||||||
|
{
|
||||||
|
return CreateRouteBindContext(new RouteValueDictionary(values), new RouteValueDictionary(ambientValues));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RouteBindContext CreateRouteBindContext(IDictionary<string, object> values, IDictionary<string, object> ambientValues)
|
||||||
|
{
|
||||||
|
var context = new Mock<HttpContext>(MockBehavior.Strict);
|
||||||
|
context.Setup(c => c.GetFeature<IRouteValues>()).Returns(new RouteValues(ambientValues));
|
||||||
|
|
||||||
|
return new RouteBindContext(context.Object, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private static TemplateRoute CreateRoute(string template)
|
||||||
|
{
|
||||||
|
return new TemplateRoute(CreateEndpoint(), template);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TemplateRoute CreateRoute(string template, object defaults)
|
||||||
|
{
|
||||||
|
return new TemplateRoute(CreateEndpoint(), template, new RouteValueDictionary(defaults));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IRouteEndpoint CreateEndpoint()
|
||||||
|
{
|
||||||
|
return new Mock<IRouteEndpoint>(MockBehavior.Strict).Object;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
"configurations": {
|
"configurations": {
|
||||||
"net45": {
|
"net45": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"Moq": "4.2.1402.2112",
|
||||||
"Owin": "1.0",
|
"Owin": "1.0",
|
||||||
"xunit": "1.9.2",
|
"xunit": "1.9.2",
|
||||||
"xunit.extensions": "1.9.2"
|
"xunit.extensions": "1.9.2"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue