Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Commit

Permalink
[Fixes #4043] Figure out ControllerModel.AttributeRoutes
Browse files Browse the repository at this point in the history
  • Loading branch information
kichalla committed Feb 19, 2016
1 parent b557ca5 commit 6e21ab7
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
namespace Microsoft.AspNetCore.Mvc.ApplicationModels
{
[DebuggerDisplay("Name={ControllerName}, Type={ControllerType.Name}," +
" Routes: {AttributeRoutes.Count}, Filters: {Filters.Count}")]
" Route: {AttributeRouteModel?.Template}, Filters: {Filters.Count}")]
public class ControllerModel : ICommonModel, IFilterModel, IApiExplorerModel
{
public ControllerModel(
Expand All @@ -35,7 +35,6 @@ public ControllerModel(
Actions = new List<ActionModel>();
ApiExplorer = new ApiExplorerModel();
Attributes = new List<object>(attributes);
AttributeRoutes = new List<AttributeRouteModel>();
ActionConstraints = new List<IActionConstraintMetadata>();
Filters = new List<IFilterMetadata>();
RouteConstraints = new List<IRouteConstraintProvider>();
Expand Down Expand Up @@ -66,8 +65,7 @@ public ControllerModel(ControllerModel other)
// Make a deep copy of other 'model' types.
Actions = new List<ActionModel>(other.Actions.Select(a => new ActionModel(a)));
ApiExplorer = new ApiExplorerModel(other.ApiExplorer);
AttributeRoutes = new List<AttributeRouteModel>(
other.AttributeRoutes.Select(a => new AttributeRouteModel(a)));
AttributeRouteModel = new AttributeRouteModel(other.AttributeRouteModel);
ControllerProperties =
new List<PropertyModel>(other.ControllerProperties.Select(p => new PropertyModel(p)));
}
Expand All @@ -82,15 +80,15 @@ public ControllerModel(ControllerModel other)
/// <remarks>
/// <see cref="ControllerModel.ApiExplorer"/> allows configuration of settings for ApiExplorer
/// which apply to all actions in the controller unless overridden by <see cref="ActionModel.ApiExplorer"/>.
///
///
/// Settings applied by <see cref="ControllerModel.ApiExplorer"/> override settings from
/// <see cref="ApplicationModel.ApiExplorer"/>.
/// </remarks>
public ApiExplorerModel ApiExplorer { get; set; }

public ApplicationModel Application { get; set; }

public IList<AttributeRouteModel> AttributeRoutes { get; private set; }
public AttributeRouteModel AttributeRouteModel { get; set; }

public IReadOnlyList<object> Attributes { get; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,43 +55,35 @@ public static IList<ControllerActionDescriptor> Build(ApplicationModel applicati
.ToList();
foreach (var action in controller.Actions)
{
// Controllers with multiple [Route] attributes (or user defined implementation of
// IRouteTemplateProvider) will generate one action descriptor per IRouteTemplateProvider
// instance.
// Actions with multiple [Http*] attributes or other (IRouteTemplateProvider implementations
// have already been identified as different actions during action discovery.
var actionDescriptors = CreateActionDescriptors(application, controller, action);

foreach (var actionDescriptor in actionDescriptors)
{
actionDescriptor.ControllerName = controller.ControllerName;
actionDescriptor.ControllerTypeInfo = controller.ControllerType;
var actionDescriptor = CreateActionDescriptor(application, controller, action);

AddApiExplorerInfo(actionDescriptor, application, controller, action);
AddRouteConstraints(removalConstraints, actionDescriptor, controller, action);
AddProperties(actionDescriptor, action, controller, application);
actionDescriptor.ControllerName = controller.ControllerName;
actionDescriptor.ControllerTypeInfo = controller.ControllerType;

actionDescriptor.BoundProperties = controllerPropertyDescriptors;
if (IsAttributeRoutedAction(actionDescriptor))
{
hasAttributeRoutes = true;
AddApiExplorerInfo(actionDescriptor, application, controller, action);
AddRouteConstraints(removalConstraints, actionDescriptor, controller, action);
AddProperties(actionDescriptor, action, controller, application);

actionDescriptor.BoundProperties = controllerPropertyDescriptors;
if (IsAttributeRoutedAction(actionDescriptor))
{
hasAttributeRoutes = true;

// An attribute routed action will ignore conventional routed constraints. We still
// want to provide these values as ambient values for link generation.
AddConstraintsAsDefaultRouteValues(actionDescriptor);
// An attribute routed action will ignore conventional routed constraints. We still
// want to provide these values as ambient values for link generation.
AddConstraintsAsDefaultRouteValues(actionDescriptor);

// Replaces tokens like [controller]/[action] in the route template with the actual values
// for this action.
ReplaceAttributeRouteTokens(actionDescriptor, routeTemplateErrors);
// Replaces tokens like [controller]/[action] in the route template with the actual values
// for this action.
ReplaceAttributeRouteTokens(actionDescriptor, routeTemplateErrors);

// Attribute routed actions will ignore conventional routed constraints. Instead they have
// a single route constraint "RouteGroup" associated with it.
ReplaceRouteConstraints(actionDescriptor);
}
// Attribute routed actions will ignore conventional routed constraints. Instead they have
// a single route constraint "RouteGroup" associated with it.
ReplaceRouteConstraints(actionDescriptor);
}

methodInfoMap.AddToMethodInfo(action, actionDescriptors);
actions.AddRange(actionDescriptors);
methodInfoMap.AddToMethodInfo(action, actionDescriptor);
actions.Add(actionDescriptor);
}
}

Expand Down Expand Up @@ -180,12 +172,12 @@ public static IList<ControllerActionDescriptor> Build(ApplicationModel applicati
return actions;
}

private static IList<ControllerActionDescriptor> CreateActionDescriptors(
private static ControllerActionDescriptor CreateActionDescriptor(
ApplicationModel application,
ControllerModel controller,
ActionModel action)
{
var actionDescriptors = new List<ControllerActionDescriptor>();
ControllerActionDescriptor actionDescriptor;

// We check the action to see if the template allows combination behavior
// (It doesn't start with / or ~/) so that in the case where we have multiple
Expand All @@ -195,12 +187,10 @@ private static IList<ControllerActionDescriptor> CreateActionDescriptors(
{
// We're overriding the attribute routes on the controller, so filter out any metadata
// from controller level routes.
var actionDescriptor = CreateActionDescriptor(
actionDescriptor = CreateActionDescriptor(
action,
controllerAttributeRoute: null);

actionDescriptors.Add(actionDescriptor);

// If we're using an attribute route on the controller, then filter out any additional
// metadata from the 'other' attribute routes.
var controllerFilters = controller.Filters
Expand All @@ -211,44 +201,36 @@ private static IList<ControllerActionDescriptor> CreateActionDescriptors(
.Where(c => !(c is IRouteTemplateProvider));
AddActionConstraints(actionDescriptor, action, controllerConstraints);
}
else if (controller.AttributeRoutes != null &&
controller.AttributeRoutes.Count > 0)
else if (controller.AttributeRouteModel != null)
{
// We're using the attribute routes from the controller
foreach (var controllerAttributeRoute in controller.AttributeRoutes)
{
var actionDescriptor = CreateActionDescriptor(
action,
controllerAttributeRoute);
actionDescriptor = CreateActionDescriptor(
action,
controller.AttributeRouteModel);

actionDescriptors.Add(actionDescriptor);

// If we're using an attribute route on the controller, then filter out any additional
// metadata from the 'other' attribute routes.
var controllerFilters = controller.Filters
.Where(c => c == controllerAttributeRoute?.Attribute || !(c is IRouteTemplateProvider));
AddActionFilters(actionDescriptor, action.Filters, controllerFilters, application.Filters);
// If we're using an attribute route on the controller, then filter out any additional
// metadata from the 'other' attribute routes.
var controllerFilters = controller.Filters
.Where(c => c == controller.AttributeRouteModel?.Attribute || !(c is IRouteTemplateProvider));
AddActionFilters(actionDescriptor, action.Filters, controllerFilters, application.Filters);

var controllerConstraints = controller.ActionConstraints
.Where(c => c == controllerAttributeRoute?.Attribute || !(c is IRouteTemplateProvider));
AddActionConstraints(actionDescriptor, action, controllerConstraints);
}
var controllerConstraints = controller.ActionConstraints
.Where(c => c == controller.AttributeRouteModel?.Attribute || !(c is IRouteTemplateProvider));
AddActionConstraints(actionDescriptor, action, controllerConstraints);
}
else
{
// No attribute routes on the controller
var actionDescriptor = CreateActionDescriptor(
actionDescriptor = CreateActionDescriptor(
action,
controllerAttributeRoute: null);
actionDescriptors.Add(actionDescriptor);

// If there's no attribute route on the controller, then we can use all of the filters/constraints
// on the controller.
AddActionFilters(actionDescriptor, action.Filters, controller.Filters, application.Filters);
AddActionConstraints(actionDescriptor, action, controller.ActionConstraints);
}

return actionDescriptors;
return actionDescriptor;
}

private static ControllerActionDescriptor CreateActionDescriptor(
Expand Down Expand Up @@ -316,15 +298,15 @@ private static void AddApiExplorerInfo(
ControllerModel controller,
ActionModel action)
{
var isVisible =
action.ApiExplorer?.IsVisible ??
controller.ApiExplorer?.IsVisible ??
var isVisible =
action.ApiExplorer?.IsVisible ??
controller.ApiExplorer?.IsVisible ??
application.ApiExplorer?.IsVisible ??
false;

var isVisibleSetOnActionOrController =
action.ApiExplorer?.IsVisible ??
controller.ApiExplorer?.IsVisible ??
var isVisibleSetOnActionOrController =
action.ApiExplorer?.IsVisible ??
controller.ApiExplorer?.IsVisible ??
false;

// ApiExplorer isn't supported on conventional-routed actions, but we still allow you to configure
Expand Down Expand Up @@ -449,7 +431,7 @@ public static void AddRouteConstraints(
ControllerModel controller,
ActionModel action)
{
// Apply all the constraints defined on the action, then controller (for example, [Area])
// Apply all the constraints defined on the action, then controller (for example, [Area])
// to the actions. Also keep track of all the constraints that require preventing actions
// without the constraint to match. For example, actions without an [Area] attribute on their
// controller should not match when a value has been given for area when matching a url or
Expand Down Expand Up @@ -788,17 +770,23 @@ private class MethodToActionMap :
{
public void AddToMethodInfo(
ActionModel action,
IList<ControllerActionDescriptor> actionDescriptors)
ControllerActionDescriptor actionDescriptor)
{
IDictionary<ActionModel, IList<ControllerActionDescriptor>> actionsForMethod = null;
if (TryGetValue(action.ActionMethod, out actionsForMethod))
{
actionsForMethod.Add(action, actionDescriptors);
IList<ControllerActionDescriptor> actionDescriptors;
if (actionsForMethod.TryGetValue(action, out actionDescriptors))
{
actionDescriptors.Add(actionDescriptor);
}
}
else
{
var reflectedActionMap =
new Dictionary<ActionModel, IList<ControllerActionDescriptor>>();
var actionDescriptors = new List<ControllerActionDescriptor>();
actionDescriptors.Add(actionDescriptor);
reflectedActionMap.Add(action, actionDescriptors);
Add(action.ActionMethod, reflectedActionMap);
}
Expand Down
Loading

0 comments on commit 6e21ab7

Please sign in to comment.