Changed to use OptionalRouteConstraint created by Routing to use for inline optional parameters in attribute routing. Also added tests for inline parameters.

This commit is contained in:
Mugdha Kulkarni 2014-11-18 13:04:53 -08:00 committed by Mugdha Kulkarni
parent 00b61ec1e6
commit ba8cf3ca46
7 changed files with 844 additions and 3 deletions

View File

@ -224,6 +224,11 @@ namespace Microsoft.AspNet.Mvc.Routing
{
if (parameter.InlineConstraints != null)
{
if (parameter.IsOptional)
{
constraintBuilder.SetOptional(parameter.Name);
}
foreach (var inlineConstraint in parameter.InlineConstraints)
{
constraintBuilder.AddResolvedConstraint(parameter.Name, inlineConstraint.Constraint);

View File

@ -198,6 +198,53 @@ namespace Microsoft.AspNet.Mvc.Routing
Assert.Equal(expectedRouteGroup, context.RouteData.Values["test_route_group"]);
}
[Theory]
[InlineData("template/{parameter:int}", "/template/5", true)]
[InlineData("template/{parameter:int?}", "/template/5", true)]
[InlineData("template/{parameter:int?}", "/template", true)]
[InlineData("template/{parameter:int?}", "/template/qwer", false)]
public async Task AttributeRoute_WithOptionalInlineConstraint(string template, string request, bool expectedResult)
{
// Arrange
var expectedRouteGroup = string.Format("{0}&&{1}", 0, template);
// We need to force the creation of a closure in order to avoid an issue with Moq and Roslyn.
var numberOfCalls = 0;
Action<RouteContext> callBack = ctx => { ctx.IsHandled = true; numberOfCalls++; };
var next = new Mock<IRouter>();
next.Setup(r => r.RouteAsync(It.IsAny<RouteContext>()))
.Callback(callBack)
.Returns(Task.FromResult(true))
.Verifiable();
var firstRoute = CreateMatchingEntry(next.Object, template, order: 0);
// We setup the route entries in reverse order of precedence to ensure that when we
// try to route the request, the route with a higher precedence gets tried first.
var matchingRoutes = new[] { firstRoute };
var linkGenerationEntries = Enumerable.Empty<AttributeRouteLinkGenerationEntry>();
var route = new AttributeRoute(next.Object, matchingRoutes, linkGenerationEntries, NullLoggerFactory.Instance);
var context = CreateRouteContext(request);
// Act
await route.RouteAsync(context);
// Assert
if (expectedResult)
{
Assert.True(context.IsHandled);
Assert.Equal(expectedRouteGroup, context.RouteData.Values["test_route_group"]);
}
else
{
Assert.False(context.IsHandled);
}
}
[Theory]
[InlineData("template/5", "template/{parameter:int}")]
[InlineData("template/5", "template/{parameter}")]
@ -246,6 +293,56 @@ namespace Microsoft.AspNet.Mvc.Routing
Assert.Equal(expectedGroup, selectedGroup);
}
[Theory]
[InlineData("template/{parameter:int}", "template/5", 5)]
[InlineData("template/{parameter:int?}", "template/5", 5)]
[InlineData("template/{parameter:int?}", "template", null)]
[InlineData("template/{parameter:int?}", null, "asdf")]
[InlineData("template/{parameter:alpha?}", "template/asdf", "asdf")]
[InlineData("template/{parameter:alpha?}", "template", null)]
[InlineData("template/{parameter:int:range(1,20)?}", "template", null)]
[InlineData("template/{parameter:int:range(1,20)?}", "template/5", 5)]
[InlineData("template/{parameter:int:range(1,20)?}", null, 21)]
public void AttributeRoute_GenerateLink_OptionalInlineParameter(string template, string expectedResult, object parameter)
{
// Arrange
var expectedGroup = CreateRouteGroup(0, template);
string selectedGroup = null;
var next = new Mock<IRouter>();
next.Setup(n => n.GetVirtualPath(It.IsAny<VirtualPathContext>())).Callback<VirtualPathContext>(ctx =>
{
selectedGroup = (string)ctx.ProvidedValues[AttributeRouting.RouteGroupKey];
ctx.IsBound = true;
})
.Returns((string)null);
var matchingRoutes = Enumerable.Empty<AttributeRouteMatchingEntry>();
var entry = CreateGenerationEntry(template, requiredValues: null);
var linkGenerationEntries = new[] { entry };
var route = new AttributeRoute(next.Object, matchingRoutes, linkGenerationEntries, NullLoggerFactory.Instance);
VirtualPathContext context;
if (parameter != null)
{
context = CreateVirtualPathContext(values: null, ambientValues: new { parameter = parameter });
}
else
{
context = CreateVirtualPathContext(values: null, ambientValues: null);
}
// Act
string result = route.GetVirtualPath(context);
// Assert
Assert.Equal(expectedResult, result);
}
[Theory]
[InlineData("template/5", "template/{parameter:int}")]
[InlineData("template/5", "template/{parameter}")]
@ -1295,6 +1392,11 @@ namespace Microsoft.AspNet.Mvc.Routing
{
if (parameter.InlineConstraints != null)
{
if (parameter.IsOptional)
{
constraintBuilder.SetOptional(parameter.Name);
}
foreach (var constraint in parameter.InlineConstraints)
{
constraintBuilder.AddResolvedConstraint(parameter.Name, constraint.Constraint);

View File

@ -2,11 +2,14 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using InlineConstraints;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.TestHost;
using Newtonsoft.Json;
using Xunit;
namespace Microsoft.AspNet.Mvc.FunctionalTests
@ -40,12 +43,633 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
var client = server.CreateClient();
// Act & Assert
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() => client.GetAsync("http://localhost/area-withoutexists/Users"));
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
() => client.GetAsync("http://localhost/area-withoutexists/Users")
);
Assert.Equal("The view 'Index' was not found." +
" The following locations were searched:\r\n/Areas/Users/Views/Home/Index.cshtml\r\n" +
"/Areas/Users/Views/Shared/Index.cshtml\r\n/Views/Shared/Index.cshtml.",
ex.Message);
}
[Fact]
public async Task GetProductById_IntConstraintForOptionalId_IdPresent()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetProductById/5");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await GetResponseValues(response);
Assert.Equal(result["id"], "5");
Assert.Equal(result["controller"], "InlineConstraints_Products");
Assert.Equal(result["action"], "GetProductById");
}
[Fact]
public async Task GetProductById_IntConstraintForOptionalId_NoId()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetProductById");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await GetResponseValues(response);
Assert.Equal(result["controller"], "InlineConstraints_Products");
Assert.Equal(result["action"], "GetProductById");
}
[Fact]
public async Task GetProductById_IntConstraintForOptionalId_NotIntId()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetProductById/asdf");
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task GetProductByName_AlphaContraintForMandatoryName_ValidName()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetProductByName/asdf");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await GetResponseValues(response);
Assert.Equal(result["name"], "asdf");
Assert.Equal(result["controller"], "InlineConstraints_Products");
Assert.Equal(result["action"], "GetProductByName");
}
[Fact]
public async Task GetProductByName_AlphaContraintForMandatoryName_NonAlphaName()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetProductByName/asd123");
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task GetProductByName_AlphaContraintForMandatoryName_NoName()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetProductByName");
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task GetProductByManufacturingDate_DateTimeConstraintForMandatoryDateTime_ValidDateTime()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response =
await client.GetAsync(@"http://localhost/products/GetProductByManufacturingDate/2014-10-11T13:45:30");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await GetResponseValues(response);
Assert.Equal(result["dateTime"], new DateTime(2014, 10, 11, 13, 45, 30));
Assert.Equal(result["controller"], "InlineConstraints_Products");
Assert.Equal(result["action"], "GetProductByManufacturingDate");
}
[Fact]
public async Task GetProductByCategoryName_StringLengthConstraint_ForOptionalCategoryName_ValidCatName()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetProductByCategoryName/Sports");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await GetResponseValues(response);
Assert.Equal(result["name"], "Sports");
Assert.Equal(result["controller"], "InlineConstraints_Products");
Assert.Equal(result["action"], "GetProductByCategoryName");
}
[Fact]
public async Task GetProductByCategoryName_StringLengthConstraint_ForOptionalCategoryName_InvalidCatName()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response =
await client.GetAsync("http://localhost/products/GetProductByCategoryName/SportsSportsSportsSports");
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task GetProductByCategoryName_StringLength1To20Constraint_ForOptionalCategoryName_NoCatName()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetProductByCategoryName");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await GetResponseValues(response);
Assert.Equal(result["controller"], "InlineConstraints_Products");
Assert.Equal(result["action"], "GetProductByCategoryName");
}
[Fact]
public async Task GetProductByCategoryId_Int10To100Constraint_ForMandatoryCatId_ValidId()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetProductByCategoryId/40");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await GetResponseValues(response);
Assert.Equal(result["catId"], "40");
Assert.Equal(result["controller"], "InlineConstraints_Products");
Assert.Equal(result["action"], "GetProductByCategoryId");
}
[Fact]
public async Task GetProductByCategoryId_Int10To100Constraint_ForMandatoryCatId_InvalidId()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetProductByCategoryId/5");
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task GetProductByCategoryId_Int10To100Constraint_ForMandatoryCatId_NotIntId()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetProductByCategoryId/asdf");
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task GetProductByPrice_FloatContraintForOptionalPrice_Valid()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetProductByPrice/4023.23423");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await GetResponseValues(response);
Assert.Equal(result["price"], "4023.23423");
Assert.Equal(result["controller"], "InlineConstraints_Products");
Assert.Equal(result["action"], "GetProductByPrice");
}
[Fact]
public async Task GetProductByPrice_FloatContraintForOptionalPrice_NoPrice()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetProductByPrice");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await GetResponseValues(response);
Assert.Equal(result["controller"], "InlineConstraints_Products");
Assert.Equal(result["action"], "GetProductByPrice");
}
[Fact]
public async Task GetProductByManufacturerId_IntMin10Constraint_ForOptionalManufacturerId_Valid()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetProductByManufacturerId/57");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await GetResponseValues(response);
Assert.Equal(result["manId"], "57");
Assert.Equal(result["controller"], "InlineConstraints_Products");
Assert.Equal(result["action"], "GetProductByManufacturerId");
}
[Fact]
public async Task GetProductByManufacturerId_IntMin10Cinstraint_ForOptionalManufacturerId_NoId()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetProductByManufacturerId");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await GetResponseValues(response);
Assert.Equal(result["controller"], "InlineConstraints_Products");
Assert.Equal(result["action"], "GetProductByManufacturerId");
}
[Fact]
public async Task GetUserByName_RegExConstraint_ForMandatoryName_Valid()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetUserByName/abc");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await GetResponseValues(response);
Assert.Equal(result["controller"], "InlineConstraints_Products");
Assert.Equal(result["action"], "GetUserByName");
Assert.Equal(result["name"], "abc");
}
[Fact]
public async Task GetUserByName_RegExConstraint_ForMandatoryName_InValid()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/products/GetUserByName/abcd");
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task GetStoreById_GuidConstraintForOptionalId_Valid()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response =
await client.GetAsync("http://localhost/Store/GetStoreById/691cf17a-791b-4af8-99fd-e739e168170f");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await GetResponseValues(response);
Assert.Equal(result["id"], "691cf17a-791b-4af8-99fd-e739e168170f");
Assert.Equal(result["controller"], "InlineConstraints_Store");
Assert.Equal(result["action"], "GetStoreById");
}
[Fact]
public async Task GetStoreById_GuidConstraintForOptionalId_NoId()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/Store/GetStoreById");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await GetResponseValues(response);
Assert.Equal(result["controller"], "InlineConstraints_Store");
Assert.Equal(result["action"], "GetStoreById");
}
[Fact]
public async Task GetStoreById_GuidConstraintForOptionalId_NotGuidId()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/Store/GetStoreById/691cf17a-791b");
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task GetStoreByLocation_StringLengthConstraint_AlphaConstraint_ForMandatoryLocation_Valid()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/Store/GetStoreByLocation/Bellevue");
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var result = await GetResponseValues(response);
Assert.Equal(result["location"], "Bellevue");
Assert.Equal(result["controller"], "InlineConstraints_Store");
Assert.Equal(result["action"], "GetStoreByLocation");
}
[Fact]
public async Task GetStoreByLocation_StringLengthConstraint_AlphaConstraint_ForMandatoryLocation_MoreLength()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/Store/GetStoreByLocation/BellevueRedmond");
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task GetStoreByLocation_StringLengthConstraint_AlphaConstraint_ForMandatoryLocation_LessLength()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/Store/GetStoreByLocation/Be");
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task GetStoreByLocation_StringLengthConstraint_AlphaConstraint_ForMandatoryLocation_NoAlpha()
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
var response = await client.GetAsync("http://localhost/Store/GetStoreByLocation/Bell124");
// Assert
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
public static IEnumerable<object[]> QueryParameters
{
// The first four parameters are controller name, action name, parameters in the query and their values.
// These are used to generate a link, the last parameter is expected generated link
get
{
// Attribute Route, id:int? constraint
yield return new object[]
{
"InlineConstraints_Products",
"GetProductById",
"id",
"5",
"/products/GetProductById/5"
};
// Attribute Route, id:int? constraint
yield return new object[]
{
"InlineConstraints_Products",
"GetProductById",
"id",
"sdsd", ""
};
// Attribute Route, name:alpha constraint
yield return new object[]
{
"InlineConstraints_Products",
"GetProductByName",
"name",
"zxcv",
"/products/GetProductByName/zxcv"
};
// Attribute Route, name:length(1,20)? constraint
yield return new object[]
{
"InlineConstraints_Products",
"GetProductByCategoryName",
"name",
"sports",
"/products/GetProductByCategoryName/sports"
};
// Attribute Route, name:length(1,20)? constraint
yield return new object[]
{
"InlineConstraints_Products",
"GetProductByCategoryName",
null,
null,
"/products/GetProductByCategoryName"
};
// Attribute Route, catId:int:range(10, 100) constraint
yield return new object[]
{
"InlineConstraints_Products",
"GetProductByCategoryId",
"catId",
"50",
"/products/GetProductByCategoryId/50"
};
// Attribute Route, catId:int:range(10, 100) constraint
yield return new object[]
{
"InlineConstraints_Products",
"GetProductByCategoryId",
"catId",
"500",
""
};
// Attribute Route, name:length(1,20)? constraint
yield return new object[]
{
"InlineConstraints_Products",
"GetProductByPrice",
"price",
"123.45",
"/products/GetProductByPrice/123.45"
};
// Attribute Route, price:float? constraint
yield return new object[]
{
"InlineConstraints_Products",
"GetProductByManufacturerId",
"manId",
"15",
"/products/GetProductByManufacturerId/15"
};
// Attribute Route, manId:int:min(10)? constraint
yield return new object[]
{
"InlineConstraints_Products",
"GetProductByManufacturerId",
"manId",
"qwer",
""
};
// Attribute Route, manId:int:min(10)? constraint
yield return new object[]
{
"InlineConstraints_Products",
"GetProductByManufacturerId",
"manId",
"1",
""
};
// Attribute Route, manId:int:min(10)? constraint
yield return new object[]
{
"InlineConstraints_Products",
"GetProductByManufacturerId",
"manId",
"1",
""
};
// Attribute Route, dateTime:datetime constraint
yield return new object[]
{
"InlineConstraints_Products",
"GetProductByManufacturingDate",
"dateTime",
"2014-10-11T13:45:30",
"/products/GetProductByManufacturingDate/2014-10-11T13%3a45%3a30"
};
// Conventional Route, id:guid? constraint
yield return new object[]
{
"InlineConstraints_Store",
"GetStoreById",
"id",
"691cf17a-791b-4af8-99fd-e739e168170f",
"/store/GetStoreById/691cf17a-791b-4af8-99fd-e739e168170f"
};
}
}
[Theory]
[MemberData(nameof(QueryParameters))]
public async Task GetGeneratedLink(
string controller,
string action,
string parameterName,
string parameterValue,
string expectedLink)
{
// Arrange
var server = TestServer.Create(_provider, _app);
var client = server.CreateClient();
// Act
string url;
if (parameterName == null)
{
url = string.Format(
"{0}newController={1}&newAction={2}",
"http://localhost/products/GetGeneratedLink?",
controller,
action);
}
else
{
url = string.Format(
"{0}newController={1}&newAction={2}&{3}={4}",
"http://localhost/products/GetGeneratedLink?",
controller,
action,
parameterName,
parameterValue);
}
var response = await client.GetAsync(url);
// Assert
var body = await response.Content.ReadAsStringAsync();
Assert.Equal(expectedLink, body);
}
private async Task<IDictionary<string, object>> GetResponseValues(HttpResponseMessage response)
{
var body = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<IDictionary<string, object>>(body);
}
}
}
}

