This additional constraint enables adding a route to the template (and potentially to the UseMvc method) without actually implementing the actual artifact.
For example without adding an area to a controller, a route can still be added to the template. - Also added functional tests.
This commit is contained in:
parent
b58083f73a
commit
10285d7d39
17
Mvc.sln
17
Mvc.sln
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 14
|
# Visual Studio 14
|
||||||
VisualStudioVersion = 14.0.21708.0
|
VisualStudioVersion = 14.0.21806.0
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DAAE4C74-D06F-4874-A166-33305D2643CE}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DAAE4C74-D06F-4874-A166-33305D2643CE}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -17,7 +17,7 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.Core",
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.ModelBinding", "src\Microsoft.AspNet.Mvc.ModelBinding\Microsoft.AspNet.Mvc.ModelBinding.kproj", "{FA915D3D-22C3-4478-97F2-A81D28B6C503}"
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.ModelBinding", "src\Microsoft.AspNet.Mvc.ModelBinding\Microsoft.AspNet.Mvc.ModelBinding.kproj", "{FA915D3D-22C3-4478-97F2-A81D28B6C503}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Common", "src\Microsoft.AspNet.Mvc.Common\Microsoft.AspNet.Mvc.Common.kproj", "{F3DF6D0B-16FE-4402-B92C-7243A75CF1FD}"
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.Common", "src\Microsoft.AspNet.Mvc.Common\Microsoft.AspNet.Mvc.Common.kproj", "{F3DF6D0B-16FE-4402-B92C-7243A75CF1FD}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.ModelBinding.Test", "test\Microsoft.AspNet.Mvc.ModelBinding.Test\Microsoft.AspNet.Mvc.ModelBinding.Test.kproj", "{3B8DC0C0-6C55-4034-AD96-DE1000928E6B}"
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.ModelBinding.Test", "test\Microsoft.AspNet.Mvc.ModelBinding.Test\Microsoft.AspNet.Mvc.ModelBinding.Test.kproj", "{3B8DC0C0-6C55-4034-AD96-DE1000928E6B}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|
@ -37,6 +37,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.AspNet.Mvc.Functi
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "BasicWebSite", "test\WebSites\BasicWebSite\BasicWebSite.kproj", "{34DF1487-12C6-476C-BE0A-F31DF1939AE5}"
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "BasicWebSite", "test\WebSites\BasicWebSite\BasicWebSite.kproj", "{34DF1487-12C6-476C-BE0A-F31DF1939AE5}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "InlineConstraintsWebSite", "test\WebSites\InlineConstraintsWebSite\InlineConstraintsWebSite.kproj", "{EA34877F-1AC1-42B7-B4E6-15A093F40CAE}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -177,6 +179,16 @@ Global
|
||||||
{34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
{34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
{34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
{34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
{34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Release|x86.ActiveCfg = Release|Any CPU
|
{34DF1487-12C6-476C-BE0A-F31DF1939AE5}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{EA34877F-1AC1-42B7-B4E6-15A093F40CAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{EA34877F-1AC1-42B7-B4E6-15A093F40CAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{EA34877F-1AC1-42B7-B4E6-15A093F40CAE}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
|
||||||
|
{EA34877F-1AC1-42B7-B4E6-15A093F40CAE}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
|
||||||
|
{EA34877F-1AC1-42B7-B4E6-15A093F40CAE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{EA34877F-1AC1-42B7-B4E6-15A093F40CAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{EA34877F-1AC1-42B7-B4E6-15A093F40CAE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{EA34877F-1AC1-42B7-B4E6-15A093F40CAE}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
|
||||||
|
{EA34877F-1AC1-42B7-B4E6-15A093F40CAE}.Release|Mixed Platforms.Build.0 = Release|Any CPU
|
||||||
|
{EA34877F-1AC1-42B7-B4E6-15A093F40CAE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
@ -196,5 +208,6 @@ Global
|
||||||
{16703B76-C9F7-4C75-AE6C-53D92E308E3C} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
|
{16703B76-C9F7-4C75-AE6C-53D92E308E3C} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
|
||||||
{323D0C04-B518-4A8F-8A8E-3546AD153D34} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
|
{323D0C04-B518-4A8F-8A8E-3546AD153D34} = {3BA657BF-28B1-42DA-B5B0-1C4601FCF7B1}
|
||||||
{34DF1487-12C6-476C-BE0A-F31DF1939AE5} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
{34DF1487-12C6-476C-BE0A-F31DF1939AE5} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||||
|
{EA34877F-1AC1-42B7-B4E6-15A093F40CAE} = {16703B76-C9F7-4C75-AE6C-53D92E308E3C}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using Microsoft.AspNet.Builder;
|
using Microsoft.AspNet.Builder;
|
||||||
using Microsoft.AspNet.Routing;
|
using Microsoft.AspNet.Routing;
|
||||||
|
using Microsoft.Framework.ConfigurationModel;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
using Microsoft.Framework.DependencyInjection;
|
||||||
using MvcSample.Web.Filters;
|
using MvcSample.Web.Filters;
|
||||||
using MvcSample.Web.Services;
|
using MvcSample.Web.Services;
|
||||||
|
|
@ -63,7 +64,7 @@ namespace MvcSample.Web
|
||||||
|
|
||||||
app.UseMvc(routes =>
|
app.UseMvc(routes =>
|
||||||
{
|
{
|
||||||
routes.MapRoute("areaRoute", "{area}/{controller}/{action}");
|
routes.MapRoute("areaRoute", "{area:exists}/{controller}/{action}");
|
||||||
|
|
||||||
routes.MapRoute(
|
routes.MapRoute(
|
||||||
"controllerActionRoute",
|
"controllerActionRoute",
|
||||||
|
|
|
||||||
|
|
@ -345,19 +345,12 @@ namespace Microsoft.AspNet.Mvc
|
||||||
if (descriptors == null)
|
if (descriptors == null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException(
|
throw new InvalidOperationException(
|
||||||
Resources.FormatPropertyOfTypeCannotBeNull(_actionDescriptorsCollectionProvider.GetType(),
|
Resources.FormatPropertyOfTypeCannotBeNull("ActionDescriptors",
|
||||||
"ActionDescriptors"));
|
_actionDescriptorsCollectionProvider.GetType()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
var items = descriptors.Items;
|
return descriptors.Items;
|
||||||
|
|
||||||
if (items == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException(
|
|
||||||
Resources.FormatPropertyOfTypeCannotBeNull(descriptors.GetType(), "Items"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ActionDescriptorCandidate
|
private class ActionDescriptorCandidate
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
// 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 System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNet.Http;
|
||||||
|
using Microsoft.AspNet.Mvc.Core;
|
||||||
|
using Microsoft.AspNet.Routing;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc
|
||||||
|
{
|
||||||
|
public class KnownRouteValueConstraint : IRouteConstraint
|
||||||
|
{
|
||||||
|
private RouteValuesCollection _cachedValuesCollection;
|
||||||
|
|
||||||
|
public bool Match([NotNull] HttpContext httpContext,
|
||||||
|
[NotNull] IRouter route,
|
||||||
|
[NotNull] string routeKey,
|
||||||
|
[NotNull] IDictionary<string, object> values,
|
||||||
|
RouteDirection routeDirection)
|
||||||
|
{
|
||||||
|
object value;
|
||||||
|
if (values.TryGetValue(routeKey, out value))
|
||||||
|
{
|
||||||
|
string valueAsString = value as string;
|
||||||
|
|
||||||
|
if (valueAsString != null)
|
||||||
|
{
|
||||||
|
var allValues = GetAndCacheAllMatchingValues(routeKey, httpContext);
|
||||||
|
var match = allValues.Any(existingRouteValue =>
|
||||||
|
existingRouteValue.Equals(
|
||||||
|
valueAsString,
|
||||||
|
StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string[] GetAndCacheAllMatchingValues(string routeKey, HttpContext httpContext)
|
||||||
|
{
|
||||||
|
var actionDescriptors = GetAndValidateActionDescriptorsCollection(httpContext);
|
||||||
|
var version = actionDescriptors.Version;
|
||||||
|
var valuesCollection = _cachedValuesCollection;
|
||||||
|
|
||||||
|
if (valuesCollection == null ||
|
||||||
|
version != valuesCollection.Version)
|
||||||
|
{
|
||||||
|
var routeValueCollection = actionDescriptors
|
||||||
|
.Items
|
||||||
|
.Select(ad => ad.RouteConstraints
|
||||||
|
.FirstOrDefault(
|
||||||
|
c => c.RouteKey == routeKey &&
|
||||||
|
c.KeyHandling == RouteKeyHandling.RequireKey))
|
||||||
|
.Where(rc => rc != null)
|
||||||
|
.Select(rc => rc.RouteValue)
|
||||||
|
.Distinct()
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
valuesCollection = new RouteValuesCollection(version, routeValueCollection);
|
||||||
|
_cachedValuesCollection = valuesCollection;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _cachedValuesCollection.Items;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActionDescriptorsCollection GetAndValidateActionDescriptorsCollection(HttpContext httpContext)
|
||||||
|
{
|
||||||
|
var provider = httpContext.ApplicationServices
|
||||||
|
.GetService<IActionDescriptorsCollectionProvider>();
|
||||||
|
var descriptors = provider.ActionDescriptors;
|
||||||
|
|
||||||
|
if (descriptors == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
Resources.FormatPropertyOfTypeCannotBeNull("ActionDescriptors",
|
||||||
|
provider.GetType()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return descriptors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RouteValuesCollection
|
||||||
|
{
|
||||||
|
public RouteValuesCollection(int version, string[] items)
|
||||||
|
{
|
||||||
|
Version = version;
|
||||||
|
Items = items;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Version { get; private set; }
|
||||||
|
|
||||||
|
public string[] Items { get; private set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -202,6 +202,7 @@
|
||||||
<Compile Include="Rendering\ViewEngineResult.cs" />
|
<Compile Include="Rendering\ViewEngineResult.cs" />
|
||||||
<Compile Include="RouteConstraintAttribute.cs" />
|
<Compile Include="RouteConstraintAttribute.cs" />
|
||||||
<Compile Include="RouteDataActionConstraint.cs" />
|
<Compile Include="RouteDataActionConstraint.cs" />
|
||||||
|
<Compile Include="KnownRouteValueConstraint.cs" />
|
||||||
<Compile Include="RouteKeyHandling.cs" />
|
<Compile Include="RouteKeyHandling.cs" />
|
||||||
<Compile Include="TemplateInfo.cs" />
|
<Compile Include="TemplateInfo.cs" />
|
||||||
<Compile Include="UrlHelper.cs" />
|
<Compile Include="UrlHelper.cs" />
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,23 @@ namespace Microsoft.Framework.DependencyInjection
|
||||||
public static IServiceCollection AddMvc(this IServiceCollection services)
|
public static IServiceCollection AddMvc(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.Add(RoutingServices.GetDefaultServices());
|
services.Add(RoutingServices.GetDefaultServices());
|
||||||
|
AddMvcRouteOptions(services);
|
||||||
return services.Add(MvcServices.GetDefaultServices());
|
return services.Add(MvcServices.GetDefaultServices());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IServiceCollection AddMvc(this IServiceCollection services, IConfiguration configuration)
|
public static IServiceCollection AddMvc(this IServiceCollection services, IConfiguration configuration)
|
||||||
{
|
{
|
||||||
services.Add(RoutingServices.GetDefaultServices());
|
services.Add(RoutingServices.GetDefaultServices());
|
||||||
|
AddMvcRouteOptions(services);
|
||||||
return services.Add(MvcServices.GetDefaultServices(configuration));
|
return services.Add(MvcServices.GetDefaultServices(configuration));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void AddMvcRouteOptions(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.SetupOptions<RouteOptions>(routeOptions =>
|
||||||
|
routeOptions.ConstraintMap
|
||||||
|
.Add("exists",
|
||||||
|
typeof(KnownRouteValueConstraint)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,198 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#if NET45
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.AspNet.Http;
|
||||||
|
using Microsoft.AspNet.Mvc;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
using Moq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Routing.Tests
|
||||||
|
{
|
||||||
|
public class KnownRouteValueConstraintTests
|
||||||
|
{
|
||||||
|
private readonly IRouteConstraint _constraint = new KnownRouteValueConstraint();
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("area", RouteDirection.IncomingRequest)]
|
||||||
|
[InlineData("controller", RouteDirection.IncomingRequest)]
|
||||||
|
[InlineData("action", RouteDirection.IncomingRequest)]
|
||||||
|
[InlineData("randomKey", RouteDirection.IncomingRequest)]
|
||||||
|
[InlineData("area", RouteDirection.UrlGeneration)]
|
||||||
|
[InlineData("controller", RouteDirection.UrlGeneration)]
|
||||||
|
[InlineData("action", RouteDirection.UrlGeneration)]
|
||||||
|
[InlineData("randomKey", RouteDirection.UrlGeneration)]
|
||||||
|
public void RouteKey_DoesNotExist_MatchFails(string keyName, RouteDirection direction)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var values = new Dictionary<string, object>();
|
||||||
|
var httpContext = GetHttpContext(new ActionDescriptor());
|
||||||
|
var route = (new Mock<IRouter>()).Object;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var match = _constraint.Match(httpContext, route, keyName, values, direction);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("area", RouteDirection.IncomingRequest)]
|
||||||
|
[InlineData("controller", RouteDirection.IncomingRequest)]
|
||||||
|
[InlineData("action", RouteDirection.IncomingRequest)]
|
||||||
|
[InlineData("randomKey", RouteDirection.IncomingRequest)]
|
||||||
|
[InlineData("area", RouteDirection.UrlGeneration)]
|
||||||
|
[InlineData("controller", RouteDirection.UrlGeneration)]
|
||||||
|
[InlineData("action", RouteDirection.UrlGeneration)]
|
||||||
|
[InlineData("randomKey", RouteDirection.UrlGeneration)]
|
||||||
|
public void RouteKey_Exists_MatchSucceeds(string keyName, RouteDirection direction)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var actionDescriptor = CreateActionDescriptor("testArea",
|
||||||
|
"testController",
|
||||||
|
"testAction");
|
||||||
|
actionDescriptor.RouteConstraints.Add(new RouteDataActionConstraint("randomKey", "testRandom"));
|
||||||
|
var httpContext = GetHttpContext(actionDescriptor);
|
||||||
|
var route = (new Mock<IRouter>()).Object;
|
||||||
|
var values = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "area", "testArea" },
|
||||||
|
{ "controller", "testController" },
|
||||||
|
{ "action", "testAction" },
|
||||||
|
{ "randomKey", "testRandom" }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var match = _constraint.Match(httpContext, route, keyName, values, direction);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.True(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("area", RouteDirection.IncomingRequest)]
|
||||||
|
[InlineData("controller", RouteDirection.IncomingRequest)]
|
||||||
|
[InlineData("action", RouteDirection.IncomingRequest)]
|
||||||
|
[InlineData("randomKey", RouteDirection.IncomingRequest)]
|
||||||
|
[InlineData("area", RouteDirection.UrlGeneration)]
|
||||||
|
[InlineData("controller", RouteDirection.UrlGeneration)]
|
||||||
|
[InlineData("action", RouteDirection.UrlGeneration)]
|
||||||
|
[InlineData("randomKey", RouteDirection.UrlGeneration)]
|
||||||
|
public void RouteValue_DoesNotExists_MatchFails(string keyName, RouteDirection direction)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var actionDescriptor = CreateActionDescriptor("testArea",
|
||||||
|
"testController",
|
||||||
|
"testAction");
|
||||||
|
actionDescriptor.RouteConstraints.Add(new RouteDataActionConstraint("randomKey", "testRandom"));
|
||||||
|
var httpContext = GetHttpContext(actionDescriptor);
|
||||||
|
var route = (new Mock<IRouter>()).Object;
|
||||||
|
var values = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "area", "invalidTestArea" },
|
||||||
|
{ "controller", "invalidTestController" },
|
||||||
|
{ "action", "invalidTestAction" },
|
||||||
|
{ "randomKey", "invalidTestRandom" }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var match = _constraint.Match(httpContext, route, keyName, values, direction);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(RouteDirection.IncomingRequest)]
|
||||||
|
[InlineData(RouteDirection.UrlGeneration)]
|
||||||
|
public void RouteValue_IsNotAString_MatchFails(RouteDirection direction)
|
||||||
|
{
|
||||||
|
var actionDescriptor = CreateActionDescriptor("testArea",
|
||||||
|
controller: null,
|
||||||
|
action: null);
|
||||||
|
var httpContext = GetHttpContext(actionDescriptor);
|
||||||
|
var route = (new Mock<IRouter>()).Object;
|
||||||
|
var values = new Dictionary<string, object>()
|
||||||
|
{
|
||||||
|
{ "area", 12 },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var match = _constraint.Match(httpContext, route, "area", values, direction);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.False(match);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData(RouteDirection.IncomingRequest)]
|
||||||
|
[InlineData(RouteDirection.UrlGeneration)]
|
||||||
|
public void ActionDescriptorsCollection_SettingNullValue_Throws(RouteDirection direction)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var httpContext = new Mock<HttpContext>();
|
||||||
|
httpContext.Setup(o => o.ApplicationServices
|
||||||
|
.GetService(typeof(IActionDescriptorsCollectionProvider)))
|
||||||
|
.Returns(new Mock<IActionDescriptorsCollectionProvider>().Object);
|
||||||
|
// Act & Assert
|
||||||
|
var ex = Assert.Throws<InvalidOperationException>(
|
||||||
|
() => _constraint.Match(httpContext.Object,
|
||||||
|
null,
|
||||||
|
"area",
|
||||||
|
new Dictionary<string, object>{ { "area", "area" } },
|
||||||
|
direction));
|
||||||
|
Assert.Equal("The 'ActionDescriptors' property of "+
|
||||||
|
"'Castle.Proxies.IActionDescriptorsCollectionProviderProxy' must not be null.",
|
||||||
|
ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static HttpContext GetHttpContext(ActionDescriptor actionDescriptor)
|
||||||
|
{
|
||||||
|
var actionProvider = new Mock<INestedProviderManager<ActionDescriptorProviderContext>>(
|
||||||
|
MockBehavior.Strict);
|
||||||
|
|
||||||
|
actionProvider
|
||||||
|
.Setup(p => p.Invoke(It.IsAny<ActionDescriptorProviderContext>()))
|
||||||
|
.Callback<ActionDescriptorProviderContext>(c => c.Results.Add(actionDescriptor));
|
||||||
|
|
||||||
|
var context = new Mock<HttpContext>();
|
||||||
|
context.Setup(o => o.ApplicationServices
|
||||||
|
.GetService(typeof(INestedProviderManager<ActionDescriptorProviderContext>)))
|
||||||
|
.Returns(actionProvider.Object);
|
||||||
|
context.Setup(o => o.ApplicationServices
|
||||||
|
.GetService(typeof(IActionDescriptorsCollectionProvider)))
|
||||||
|
.Returns(new DefaultActionDescriptorsCollectionProvider(context.Object.ApplicationServices));
|
||||||
|
return context.Object;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ActionDescriptor CreateActionDescriptor(string area, string controller, string action)
|
||||||
|
{
|
||||||
|
var actionDescriptor = new ActionDescriptor()
|
||||||
|
{
|
||||||
|
Name = string.Format("Area: {0}, Controller: {1}, Action: {2}", area, controller, action),
|
||||||
|
RouteConstraints = new List<RouteDataActionConstraint>(),
|
||||||
|
};
|
||||||
|
|
||||||
|
actionDescriptor.RouteConstraints.Add(
|
||||||
|
area == null ?
|
||||||
|
new RouteDataActionConstraint("area", RouteKeyHandling.DenyKey) :
|
||||||
|
new RouteDataActionConstraint("area", area));
|
||||||
|
|
||||||
|
actionDescriptor.RouteConstraints.Add(
|
||||||
|
controller == null ?
|
||||||
|
new RouteDataActionConstraint("controller", RouteKeyHandling.DenyKey) :
|
||||||
|
new RouteDataActionConstraint("controller", controller));
|
||||||
|
|
||||||
|
actionDescriptor.RouteConstraints.Add(
|
||||||
|
action == null ?
|
||||||
|
new RouteDataActionConstraint("action", RouteKeyHandling.DenyKey) :
|
||||||
|
new RouteDataActionConstraint("action", action));
|
||||||
|
|
||||||
|
return actionDescriptor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
@ -55,6 +55,7 @@
|
||||||
<Compile Include="Rendering\HtmlAttributePropertyHelperTest.cs" />
|
<Compile Include="Rendering\HtmlAttributePropertyHelperTest.cs" />
|
||||||
<Compile Include="Rendering\ViewContextTests.cs" />
|
<Compile Include="Rendering\ViewContextTests.cs" />
|
||||||
<Compile Include="Rendering\ViewDataOfTTest.cs" />
|
<Compile Include="Rendering\ViewDataOfTTest.cs" />
|
||||||
|
<Compile Include="KnownRouteValueConstraintTests.cs" />
|
||||||
<Compile Include="TestController.cs" />
|
<Compile Include="TestController.cs" />
|
||||||
<Compile Include="TypeHelperTest.cs" />
|
<Compile Include="TypeHelperTest.cs" />
|
||||||
<Compile Include="UrlHelperTest.cs" />
|
<Compile Include="UrlHelperTest.cs" />
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,11 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BasicWebSite;
|
using BasicWebSite;
|
||||||
using Microsoft.AspNet.Builder;
|
using Microsoft.AspNet.Builder;
|
||||||
using Microsoft.AspNet.TestHost;
|
using Microsoft.AspNet.TestHost;
|
||||||
using Microsoft.Framework.DependencyInjection;
|
|
||||||
using Microsoft.Framework.DependencyInjection.Fallback;
|
|
||||||
using Microsoft.Framework.Runtime;
|
|
||||||
using Microsoft.Framework.Runtime.Infrastructure;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
|
|
@ -29,24 +24,15 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
|
|
||||||
public BasicTests()
|
public BasicTests()
|
||||||
{
|
{
|
||||||
var originalProvider = CallContextServiceLocator.Locator.ServiceProvider;
|
_provider = TestHelper.CreateServices("BasicWebSite");
|
||||||
IApplicationEnvironment appEnvironment = originalProvider.GetService<IApplicationEnvironment>();
|
|
||||||
|
|
||||||
// When an application executes in a regular context, the application base path points to the root
|
|
||||||
// directory where the application is located, for example MvcSample.Web. However, when executing
|
|
||||||
// an aplication as part of a test, the ApplicationBasePath of the IApplicationEnvironment points
|
|
||||||
// to the root folder of the test project.
|
|
||||||
// To compensate for this, we need to calculate the original path and override the application
|
|
||||||
// environment value so that components like the view engine work properly in the context of the
|
|
||||||
// test.
|
|
||||||
string appBasePath = CalculateApplicationBasePath(appEnvironment);
|
|
||||||
_provider = new ServiceCollection()
|
|
||||||
.AddInstance(typeof(IApplicationEnvironment), new TestApplicationEnvironment(appEnvironment, appBasePath))
|
|
||||||
.BuildServiceProvider(originalProvider);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[InlineData("http://localhost/")]
|
||||||
public async Task CanRender_ViewsWithLayout()
|
[InlineData("http://localhost/Home")]
|
||||||
|
[InlineData("http://localhost/Home/Index")]
|
||||||
|
[InlineData("http://localhost/Users")]
|
||||||
|
[InlineData("http://localhost/Monitor/CountActionDescriptorInvocations")]
|
||||||
|
public async Task CanRender_ViewsWithLayout(string url)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var server = TestServer.Create(_provider, _app);
|
var server = TestServer.Create(_provider, _app);
|
||||||
|
|
@ -59,7 +45,7 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
// Act
|
// Act
|
||||||
|
|
||||||
// The host is not important as everything runs in memory and tests are isolated from each other.
|
// The host is not important as everything runs in memory and tests are isolated from each other.
|
||||||
var result = await client.GetAsync("http://localhost/");
|
var result = await client.GetAsync(url);
|
||||||
var responseContent = await result.ReadBodyAsStringAsync();
|
var responseContent = await result.ReadBodyAsStringAsync();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
@ -129,18 +115,5 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
Assert.Equal(expectedContent, results[1]);
|
Assert.Equal(expectedContent, results[1]);
|
||||||
Assert.Equal(expectedContent, results[2]);
|
Assert.Equal(expectedContent, results[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the path relative to the current application base path.
|
|
||||||
private static string CalculateApplicationBasePath(IApplicationEnvironment appEnvironment)
|
|
||||||
{
|
|
||||||
// Mvc/test/Microsoft.AspNet.Mvc.FunctionalTests
|
|
||||||
var appBase = appEnvironment.ApplicationBasePath;
|
|
||||||
|
|
||||||
// Mvc/test
|
|
||||||
var test = Path.GetDirectoryName(appBase);
|
|
||||||
|
|
||||||
// Mvc/test/WebSites/BasicWebSite
|
|
||||||
return Path.GetFullPath(Path.Combine(appBase, "..", "WebSites", "BasicWebSite"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
// 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 System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using InlineConstraints;
|
||||||
|
using Microsoft.AspNet.Builder;
|
||||||
|
using Microsoft.AspNet.Routing;
|
||||||
|
using Microsoft.AspNet.TestHost;
|
||||||
|
using Microsoft.Framework.ConfigurationModel;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||||
|
using Microsoft.Framework.Runtime;
|
||||||
|
using Microsoft.Framework.Runtime.Infrastructure;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
|
{
|
||||||
|
public class InlineConstraintTests
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider _provider;
|
||||||
|
private readonly Action<IBuilder> _app = new Startup().Configure;
|
||||||
|
private readonly string _jsonConfigFilePath;
|
||||||
|
private readonly Configuration _config = new Configuration();
|
||||||
|
public InlineConstraintTests()
|
||||||
|
{
|
||||||
|
_provider = TestHelper.CreateServices("InlineConstraintsWebSite");
|
||||||
|
|
||||||
|
// TODO: Hardcoding the config file path for now. Update it to read it from args.
|
||||||
|
_jsonConfigFilePath = @"config\InlineConstraintTestsConfig.json";
|
||||||
|
_config.AddJsonFile(_jsonConfigFilePath);
|
||||||
|
|
||||||
|
Environment.SetEnvironmentVariable("AppConfigPath", _jsonConfigFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task RoutingToANonExistantArea_WithExistConstraint_RoutesToCorrectAction()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var source = new JsonConfigurationSource(_jsonConfigFilePath);
|
||||||
|
|
||||||
|
// Add the exists inline constraint.
|
||||||
|
_config.Set("TemplateCollection:areaRoute:TemplateValue",
|
||||||
|
@"{area:exists}/{controller=Home}/{action=Index}");
|
||||||
|
_config.Set("TemplateCollection:actionAsMethod:TemplateValue",
|
||||||
|
@"{controller=Home}/{action=Index}");
|
||||||
|
_config.Commit();
|
||||||
|
|
||||||
|
var server = TestServer.Create(_provider, _app);
|
||||||
|
var client = server.Handler;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await client.GetAsync("http://localhost/Users");
|
||||||
|
Assert.Equal(200, result.StatusCode);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var returnValue = await result.ReadBodyAsStringAsync();
|
||||||
|
Assert.Equal("Users.Index", returnValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task RoutingToANonExistantArea_WithoutExistConstraint_RoutesToIncorrectAction()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
_config.Set("TemplateCollection:areaRoute:TemplateValue",
|
||||||
|
@"{area}/{controller=Home}/{action=Index}");
|
||||||
|
_config.Set("TemplateCollection:actionAsMethod:TemplateValue",
|
||||||
|
@"{controller=Home}/{action=Index}");
|
||||||
|
|
||||||
|
_config.Commit();
|
||||||
|
|
||||||
|
var server = TestServer.Create(_provider, _app);
|
||||||
|
var client = server.Handler;
|
||||||
|
|
||||||
|
// Act & Assert
|
||||||
|
var ex = await Assert.ThrowsAsync<InvalidOperationException>
|
||||||
|
(async () => await client.GetAsync("http://localhost/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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,6 +30,8 @@
|
||||||
<Content Include="project.json" />
|
<Content Include="project.json" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="InlineConstraintTests.cs" />
|
||||||
|
<Compile Include="TestHelper.cs" />
|
||||||
<Compile Include="BasicTests.cs" />
|
<Compile Include="BasicTests.cs" />
|
||||||
<Compile Include="HttpResponseHelpers.cs" />
|
<Compile Include="HttpResponseHelpers.cs" />
|
||||||
<Compile Include="ResourceHelpers.cs" />
|
<Compile Include="ResourceHelpers.cs" />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
// 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 System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using InlineConstraints;
|
||||||
|
using Microsoft.AspNet.Builder;
|
||||||
|
using Microsoft.AspNet.Routing;
|
||||||
|
using Microsoft.AspNet.TestHost;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
using Microsoft.Framework.DependencyInjection.Fallback;
|
||||||
|
using Microsoft.Framework.Runtime;
|
||||||
|
using Microsoft.Framework.Runtime.Infrastructure;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
|
{
|
||||||
|
public static class TestHelper
|
||||||
|
{
|
||||||
|
public static IServiceProvider CreateServices(string applicationWebSiteName)
|
||||||
|
{
|
||||||
|
var originalProvider = CallContextServiceLocator.Locator.ServiceProvider;
|
||||||
|
IApplicationEnvironment appEnvironment = originalProvider.GetService<IApplicationEnvironment>();
|
||||||
|
|
||||||
|
// When an application executes in a regular context, the application base path points to the root
|
||||||
|
// directory where the application is located, for example MvcSample.Web. However, when executing
|
||||||
|
// an aplication as part of a test, the ApplicationBasePath of the IApplicationEnvironment points
|
||||||
|
// to the root folder of the test project.
|
||||||
|
// To compensate for this, we need to calculate the original path and override the application
|
||||||
|
// environment value so that components like the view engine work properly in the context of the
|
||||||
|
// test.
|
||||||
|
string appBasePath = CalculateApplicationBasePath(appEnvironment, applicationWebSiteName);
|
||||||
|
var provider = new ServiceCollection()
|
||||||
|
.AddInstance(typeof(IApplicationEnvironment),
|
||||||
|
new TestApplicationEnvironment(appEnvironment, appBasePath))
|
||||||
|
.BuildServiceProvider(originalProvider);
|
||||||
|
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the path relative to the application base path.
|
||||||
|
public static string CalculateApplicationBasePath(IApplicationEnvironment appEnvironment, string applicationWebSiteName)
|
||||||
|
{
|
||||||
|
// Mvc/test/Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
|
var appBase = appEnvironment.ApplicationBasePath;
|
||||||
|
|
||||||
|
// Mvc/test
|
||||||
|
var test = Path.GetDirectoryName(appBase);
|
||||||
|
|
||||||
|
// Mvc/test/WebSites/applicationWebSiteName
|
||||||
|
return Path.GetFullPath(Path.Combine(appBase, "..", "WebSites", applicationWebSiteName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"TemplateCollection": {
|
||||||
|
"areaRoute": {
|
||||||
|
"TemplateValue": ""
|
||||||
|
},
|
||||||
|
"actionAsMethod": {
|
||||||
|
"TemplateValue": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,12 +5,14 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"BasicWebSite": "",
|
"BasicWebSite": "",
|
||||||
|
"InlineConstraintsWebSite": "",
|
||||||
"Microsoft.AspNet.TestHost": "0.1-alpha-*",
|
"Microsoft.AspNet.TestHost": "0.1-alpha-*",
|
||||||
"Microsoft.Framework.Runtime.Interfaces": "0.1-alpha-*",
|
"Microsoft.Framework.Runtime.Interfaces": "0.1-alpha-*",
|
||||||
"xunit.abstractions": "2.0.0-aspnet-*",
|
"xunit.abstractions": "2.0.0-aspnet-*",
|
||||||
"xunit.assert": "2.0.0-aspnet-*",
|
"xunit.assert": "2.0.0-aspnet-*",
|
||||||
"xunit.core": "2.0.0-aspnet-*",
|
"xunit.core": "2.0.0-aspnet-*",
|
||||||
"Xunit.KRunner": "0.1-alpha-*"
|
"Xunit.KRunner": "0.1-alpha-*",
|
||||||
|
"Microsoft.Framework.ConfigurationModel.Json": "0.1-alpha-*"
|
||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
"test": "Xunit.KRunner"
|
"test": "Xunit.KRunner"
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="ActionDescriptorCreationCounter.cs" />
|
<Compile Include="ActionDescriptorCreationCounter.cs" />
|
||||||
|
<Compile Include="Controllers\UsersController.cs" />
|
||||||
<Compile Include="Controllers\HomeController.cs" />
|
<Compile Include="Controllers\HomeController.cs" />
|
||||||
<Compile Include="Controllers\MonitorController.cs" />
|
<Compile Include="Controllers\MonitorController.cs" />
|
||||||
<Compile Include="Startup.cs" />
|
<Compile Include="Startup.cs" />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using Microsoft.AspNet.Mvc;
|
||||||
|
|
||||||
|
namespace BasicWebSite.Controllers
|
||||||
|
{
|
||||||
|
public class UsersController : Controller
|
||||||
|
{
|
||||||
|
public IActionResult Index()
|
||||||
|
{
|
||||||
|
return Content("Users.Index");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -21,8 +21,13 @@ namespace BasicWebSite
|
||||||
// Add MVC to the request pipeline
|
// Add MVC to the request pipeline
|
||||||
app.UseMvc(routes =>
|
app.UseMvc(routes =>
|
||||||
{
|
{
|
||||||
|
routes.MapRoute("areaRoute",
|
||||||
|
"{area:exists}/{controller}/{action}",
|
||||||
|
new { controller = "Home", action = "Index" });
|
||||||
|
|
||||||
routes.MapRoute("ActionAsMethod", "{controller}/{action}",
|
routes.MapRoute("ActionAsMethod", "{controller}/{action}",
|
||||||
defaults: new { controller = "Home", action = "Index" });
|
defaults: new { controller = "Home", action = "Index" });
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"TemplateCollection" : {
|
||||||
|
"areaRoute" : {
|
||||||
|
"TemplateValue" : "{area:exists}/{controller=Home}/{action=Index}"
|
||||||
|
},
|
||||||
|
"actionRoute" : {
|
||||||
|
"TemplateValue" : "{controller=Home}/{action=Index}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using Microsoft.AspNet.Mvc;
|
||||||
|
|
||||||
|
namespace InlineConstraints.Controllers
|
||||||
|
{
|
||||||
|
public class HomeController : Controller
|
||||||
|
{
|
||||||
|
public IActionResult Index()
|
||||||
|
{
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
using Microsoft.AspNet.Mvc;
|
||||||
|
|
||||||
|
namespace InlineConstraints.Controllers
|
||||||
|
{
|
||||||
|
public class UsersController : Controller
|
||||||
|
{
|
||||||
|
public IActionResult Index()
|
||||||
|
{
|
||||||
|
return Content("Users.Index");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">12.0</VisualStudioVersion>
|
||||||
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.Props" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>ea34877f-1ac1-42b7-b4e6-15a093f40cae</ProjectGuid>
|
||||||
|
<OutputType>Web</OutputType>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="$(OutputType) == 'Console'">
|
||||||
|
<DebuggerFlavor>ConsoleDebugger</DebuggerFlavor>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="$(OutputType) == 'Web'">
|
||||||
|
<DebuggerFlavor>WebDebugger</DebuggerFlavor>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'" Label="Configuration">
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<DevelopmentServerPort>38821</DevelopmentServerPort>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||||
|
<DevelopmentServerPort>624661</DevelopmentServerPort>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Controllers\HomeController.cs" />
|
||||||
|
<Compile Include="Controllers\UsersController.cs" />
|
||||||
|
<Compile Include="Startup.cs" />
|
||||||
|
<Compile Include="TestControllerAssemblyProvider.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="App_Data\config.json" />
|
||||||
|
<Content Include="project.json" />
|
||||||
|
<Content Include="Views\Home\Index.cshtml" />
|
||||||
|
<Content Include="Views\Shared\Error.cshtml" />
|
||||||
|
<Content Include="Views\Shared\_Layout.cshtml" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.AspNet.Builder;
|
||||||
|
using Microsoft.AspNet.Mvc;
|
||||||
|
using Microsoft.AspNet.Routing;
|
||||||
|
using Microsoft.Framework.ConfigurationModel;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
using Microsoft.Framework.Runtime;
|
||||||
|
|
||||||
|
namespace InlineConstraints
|
||||||
|
{
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
public Action<IRouteBuilder> RouteCollectionProvider { get; set; }
|
||||||
|
public void Configure(IBuilder app)
|
||||||
|
{
|
||||||
|
// Set up application services
|
||||||
|
app.UseServices(services =>
|
||||||
|
{
|
||||||
|
// Add MVC services to the services container
|
||||||
|
services.AddMvc();
|
||||||
|
|
||||||
|
// Add a custom assembly provider so that we add only controllers present in
|
||||||
|
// this assembly.
|
||||||
|
services.AddTransient<IControllerAssemblyProvider, TestControllerAssemblyProvider>();
|
||||||
|
});
|
||||||
|
|
||||||
|
var config = new Configuration();
|
||||||
|
config.AddEnvironmentVariables();
|
||||||
|
|
||||||
|
string appConfigPath;
|
||||||
|
if (config.TryGet("AppConfigPath", out appConfigPath))
|
||||||
|
{
|
||||||
|
config.AddJsonFile(appConfigPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var basePath = app.ApplicationServices.GetService<IApplicationEnvironment>().ApplicationBasePath;
|
||||||
|
config.AddJsonFile(Path.Combine(basePath, @"App_Data\config.json"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add MVC to the request pipeline
|
||||||
|
app.UseMvc(routes=> {
|
||||||
|
foreach (var item in GetDataFromConfig(config))
|
||||||
|
{
|
||||||
|
routes.MapRoute(item.RouteName, item.RouteTemplateValue);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<RouteConfigData> GetDataFromConfig(IConfiguration config)
|
||||||
|
{
|
||||||
|
foreach (var template in config.GetSubKey("TemplateCollection").GetSubKeys())
|
||||||
|
{
|
||||||
|
yield return
|
||||||
|
new RouteConfigData()
|
||||||
|
{
|
||||||
|
RouteName = template.Key,
|
||||||
|
RouteTemplateValue = template.Value.Get("TemplateValue")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RouteConfigData
|
||||||
|
{
|
||||||
|
public string RouteName { get; set; }
|
||||||
|
public string RouteTemplateValue { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using Microsoft.AspNet.Mvc;
|
||||||
|
|
||||||
|
namespace InlineConstraints
|
||||||
|
{
|
||||||
|
public class TestControllerAssemblyProvider : IControllerAssemblyProvider
|
||||||
|
{
|
||||||
|
public IEnumerable<Assembly> CandidateAssemblies
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new[] { typeof(TestControllerAssemblyProvider).GetTypeInfo().Assembly };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
@{
|
||||||
|
Layout = "/Views/Shared/_Layout.cshtml";
|
||||||
|
ViewBag.Title = "Inline Constraints Home Page";
|
||||||
|
}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h1>ASP.NET vNext</h1>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
@{
|
||||||
|
Layout = "/Views/Shared/_Layout.cshtml";
|
||||||
|
ViewBag.Title = "Error";
|
||||||
|
}
|
||||||
|
|
||||||
|
<h1>Error.</h1>
|
||||||
|
<h2>An error occurred while processing your request.</h2>
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>@ViewBag.Title - My ASP.NET Application</title>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
@Html.ActionLink("InlineConstraintsWebApplication", "Index", "Home", new { area = "" })
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<ul>
|
||||||
|
<li>@Html.ActionLink("Home", "Index", "Home")</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
@RenderBody()
|
||||||
|
<hr />
|
||||||
|
<footer>
|
||||||
|
<p>© 2014 - My ASP.NET Application</p>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"Helios": "0.1-alpha-*",
|
||||||
|
"Microsoft.AspNet.Mvc": "",
|
||||||
|
"Microsoft.Framework.ConfigurationModel.Json": "0.1-alpha-*"
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"net45": { },
|
||||||
|
"k10": { }
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue