Add tests to ApplicationModelTest (#6932)

Addresses #756
This commit is contained in:
Jass Bagga 2017-10-10 11:24:03 -07:00 committed by GitHub
parent 7ba167fcd8
commit b992ef0ced
15 changed files with 170 additions and 2 deletions

View File

@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.10
VisualStudioVersion = 15.0.26831.3000
MinimumVisualStudioVersion = 15.0.26730.03
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{DAAE4C74-D06F-4874-A166-33305D2643CE}"
EndProject

View File

@ -166,5 +166,35 @@ namespace Microsoft.AspNetCore.Mvc.FunctionalTests
// Assert
Assert.Equal("/Home/CannotBeRouted", response.Headers.Location.ToString());
}
[Theory]
[InlineData("Products", "Products View")]
[InlineData("Services", "Services View")]
[InlineData("Manage", "Manage View")]
public async Task ApplicationModel_CanDuplicateController_InMultipleAreas(string areaName, string expectedContent)
{
// Arrange & Act
var response = await Client.GetAsync(areaName + "/MultipleAreas/Index");
var content = await response.Content.ReadAsStringAsync();
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Contains(expectedContent, content);
}
[Theory]
[InlineData("Help", "This is the help page")]
[InlineData("MoreHelp", "This is the more help page")]
public async Task ControllerModel_CanDuplicateActions_RoutesToDifferentNames(string actionName, string expectedContent)
{
// Arrange & Act
var response = await Client.GetAsync("ActionModel/" + actionName);
// Assert
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
var body = await response.Content.ReadAsStringAsync();
Assert.Contains(expectedContent, body);
}
}
}

View File

@ -0,0 +1 @@
Products View

View File

@ -0,0 +1 @@
Services View

View File

@ -17,6 +17,12 @@ namespace ApplicationModelWebSite
return ControllerContext.ActionDescriptor.ActionName;
}
[CloneAction("MoreHelp")]
public IActionResult Help()
{
return View();
}
private class ActionName2Attribute : Attribute, IActionModelConvention
{
private readonly string _actionName;

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
namespace ApplicationModelWebSite
{

View File

@ -0,0 +1,16 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Mvc;
namespace ApplicationModelWebSite.Controllers
{
[MultipleAreas("Products", "Services", "Manage")]
public class MultipleAreasController : Controller
{
public IActionResult Index()
{
return View();
}
}
}

View File

@ -0,0 +1,18 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace ApplicationModelWebSite
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CloneActionAttribute : Attribute
{
public CloneActionAttribute(string newActionName)
{
ActionName = newActionName;
}
public string ActionName { get; private set; }
}
}

View File

@ -0,0 +1,36 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace ApplicationModelWebSite
{
public class CloneActionConvention : IControllerModelConvention
{
public void Apply(ControllerModel controller)
{
var actionModels = new List<ActionModel>();
foreach (var action in controller.Actions)
{
var actionName = action.Attributes.OfType<CloneActionAttribute>()?.FirstOrDefault()?.ActionName;
if (!string.IsNullOrEmpty(actionName))
{
var actionCopy = new ActionModel(action)
{
ActionName = actionName
};
actionModels.Add(actionCopy);
}
}
foreach (var model in actionModels)
{
controller.Actions.Add(model);
}
}
}
}

View File

@ -0,0 +1,19 @@
// Copyright (c) .NET Foundation. 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.Linq;
namespace ApplicationModelWebSite
{
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
public class MultipleAreasAttribute : Attribute
{
public MultipleAreasAttribute(string area1, string area2, params string[] areaNames)
{
AreaNames = new string[] { area1, area2 }.Concat(areaNames).ToArray();
}
public string[] AreaNames { get; }
}
}

View File

@ -0,0 +1,34 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Mvc.ApplicationModels;
namespace ApplicationModelWebSite
{
public class MultipleAreasControllerConvention : IApplicationModelConvention
{
public void Apply(ApplicationModel application)
{
var controllerModels = new List<ControllerModel>();
foreach (var controller in application.Controllers)
{
var areaNames = controller.ControllerType.GetCustomAttributes<MultipleAreasAttribute>()?.FirstOrDefault()?.AreaNames;
controller.RouteValues.Add("area", areaNames?[0]);
for (var i = 1; i < areaNames?.Length; i++)
{
var controllerCopy = new ControllerModel(controller);
controllerCopy.RouteValues["area"] = areaNames[i];
controllerModels.Add(controllerCopy);
}
}
foreach (var model in controllerModels)
{
application.Controllers.Add(model);
}
}
}
}

View File

@ -18,6 +18,8 @@ namespace ApplicationModelWebSite
options.Conventions.Add(new ApplicationDescription("Common Application Description"));
options.Conventions.Add(new ControllerLicenseConvention());
options.Conventions.Add(new FromHeaderConvention());
options.Conventions.Add(new MultipleAreasControllerConvention());
options.Conventions.Add(new CloneActionConvention());
});
}
@ -25,6 +27,9 @@ namespace ApplicationModelWebSite
{
app.UseMvc(routes =>
{
routes.MapRoute(name: "areaRoute",
template: "{area:exists}/{controller=Home}/{action=Index}");
routes.MapRoute(
name: "default",
template: "{controller}/{action}/{id?}");

View File

@ -0,0 +1 @@
This is the help page

View File

@ -0,0 +1 @@
This is the more help page