View File

@ -0,0 +1,77 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
namespace InlineConstraintsWebSite.Controllers
{
[Route("products/[action]")]
public class InlineConstraints_ProductsController : Controller
{
public IDictionary<string, object> Index()
{
return ActionContext.RouteData.Values;
}
[HttpGet("{id:int?}")]
public IDictionary<string, object> GetProductById(int id)
{
return ActionContext.RouteData.Values;
}
[HttpGet("{name:alpha}")]
public IDictionary<string, object> GetProductByName(string name)
{
return ActionContext.RouteData.Values;
}
[HttpGet("{dateTime:datetime}")]
public IDictionary<string, object> GetProductByManufacturingDate(DateTime dateTime)
{
return ActionContext.RouteData.Values;
}
[HttpGet("{name:length(1,20)?}")]
public IDictionary<string, object> GetProductByCategoryName(string name)
{
return ActionContext.RouteData.Values;
}
[HttpGet("{catId:int:range(10, 100)}")]
public IDictionary<string, object> GetProductByCategoryId(int catId)
{
return ActionContext.RouteData.Values;
}
[HttpGet("{price:float?}")]
public IDictionary<string, object> GetProductByPrice(float price)
{
return ActionContext.RouteData.Values;
}
[HttpGet("{manId:int:min(10)?}")]
public IDictionary<string, object> GetProductByManufacturerId(int manId)
{
return ActionContext.RouteData.Values;
}
[HttpGet(@"{name:regex(^abc$)}")]
public IDictionary<string, object> GetUserByName(string name)
{
return ActionContext.RouteData.Values;
}
public string GetGeneratedLink()
{
var query = ActionContext.HttpContext.Request.Query;
var values = query
.Where(kvp => kvp.Key != "newAction" && kvp.Key != "newController")
.ToDictionary(kvp => kvp.Key, kvp => (object)kvp.Value[0]);
return Url.Action(query["newAction"], query["newController"], values);
}
}
}

View File

@ -0,0 +1,22 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNet.Mvc;
using System;
using System.Collections.Generic;
namespace InlineConstraintsWebSite.Controllers
{
public class InlineConstraints_StoreController : Controller
{
public IDictionary<string, object> GetStoreById(Guid id)
{
return ActionContext.RouteData.Values;
}
public IDictionary<string, object> GetStoreByLocation(string location)
{
return ActionContext.RouteData.Values;
}
}
}

View File

@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<DevelopmentServerPort>45283</DevelopmentServerPort>
</PropertyGroup>
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">

View File

@ -4,6 +4,7 @@
using System;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Routing.Constraints;
using Microsoft.Framework.DependencyInjection;
namespace InlineConstraints
@ -23,6 +24,15 @@ namespace InlineConstraints
app.UseMvc(routes =>
{
routes.MapRoute("StoreId",
"store/{action}/{id:guid?}",
defaults: new { controller = "InlineConstraints_Store" });
routes.MapRoute("StoreLocation",
"store/{action}/{location:minlength(3):maxlength(10)}",
defaults: new { controller = "InlineConstraints_Store" },
constraints: new { location = new AlphaRouteConstraint() });
// Used by tests for the 'exists' constraint.
routes.MapRoute("areaExists-area", "area-exists/{area:exists}/{controller=Home}/{action=Index}");
routes.MapRoute("areaExists", "area-exists/{controller=Home}/{action=Index}");