Refactor I***ModelBuilder extensibility
Combining IControllerModelBuilder and IActionModelBuilder into a pipeline of IApplicationModelBuilders. Extensibility for framework features (Auth, Cors, etc) should implement an IApplicationModelBuilder to add data to models before IApplicationModelConventions have a chance to run. Also deleting IGlobalFilterProvider while touching this code, this should have been removed a while ago when we removed other options facades.
This commit is contained in:
parent
261975b0bc
commit
6cd277e8aa
|
|
@ -0,0 +1,27 @@
|
|||
// 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.Reflection;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||
{
|
||||
/// <summary>
|
||||
/// A context object for <see cref="IApplicationModelProvider"/>.
|
||||
/// </summary>
|
||||
public class ApplicationModelProviderContext
|
||||
{
|
||||
public ApplicationModelProviderContext([NotNull] IEnumerable<TypeInfo> controllerTypes)
|
||||
{
|
||||
ControllerTypes = controllerTypes;
|
||||
}
|
||||
|
||||
public IEnumerable<TypeInfo> ControllerTypes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="ApplicationModel"/>.
|
||||
/// </summary>
|
||||
public ApplicationModel Result { get; } = new ApplicationModel();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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;
|
||||
|
|
@ -6,31 +6,262 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNet.Authorization;
|
||||
using Microsoft.AspNet.Cors;
|
||||
using Microsoft.AspNet.Cors.Core;
|
||||
using Microsoft.AspNet.Mvc.ApiExplorer;
|
||||
using Microsoft.AspNet.Mvc.Filters;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
|
||||
using Microsoft.AspNet.Mvc.Routing;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||
{
|
||||
/// <summary>
|
||||
/// A default implementation of <see cref="IActionModelBuilder"/>.
|
||||
/// </summary>
|
||||
public class DefaultActionModelBuilder : IActionModelBuilder
|
||||
public class DefaultApplicationModelProvider : IApplicationModelProvider
|
||||
{
|
||||
private readonly AuthorizationOptions _authorizationOptions;
|
||||
private readonly ICollection<IFilter> _globalFilters;
|
||||
|
||||
public DefaultActionModelBuilder(IOptions<AuthorizationOptions> authorizationOptions)
|
||||
public DefaultApplicationModelProvider(
|
||||
IOptions<MvcOptions> mvcOptionsAccessor,
|
||||
IOptions<AuthorizationOptions> authorizationOptionsAccessor)
|
||||
{
|
||||
_authorizationOptions = authorizationOptions?.Options ?? new AuthorizationOptions();
|
||||
_globalFilters = mvcOptionsAccessor.Options.Filters;
|
||||
_authorizationOptions = authorizationOptionsAccessor.Options;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<ActionModel> BuildActionModels([NotNull] TypeInfo typeInfo, [NotNull] MethodInfo methodInfo)
|
||||
public int Order
|
||||
{
|
||||
get
|
||||
{
|
||||
return DefaultOrder.DefaultFrameworkSortOrder;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void OnProvidersExecuting([NotNull] ApplicationModelProviderContext context)
|
||||
{
|
||||
foreach (var filter in _globalFilters)
|
||||
{
|
||||
context.Result.Filters.Add(filter);
|
||||
}
|
||||
|
||||
foreach (var controllerType in context.ControllerTypes)
|
||||
{
|
||||
var controllerModels = BuildControllerModels(controllerType);
|
||||
if (controllerModels != null)
|
||||
{
|
||||
foreach (var controllerModel in controllerModels)
|
||||
{
|
||||
context.Result.Controllers.Add(controllerModel);
|
||||
controllerModel.Application = context.Result;
|
||||
|
||||
foreach (var propertyHelper in PropertyHelper.GetProperties(controllerType.AsType()))
|
||||
{
|
||||
var propertyInfo = propertyHelper.Property;
|
||||
var propertyModel = CreatePropertyModel(propertyInfo);
|
||||
if (propertyModel != null)
|
||||
{
|
||||
propertyModel.Controller = controllerModel;
|
||||
controllerModel.ControllerProperties.Add(propertyModel);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var methodInfo in controllerType.AsType().GetMethods())
|
||||
{
|
||||
var actionModels = BuildActionModels(controllerType, methodInfo);
|
||||
if (actionModels != null)
|
||||
{
|
||||
foreach (var actionModel in actionModels)
|
||||
{
|
||||
actionModel.Controller = controllerModel;
|
||||
controllerModel.Actions.Add(actionModel);
|
||||
|
||||
foreach (var parameterInfo in actionModel.ActionMethod.GetParameters())
|
||||
{
|
||||
var parameterModel = CreateParameterModel(parameterInfo);
|
||||
if (parameterModel != null)
|
||||
{
|
||||
parameterModel.Action = actionModel;
|
||||
actionModel.Parameters.Add(parameterModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void OnProvidersExecuted([NotNull] ApplicationModelProviderContext context)
|
||||
{
|
||||
// Intentionally empty.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the <see cref="ControllerModel"/> instances for the given controller <see cref="TypeInfo"/>.
|
||||
/// </summary>
|
||||
/// <param name="typeInfo">The controller <see cref="TypeInfo"/>.</param>
|
||||
/// <returns>
|
||||
/// A set of <see cref="ControllerModel"/> instances for the given controller <see cref="TypeInfo"/> or
|
||||
/// <c>null</c> if the <paramref name="typeInfo"/> does not represent a controller.
|
||||
/// </returns>
|
||||
protected virtual IEnumerable<ControllerModel> BuildControllerModels([NotNull] TypeInfo typeInfo)
|
||||
{
|
||||
var controllerModel = CreateControllerModel(typeInfo);
|
||||
yield return controllerModel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ControllerModel"/> for the given <see cref="TypeInfo"/>.
|
||||
/// </summary>
|
||||
/// <param name="typeInfo">The <see cref="TypeInfo"/>.</param>
|
||||
/// <returns>A <see cref="ControllerModel"/> for the given <see cref="TypeInfo"/>.</returns>
|
||||
protected virtual ControllerModel CreateControllerModel([NotNull] TypeInfo typeInfo)
|
||||
{
|
||||
// For attribute routes on a controller, we want want to support 'overriding' routes on a derived
|
||||
// class. So we need to walk up the hierarchy looking for the first class to define routes.
|
||||
//
|
||||
// Then we want to 'filter' the set of attributes, so that only the effective routes apply.
|
||||
var currentTypeInfo = typeInfo;
|
||||
var objectTypeInfo = typeof(object).GetTypeInfo();
|
||||
|
||||
IRouteTemplateProvider[] routeAttributes = null;
|
||||
|
||||
do
|
||||
{
|
||||
routeAttributes = currentTypeInfo
|
||||
.GetCustomAttributes(inherit: false)
|
||||
.OfType<IRouteTemplateProvider>()
|
||||
.ToArray();
|
||||
|
||||
if (routeAttributes.Length > 0)
|
||||
{
|
||||
// Found 1 or more route attributes.
|
||||
break;
|
||||
}
|
||||
|
||||
currentTypeInfo = currentTypeInfo.BaseType.GetTypeInfo();
|
||||
}
|
||||
while (currentTypeInfo != objectTypeInfo);
|
||||
|
||||
// CoreCLR returns IEnumerable<Attribute> from GetCustomAttributes - the OfType<object>
|
||||
// is needed to so that the result of ToArray() is object
|
||||
var attributes = typeInfo.GetCustomAttributes(inherit: true).OfType<object>().ToArray();
|
||||
|
||||
// This is fairly complicated so that we maintain referential equality between items in
|
||||
// ControllerModel.Attributes and ControllerModel.Attributes[*].Attribute.
|
||||
var filteredAttributes = new List<object>();
|
||||
foreach (var attribute in attributes)
|
||||
{
|
||||
if (attribute is IRouteTemplateProvider)
|
||||
{
|
||||
// This attribute is a route-attribute, leave it out.
|
||||
}
|
||||
else
|
||||
{
|
||||
filteredAttributes.Add(attribute);
|
||||
}
|
||||
}
|
||||
filteredAttributes.AddRange(routeAttributes);
|
||||
|
||||
attributes = filteredAttributes.ToArray();
|
||||
|
||||
var controllerModel = new ControllerModel(typeInfo, attributes);
|
||||
AddRange(
|
||||
controllerModel.AttributeRoutes, routeAttributes.Select(a => new AttributeRouteModel(a)));
|
||||
|
||||
controllerModel.ControllerName =
|
||||
typeInfo.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) ?
|
||||
typeInfo.Name.Substring(0, typeInfo.Name.Length - "Controller".Length) :
|
||||
typeInfo.Name;
|
||||
|
||||
AddRange(controllerModel.ActionConstraints, attributes.OfType<IActionConstraintMetadata>());
|
||||
AddRange(controllerModel.Filters, attributes.OfType<IFilter>());
|
||||
AddRange(controllerModel.RouteConstraints, attributes.OfType<IRouteConstraintProvider>());
|
||||
|
||||
var enableCors = attributes.OfType<IEnableCorsAttribute>().SingleOrDefault();
|
||||
if (enableCors != null)
|
||||
{
|
||||
controllerModel.Filters.Add(new CorsAuthorizationFilterFactory(enableCors.PolicyName));
|
||||
}
|
||||
|
||||
var disableCors = attributes.OfType<IDisableCorsAttribute>().SingleOrDefault();
|
||||
if (disableCors != null)
|
||||
{
|
||||
controllerModel.Filters.Add(new DisableCorsAuthorizationFilter());
|
||||
}
|
||||
|
||||
var policy = AuthorizationPolicy.Combine(_authorizationOptions, attributes.OfType<AuthorizeAttribute>());
|
||||
if (policy != null)
|
||||
{
|
||||
controllerModel.Filters.Add(new AuthorizeFilter(policy));
|
||||
}
|
||||
|
||||
var apiVisibility = attributes.OfType<IApiDescriptionVisibilityProvider>().FirstOrDefault();
|
||||
if (apiVisibility != null)
|
||||
{
|
||||
controllerModel.ApiExplorer.IsVisible = !apiVisibility.IgnoreApi;
|
||||
}
|
||||
|
||||
var apiGroupName = attributes.OfType<IApiDescriptionGroupNameProvider>().FirstOrDefault();
|
||||
if (apiGroupName != null)
|
||||
{
|
||||
controllerModel.ApiExplorer.GroupName = apiGroupName.GroupName;
|
||||
}
|
||||
|
||||
// Controllers can implement action filter and result filter interfaces. We add
|
||||
// a special delegating filter implementation to the pipeline to handle it.
|
||||
//
|
||||
// This is needed because filters are instantiated before the controller.
|
||||
if (typeof(IAsyncActionFilter).GetTypeInfo().IsAssignableFrom(typeInfo) ||
|
||||
typeof(IActionFilter).GetTypeInfo().IsAssignableFrom(typeInfo))
|
||||
{
|
||||
controllerModel.Filters.Add(new ControllerActionFilter());
|
||||
}
|
||||
if (typeof(IAsyncResultFilter).GetTypeInfo().IsAssignableFrom(typeInfo) ||
|
||||
typeof(IResultFilter).GetTypeInfo().IsAssignableFrom(typeInfo))
|
||||
{
|
||||
controllerModel.Filters.Add(new ControllerResultFilter());
|
||||
}
|
||||
|
||||
return controllerModel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="PropertyModel"/> for the given <see cref="PropertyInfo"/>.
|
||||
/// </summary>
|
||||
/// <param name="propertyInfo">The <see cref="PropertyInfo"/>.</param>
|
||||
/// <returns>A <see cref="PropertyModel"/> for the given <see cref="PropertyInfo"/>.</returns>
|
||||
protected virtual PropertyModel CreatePropertyModel([NotNull] PropertyInfo propertyInfo)
|
||||
{
|
||||
// CoreCLR returns IEnumerable<Attribute> from GetCustomAttributes - the OfType<object>
|
||||
// is needed to so that the result of ToArray() is object
|
||||
var attributes = propertyInfo.GetCustomAttributes(inherit: true).OfType<object>().ToArray();
|
||||
var propertyModel = new PropertyModel(propertyInfo, attributes);
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(attributes);
|
||||
|
||||
propertyModel.BindingInfo = bindingInfo;
|
||||
propertyModel.PropertyName = propertyInfo.Name;
|
||||
|
||||
return propertyModel;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates the <see cref="ControllerModel"/> instances for the given action <see cref="MethodInfo"/>.
|
||||
/// </summary>
|
||||
/// <param name="typeInfo">The controller <see cref="TypeInfo"/>.</param>
|
||||
/// <param name="methodInfo">The action <see cref="MethodInfo"/>.</param>
|
||||
/// <returns>
|
||||
/// A set of <see cref="ActionModel"/> instances for the given action <see cref="MethodInfo"/> or
|
||||
/// <c>null</c> if the <paramref name="methodInfo"/> does not represent an action.
|
||||
/// </returns>
|
||||
protected virtual IEnumerable<ActionModel> BuildActionModels(
|
||||
[NotNull] TypeInfo typeInfo,
|
||||
[NotNull] MethodInfo methodInfo)
|
||||
{
|
||||
if (!IsAction(typeInfo, methodInfo))
|
||||
{
|
||||
|
|
@ -214,19 +445,6 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
}
|
||||
|
||||
foreach (var actionModel in actionModels)
|
||||
{
|
||||
foreach (var parameterInfo in actionModel.ActionMethod.GetParameters())
|
||||
{
|
||||
var parameterModel = CreateParameterModel(parameterInfo);
|
||||
if (parameterModel != null)
|
||||
{
|
||||
parameterModel.Action = actionModel;
|
||||
actionModel.Parameters.Add(parameterModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return actionModels;
|
||||
}
|
||||
|
||||
|
|
@ -285,15 +503,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
return false;
|
||||
}
|
||||
|
||||
return
|
||||
methodInfo.IsPublic;
|
||||
}
|
||||
|
||||
private bool IsIDisposableMethod(MethodInfo methodInfo, TypeInfo typeInfo)
|
||||
{
|
||||
return
|
||||
(typeof(IDisposable).GetTypeInfo().IsAssignableFrom(typeInfo) &&
|
||||
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0] == methodInfo);
|
||||
return methodInfo.IsPublic;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -402,6 +612,13 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
return parameterModel;
|
||||
}
|
||||
|
||||
private bool IsIDisposableMethod(MethodInfo methodInfo, TypeInfo typeInfo)
|
||||
{
|
||||
return
|
||||
(typeof(IDisposable).GetTypeInfo().IsAssignableFrom(typeInfo) &&
|
||||
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0] == methodInfo);
|
||||
}
|
||||
|
||||
private bool IsSilentRouteAttribute(IRouteTemplateProvider routeTemplateProvider)
|
||||
{
|
||||
return
|
||||
|
|
@ -1,215 +0,0 @@
|
|||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNet.Mvc.ApiExplorer;
|
||||
using Microsoft.AspNet.Authorization;
|
||||
using Microsoft.AspNet.Cors.Core;
|
||||
using Microsoft.AspNet.Mvc.Filters;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.AspNet.Mvc.Routing;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||
{
|
||||
/// <summary>
|
||||
/// A default implementation of <see cref="IControllerModelBuilder"/>.
|
||||
/// </summary>
|
||||
public class DefaultControllerModelBuilder : IControllerModelBuilder
|
||||
{
|
||||
private readonly IActionModelBuilder _actionModelBuilder;
|
||||
private readonly AuthorizationOptions _authorizationOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="DefaultControllerModelBuilder"/>.
|
||||
/// </summary>
|
||||
/// <param name="actionModelBuilder">The <see cref="IActionModelBuilder"/> used to create actions.</param>
|
||||
public DefaultControllerModelBuilder(
|
||||
IActionModelBuilder actionModelBuilder,
|
||||
IOptions<AuthorizationOptions> authorizationOptions)
|
||||
{
|
||||
_actionModelBuilder = actionModelBuilder;
|
||||
_authorizationOptions = authorizationOptions?.Options ?? new AuthorizationOptions();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ControllerModel BuildControllerModel([NotNull] TypeInfo typeInfo)
|
||||
{
|
||||
var controllerModel = CreateControllerModel(typeInfo);
|
||||
var controllerType = typeInfo.AsType();
|
||||
|
||||
foreach (var methodInfo in controllerType.GetMethods())
|
||||
{
|
||||
var actionModels = _actionModelBuilder.BuildActionModels(typeInfo, methodInfo);
|
||||
if (actionModels != null)
|
||||
{
|
||||
foreach (var actionModel in actionModels)
|
||||
{
|
||||
actionModel.Controller = controllerModel;
|
||||
controllerModel.Actions.Add(actionModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var propertyHelper in PropertyHelper.GetProperties(controllerType))
|
||||
{
|
||||
var propertyInfo = propertyHelper.Property;
|
||||
var propertyModel = CreatePropertyModel(propertyInfo);
|
||||
if (propertyModel != null)
|
||||
{
|
||||
propertyModel.Controller = controllerModel;
|
||||
controllerModel.ControllerProperties.Add(propertyModel);
|
||||
}
|
||||
}
|
||||
|
||||
return controllerModel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="ControllerModel"/> for the given <see cref="TypeInfo"/>.
|
||||
/// </summary>
|
||||
/// <param name="typeInfo">The <see cref="TypeInfo"/>.</param>
|
||||
/// <returns>A <see cref="ControllerModel"/> for the given <see cref="TypeInfo"/>.</returns>
|
||||
protected virtual ControllerModel CreateControllerModel([NotNull] TypeInfo typeInfo)
|
||||
{
|
||||
// For attribute routes on a controller, we want want to support 'overriding' routes on a derived
|
||||
// class. So we need to walk up the hierarchy looking for the first class to define routes.
|
||||
//
|
||||
// Then we want to 'filter' the set of attributes, so that only the effective routes apply.
|
||||
var currentTypeInfo = typeInfo;
|
||||
var objectTypeInfo = typeof(object).GetTypeInfo();
|
||||
|
||||
IRouteTemplateProvider[] routeAttributes = null;
|
||||
|
||||
do
|
||||
{
|
||||
routeAttributes = currentTypeInfo
|
||||
.GetCustomAttributes(inherit: false)
|
||||
.OfType<IRouteTemplateProvider>()
|
||||
.ToArray();
|
||||
|
||||
if (routeAttributes.Length > 0)
|
||||
{
|
||||
// Found 1 or more route attributes.
|
||||
break;
|
||||
}
|
||||
|
||||
currentTypeInfo = currentTypeInfo.BaseType.GetTypeInfo();
|
||||
}
|
||||
while (currentTypeInfo != objectTypeInfo);
|
||||
|
||||
// CoreCLR returns IEnumerable<Attribute> from GetCustomAttributes - the OfType<object>
|
||||
// is needed to so that the result of ToArray() is object
|
||||
var attributes = typeInfo.GetCustomAttributes(inherit: true).OfType<object>().ToArray();
|
||||
|
||||
// This is fairly complicated so that we maintain referential equality between items in
|
||||
// ControllerModel.Attributes and ControllerModel.Attributes[*].Attribute.
|
||||
var filteredAttributes = new List<object>();
|
||||
foreach (var attribute in attributes)
|
||||
{
|
||||
if (attribute is IRouteTemplateProvider)
|
||||
{
|
||||
// This attribute is a route-attribute, leave it out.
|
||||
}
|
||||
else
|
||||
{
|
||||
filteredAttributes.Add(attribute);
|
||||
}
|
||||
}
|
||||
filteredAttributes.AddRange(routeAttributes);
|
||||
|
||||
attributes = filteredAttributes.ToArray();
|
||||
|
||||
var controllerModel = new ControllerModel(typeInfo, attributes);
|
||||
AddRange(
|
||||
controllerModel.AttributeRoutes, routeAttributes.Select(a => new AttributeRouteModel(a)));
|
||||
|
||||
controllerModel.ControllerName =
|
||||
typeInfo.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) ?
|
||||
typeInfo.Name.Substring(0, typeInfo.Name.Length - "Controller".Length) :
|
||||
typeInfo.Name;
|
||||
|
||||
AddRange(controllerModel.ActionConstraints, attributes.OfType<IActionConstraintMetadata>());
|
||||
AddRange(controllerModel.Filters, attributes.OfType<IFilter>());
|
||||
AddRange(controllerModel.RouteConstraints, attributes.OfType<IRouteConstraintProvider>());
|
||||
|
||||
var enableCors = attributes.OfType<IEnableCorsAttribute>().SingleOrDefault();
|
||||
if (enableCors != null)
|
||||
{
|
||||
controllerModel.Filters.Add(new CorsAuthorizationFilterFactory(enableCors.PolicyName));
|
||||
}
|
||||
|
||||
var disableCors = attributes.OfType<IDisableCorsAttribute>().SingleOrDefault();
|
||||
if (disableCors != null)
|
||||
{
|
||||
controllerModel.Filters.Add(new DisableCorsAuthorizationFilter());
|
||||
}
|
||||
|
||||
var policy = AuthorizationPolicy.Combine(_authorizationOptions, attributes.OfType<AuthorizeAttribute>());
|
||||
if (policy != null)
|
||||
{
|
||||
controllerModel.Filters.Add(new AuthorizeFilter(policy));
|
||||
}
|
||||
|
||||
var apiVisibility = attributes.OfType<IApiDescriptionVisibilityProvider>().FirstOrDefault();
|
||||
if (apiVisibility != null)
|
||||
{
|
||||
controllerModel.ApiExplorer.IsVisible = !apiVisibility.IgnoreApi;
|
||||
}
|
||||
|
||||
var apiGroupName = attributes.OfType<IApiDescriptionGroupNameProvider>().FirstOrDefault();
|
||||
if (apiGroupName != null)
|
||||
{
|
||||
controllerModel.ApiExplorer.GroupName = apiGroupName.GroupName;
|
||||
}
|
||||
|
||||
// Controllers can implement action filter and result filter interfaces. We add
|
||||
// a special delegating filter implementation to the pipeline to handle it.
|
||||
//
|
||||
// This is needed because filters are instantiated before the controller.
|
||||
if (typeof(IAsyncActionFilter).GetTypeInfo().IsAssignableFrom(typeInfo) ||
|
||||
typeof(IActionFilter).GetTypeInfo().IsAssignableFrom(typeInfo))
|
||||
{
|
||||
controllerModel.Filters.Add(new ControllerActionFilter());
|
||||
}
|
||||
if (typeof(IAsyncResultFilter).GetTypeInfo().IsAssignableFrom(typeInfo) ||
|
||||
typeof(IResultFilter).GetTypeInfo().IsAssignableFrom(typeInfo))
|
||||
{
|
||||
controllerModel.Filters.Add(new ControllerResultFilter());
|
||||
}
|
||||
|
||||
return controllerModel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="PropertyModel"/> for the given <see cref="PropertyInfo"/>.
|
||||
/// </summary>
|
||||
/// <param name="propertyInfo">The <see cref="PropertyInfo"/>.</param>
|
||||
/// <returns>A <see cref="PropertyModel"/> for the given <see cref="PropertyInfo"/>.</returns>
|
||||
protected virtual PropertyModel CreatePropertyModel([NotNull] PropertyInfo propertyInfo)
|
||||
{
|
||||
// CoreCLR returns IEnumerable<Attribute> from GetCustomAttributes - the OfType<object>
|
||||
// is needed to so that the result of ToArray() is object
|
||||
var attributes = propertyInfo.GetCustomAttributes(inherit: true).OfType<object>().ToArray();
|
||||
var propertyModel = new PropertyModel(propertyInfo, attributes);
|
||||
var bindingInfo = BindingInfo.GetBindingInfo(attributes);
|
||||
|
||||
propertyModel.BindingInfo = bindingInfo;
|
||||
propertyModel.PropertyName = propertyInfo.Name;
|
||||
|
||||
return propertyModel;
|
||||
}
|
||||
|
||||
private static void AddRange<T>(IList<T> list, IEnumerable<T> items)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
// 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.Reflection;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a set of <see cref="ActionModel"/> for a method.
|
||||
/// </summary>
|
||||
public interface IActionModelBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a set of <see cref="ActionModel"/> for a method. May return null or empty if
|
||||
/// <paramref name="methodInfo"/> is not an action method.
|
||||
/// </summary>
|
||||
/// <param name="methodInfo">The <see cref="MethodInfo"/>.</param>
|
||||
/// <param name="typeInfo">The <see cref="TypeInfo"/>.</param>
|
||||
/// <returns>A set of <see cref="ActionModel"/> or null.</returns>
|
||||
/// <remarks>
|
||||
/// Instances of <see cref="ActionModel"/> returned from this interface should have their
|
||||
/// <see cref="ActionModel.Parameters"/> initialized.
|
||||
/// </remarks>
|
||||
IEnumerable<ActionModel> BuildActionModels([NotNull] TypeInfo typeInfo, [NotNull] MethodInfo methodInfo);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
// 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.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||
{
|
||||
/// <summary>
|
||||
/// Builds or modifies an <see cref="ApplicationModel"/> for action discovery.
|
||||
/// </summary>
|
||||
public interface IApplicationModelProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the order value for determining the order of execution of providers. Providers execute in
|
||||
/// ascending numeric value of the <see cref="Order"/> property.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Providers are executed in an ordering determined by an ascending sort of the <see cref="Order"/> property.
|
||||
/// A provider with a lower numeric value of <see cref="Order"/> will have its
|
||||
/// <see cref="OnProvidersExecuting"/> called before that of a provider with a higher numeric value of
|
||||
/// <see cref="Order"/>. The <see cref="OnProvidersExecuted"/> method is called in the reverse ordering after
|
||||
/// all calls to <see cref="OnProvidersExecuting"/>. A provider with a lower numeric value of
|
||||
/// <see cref="Order"/> will have its <see cref="OnProvidersExecuted"/> method called after that of a provider
|
||||
/// with a higher numeric value of <see cref="Order"/>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If two providers have the same numeric value of <see cref="Order"/>, then their relative execution order
|
||||
/// is undefined.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
int Order { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Executed for the first pass of <see cref="ApplicationModel"/> building. See <see cref="Order"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="ApplicationModelProviderContext"/>.</param>
|
||||
void OnProvidersExecuting([NotNull] ApplicationModelProviderContext context);
|
||||
|
||||
/// <summary>
|
||||
/// Executed for the second pass of <see cref="ApplicationModel"/> building. See <see cref="Order"/>.
|
||||
/// </summary>
|
||||
/// <param name="context">The <see cref="ApplicationModelProviderContext"/>.</param>
|
||||
void OnProvidersExecuted([NotNull] ApplicationModelProviderContext context);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
// 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.Reflection;
|
||||
using Microsoft.Framework.Internal;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a set of <see cref="ControllerModel"/> for a type.
|
||||
/// </summary>
|
||||
public interface IControllerModelBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a set of <see cref="ControllerModel"/> for a type. May return null or empty if
|
||||
/// <paramref name="typeInfo"/> is not a controller type.
|
||||
/// </summary>
|
||||
/// <param name="typeInfo">The <see cref="TypeInfo"/>.</param>
|
||||
/// <returns>A <see cref="ControllerModel"/> or null.</returns>
|
||||
/// <remarks>
|
||||
/// Instances of <see cref="ControllerModel"/> returned from this interface should have their
|
||||
/// <see cref="ControllerModel.Actions"/> initialized.
|
||||
/// </remarks>
|
||||
ControllerModel BuildControllerModel([NotNull] TypeInfo typeInfo);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,8 +2,8 @@
|
|||
// 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.AspNet.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNet.Mvc.Filters;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
|
|
@ -11,19 +11,17 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
{
|
||||
public class ControllerActionDescriptorProvider : IActionDescriptorProvider
|
||||
{
|
||||
private readonly IControllerModelBuilder _applicationModelBuilder;
|
||||
private readonly IApplicationModelProvider[] _applicationModelProviders;
|
||||
private readonly IControllerTypeProvider _controllerTypeProvider;
|
||||
private readonly IReadOnlyList<IFilter> _globalFilters;
|
||||
private readonly IEnumerable<IApplicationModelConvention> _conventions;
|
||||
|
||||
public ControllerActionDescriptorProvider([NotNull] IControllerTypeProvider controllerTypeProvider,
|
||||
[NotNull] IControllerModelBuilder applicationModelBuilder,
|
||||
[NotNull] IGlobalFilterProvider globalFilters,
|
||||
[NotNull] IOptions<MvcOptions> optionsAccessor)
|
||||
public ControllerActionDescriptorProvider(
|
||||
[NotNull] IControllerTypeProvider controllerTypeProvider,
|
||||
[NotNull] IEnumerable<IApplicationModelProvider> applicationModelProviders,
|
||||
[NotNull] IOptions<MvcOptions> optionsAccessor)
|
||||
{
|
||||
_controllerTypeProvider = controllerTypeProvider;
|
||||
_applicationModelBuilder = applicationModelBuilder;
|
||||
_globalFilters = globalFilters.Filters;
|
||||
_applicationModelProviders = applicationModelProviders.OrderBy(p => p.Order).ToArray();
|
||||
_conventions = optionsAccessor.Options.Conventions;
|
||||
}
|
||||
|
||||
|
|
@ -55,23 +53,20 @@ namespace Microsoft.AspNet.Mvc.Core
|
|||
|
||||
internal protected ApplicationModel BuildModel()
|
||||
{
|
||||
var applicationModel = new ApplicationModel();
|
||||
foreach (var filter in _globalFilters)
|
||||
var controllerTypes = _controllerTypeProvider.ControllerTypes;
|
||||
var context = new ApplicationModelProviderContext(controllerTypes);
|
||||
|
||||
for (var i = 0; i < _applicationModelProviders.Length; i++)
|
||||
{
|
||||
applicationModel.Filters.Add(filter);
|
||||
_applicationModelProviders[i].OnProvidersExecuting(context);
|
||||
}
|
||||
|
||||
foreach (var type in _controllerTypeProvider.ControllerTypes)
|
||||
for (var i = _applicationModelProviders.Length - 1 ; i >= 0; i--)
|
||||
{
|
||||
var controllerModel = _applicationModelBuilder.BuildControllerModel(type);
|
||||
if (controllerModel != null)
|
||||
{
|
||||
controllerModel.Application = applicationModel;
|
||||
applicationModel.Controllers.Add(controllerModel);
|
||||
}
|
||||
_applicationModelProviders[i].OnProvidersExecuted(context);
|
||||
}
|
||||
|
||||
return applicationModel;
|
||||
return context.Result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
// 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.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// An implementation of <see cref="IGlobalFilterProvider"/> based on <see cref="MvcOptions"/>.
|
||||
/// </summary>
|
||||
public class DefaultGlobalFilterProvider : IGlobalFilterProvider
|
||||
{
|
||||
private readonly IReadOnlyList<IFilter> _filters;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="DefaultGlobalFilterProvider"/>.
|
||||
/// </summary>
|
||||
/// <param name="optionsAccessor">The options accessor for <see cref="MvcOptions"/>.</param>
|
||||
public DefaultGlobalFilterProvider(IOptions<MvcOptions> optionsAccessor)
|
||||
{
|
||||
var filters = optionsAccessor.Options.Filters;
|
||||
_filters = filters.ToList();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<IFilter> Filters
|
||||
{
|
||||
get
|
||||
{
|
||||
return _filters;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Filters
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides access to the collection of <see cref="IFilter"/> for globally registered filters.
|
||||
/// </summary>
|
||||
public interface IGlobalFilterProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the collection of <see cref="IFilter"/>.
|
||||
/// </summary>
|
||||
IReadOnlyList<IFilter> Filters { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -116,10 +116,8 @@ namespace Microsoft.Framework.DependencyInjection
|
|||
|
||||
// Core action discovery, filters and action execution.
|
||||
|
||||
// These are consumed only when creating action descriptors, then they can be de-allocated
|
||||
services.TryAdd(ServiceDescriptor.Transient<IControllerTypeProvider, DefaultControllerTypeProvider>());
|
||||
services.TryAdd(ServiceDescriptor.Transient<IControllerModelBuilder, DefaultControllerModelBuilder>());
|
||||
services.TryAdd(ServiceDescriptor.Transient<IActionModelBuilder, DefaultActionModelBuilder>());
|
||||
// This are consumed only when creating action descriptors, then they can be de-allocated
|
||||
services.TryAdd(ServiceDescriptor.Transient<IControllerTypeProvider, DefaultControllerTypeProvider>());;
|
||||
|
||||
// This has a cache, so it needs to be a singleton
|
||||
services.TryAdd(ServiceDescriptor.Singleton<IControllerFactory, DefaultControllerFactory>());
|
||||
|
|
@ -155,12 +153,12 @@ namespace Microsoft.Framework.DependencyInjection
|
|||
services.TryAdd(ServiceDescriptor
|
||||
.Singleton<IActionDescriptorsCollectionProvider, DefaultActionDescriptorsCollectionProvider>());
|
||||
|
||||
// The IGlobalFilterProvider is used to build the action descriptors (likely once) and so should
|
||||
// remain transient to avoid keeping it in memory.
|
||||
services.TryAdd(ServiceDescriptor.Transient<IGlobalFilterProvider, DefaultGlobalFilterProvider>());
|
||||
// multiple registration service
|
||||
services.AddTransient<IFilterProvider, DefaultFilterProvider>();
|
||||
|
||||
// multiple registration service
|
||||
services.AddTransient<IApplicationModelProvider, DefaultApplicationModelProvider>();
|
||||
|
||||
services.TryAdd(ServiceDescriptor.Transient<FormatFilter, FormatFilter>());
|
||||
services.TryAdd(ServiceDescriptor.Transient<CorsAuthorizationFilter, CorsAuthorizationFilter>());
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,190 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Authorization;
|
||||
using Microsoft.AspNet.Cors.Core;
|
||||
using Microsoft.AspNet.Mvc.Filters;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||
{
|
||||
public class DefaultActionModelBuilderTest
|
||||
public class DefaultApplicationModelProviderTest
|
||||
{
|
||||
[Fact]
|
||||
public void CreateControllerModel_DerivedFromControllerClass_HasFilter()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(StoreController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.CreateControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
var filter = Assert.Single(model.Filters);
|
||||
Assert.IsType<ControllerActionFilter>(filter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateControllerModel_AuthorizeAttributeAddsAuthorizeFilter()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(AccountController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.CreateControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.True(model.Filters.Any(f => f is AuthorizeFilter));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateControllerModel_EnableCorsAttributeAddsCorsAuthorizationFilterFactory()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(CorsController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.CreateControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.Single(model.Filters, f => f is CorsAuthorizationFilterFactory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void OnProvidersExecuting_AddsControllerProperties()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(ModelBinderController).GetTypeInfo();
|
||||
|
||||
var context = new ApplicationModelProviderContext(new[] { typeInfo });
|
||||
|
||||
// Act
|
||||
builder.OnProvidersExecuting(context);
|
||||
|
||||
// Assert
|
||||
var model = Assert.Single(context.Result.Controllers);
|
||||
Assert.Equal(2, model.ControllerProperties.Count);
|
||||
Assert.Equal("Bound", model.ControllerProperties[0].PropertyName);
|
||||
Assert.Equal(BindingSource.Query, model.ControllerProperties[0].BindingInfo.BindingSource);
|
||||
Assert.NotNull(model.ControllerProperties[0].Controller);
|
||||
var attribute = Assert.Single(model.ControllerProperties[0].Attributes);
|
||||
Assert.IsType<FromQueryAttribute>(attribute);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateControllerModel_DisableCorsAttributeAddsDisableCorsAuthorizationFilter()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(DisableCorsController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.CreateControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.True(model.Filters.Any(f => f is DisableCorsAuthorizationFilter));
|
||||
}
|
||||
|
||||
// This class has a filter attribute, but doesn't implement any filter interfaces,
|
||||
// so ControllerFilter is not present.
|
||||
[Fact]
|
||||
public void CreateControllerModel_ClassWithoutFilterInterfaces_HasNoControllerFilter()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(NoFiltersController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.CreateControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
var filter = Assert.Single(model.Filters);
|
||||
Assert.IsType<ProducesAttribute>(filter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateControllerModel_ClassWithFilterInterfaces_HasFilter()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(SomeFiltersController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.CreateControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.Single(model.Filters, f => f is ControllerActionFilter);
|
||||
Assert.Single(model.Filters, f => f is ControllerResultFilter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateControllerModel_ClassWithFilterInterfaces_UnsupportedType()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(UnsupportedFiltersController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.CreateControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(model.Filters);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateControllerModel_ClassWithInheritedRoutes()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(DerivedClassInheritingRoutesController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.CreateControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, model.AttributeRoutes.Count);
|
||||
Assert.Equal(2, model.Attributes.Count);
|
||||
|
||||
var route = Assert.Single(model.AttributeRoutes, r => r.Template == "A");
|
||||
Assert.Contains(route.Attribute, model.Attributes);
|
||||
|
||||
route = Assert.Single(model.AttributeRoutes, r => r.Template == "B");
|
||||
Assert.Contains(route.Attribute, model.Attributes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CreateControllerModel_ClassWithHiddenInheritedRoutes()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(DerivedClassHidingRoutesController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.CreateControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, model.AttributeRoutes.Count);
|
||||
Assert.Equal(2, model.Attributes.Count);
|
||||
|
||||
var route = Assert.Single(model.AttributeRoutes, r => r.Template == "C");
|
||||
Assert.Contains(route.Attribute, model.Attributes);
|
||||
|
||||
route = Assert.Single(model.AttributeRoutes, r => r.Template == "D");
|
||||
Assert.Contains(route.Attribute, model.Attributes);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("GetFromDerived", true)]
|
||||
[InlineData("NewMethod", true)] // "NewMethod" is a public method declared with keyword "new".
|
||||
|
|
@ -23,7 +192,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void IsAction_WithInheritedMethods(string methodName, bool expected)
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestAccessibleActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var method = typeof(DerivedController).GetMethod(methodName);
|
||||
Assert.NotNull(method);
|
||||
|
||||
|
|
@ -38,7 +207,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void IsAction_OverridenMethodControllerClass()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestAccessibleActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var method = typeof(BaseController).GetMethod(nameof(BaseController.Redirect));
|
||||
Assert.NotNull(method);
|
||||
|
||||
|
|
@ -53,7 +222,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void IsAction_PrivateMethod_FromUserDefinedController()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestAccessibleActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var method = typeof(DerivedController).GetMethod(
|
||||
"PrivateMethod",
|
||||
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
|
|
@ -70,7 +239,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void IsAction_OperatorOverloadingMethod_FromOperatorOverloadingController()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestAccessibleActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var method = typeof(OperatorOverloadingController).GetMethod("op_Addition");
|
||||
Assert.NotNull(method);
|
||||
Assert.True(method.IsSpecialName);
|
||||
|
|
@ -86,7 +255,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void IsAction_GenericMethod_FromUserDefinedController()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestAccessibleActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var method = typeof(DerivedController).GetMethod("GenericMethod");
|
||||
Assert.NotNull(method);
|
||||
|
||||
|
|
@ -101,7 +270,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void IsAction_OverridenNonActionMethod()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestAccessibleActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var method = typeof(DerivedController).GetMethod("OverridenNonActionMethod");
|
||||
Assert.NotNull(method);
|
||||
|
||||
|
|
@ -120,7 +289,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void IsAction_OverriddenMethodsFromObjectClass(string methodName)
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestAccessibleActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var method = typeof(DerivedController).GetMethod(
|
||||
methodName,
|
||||
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||
|
|
@ -137,7 +306,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void IsAction_DerivedControllerIDisposableDisposeMethod()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestAccessibleActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(DerivedController).GetTypeInfo();
|
||||
var methodInfo =
|
||||
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
|
||||
|
|
@ -155,7 +324,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void IsAction_DerivedControllerDisposeMethod()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestAccessibleActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(DerivedController).GetTypeInfo();
|
||||
var methodInfo =
|
||||
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
|
||||
|
|
@ -177,7 +346,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void IsAction_OverriddenDisposeMethod()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestAccessibleActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(DerivedOverriddenDisposeController).GetTypeInfo();
|
||||
var method = typeInfo.GetDeclaredMethods("Dispose").SingleOrDefault();
|
||||
Assert.NotNull(method);
|
||||
|
|
@ -193,7 +362,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void IsAction_NewDisposeMethod()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestAccessibleActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(DerivedNewDisposeController).GetTypeInfo();
|
||||
var method = typeInfo.GetDeclaredMethods("Dispose").SingleOrDefault();
|
||||
Assert.NotNull(method);
|
||||
|
|
@ -209,7 +378,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void IsAction_PocoControllerIDisposableDisposeMethod()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestAccessibleActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(IDisposablePocoController).GetTypeInfo();
|
||||
var methodInfo =
|
||||
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
|
||||
|
|
@ -227,7 +396,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void IsAction_PocoControllerDisposeMethod()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestAccessibleActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(IDisposablePocoController).GetTypeInfo();
|
||||
var methodInfo =
|
||||
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
|
||||
|
|
@ -249,7 +418,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void IsAction_SimplePocoControllerDisposeMethod()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestAccessibleActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(SimplePocoController).GetTypeInfo();
|
||||
var methods = typeInfo.GetMethods().Where(m => m.Name.Equals("Dispose"));
|
||||
|
||||
|
|
@ -272,7 +441,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void IsAction_StaticMethods(string methodName)
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestAccessibleActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var method = typeof(DerivedController).GetMethod(
|
||||
methodName,
|
||||
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
|
||||
|
|
@ -289,7 +458,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void BuildActionModel_EnableCorsAttributeAddsCorsAuthorizationFilterFactory()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DefaultActionModelBuilder(authorizationOptions: null);
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(EnableCorsController).GetTypeInfo();
|
||||
var method = typeInfo.GetMethod("Action");
|
||||
|
||||
|
|
@ -305,8 +474,8 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void BuildActionModel_DisableCorsAttributeAddsDisableCorsAuthorizationFilter()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DefaultActionModelBuilder(authorizationOptions: null);
|
||||
var typeInfo = typeof(DisableCorsController).GetTypeInfo();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(DisableCorsActionController).GetTypeInfo();
|
||||
var method = typeInfo.GetMethod("Action");
|
||||
|
||||
// Act
|
||||
|
|
@ -318,10 +487,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_ConventionallyRoutedAction_WithoutHttpConstraints()
|
||||
public void BuildActionModels_ConventionallyRoutedAction_WithoutHttpConstraints()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
|
||||
var actionName = nameof(ConventionallyRoutedController.Edit);
|
||||
|
||||
|
|
@ -337,10 +506,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_ConventionallyRoutedAction_WithHttpConstraints()
|
||||
public void BuildActionModels_ConventionallyRoutedAction_WithHttpConstraints()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
|
||||
var actionName = nameof(ConventionallyRoutedController.Update);
|
||||
|
||||
|
|
@ -358,13 +527,13 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_BaseAuthorizeFiltersAreStillValidWhenOverriden()
|
||||
public void BuildActionModels_BaseAuthorizeFiltersAreStillValidWhenOverriden()
|
||||
{
|
||||
// Arrange
|
||||
var options = new AuthorizationOptions();
|
||||
options.AddPolicy("Base", policy => policy.RequireClaim("Basic").RequireClaim("Basic2"));
|
||||
options.AddPolicy("Derived", policy => policy.RequireClaim("Derived"));
|
||||
var builder = CreateTestDefaultActionModelBuilder(options);
|
||||
var builder = new TestApplicationModelProvider();
|
||||
builder.AuthorizationOptions.AddPolicy("Base", policy => policy.RequireClaim("Basic").RequireClaim("Basic2"));
|
||||
builder.AuthorizationOptions.AddPolicy("Derived", policy => policy.RequireClaim("Derived"));
|
||||
|
||||
var typeInfo = typeof(DerivedController).GetTypeInfo();
|
||||
var actionName = nameof(DerivedController.Authorize);
|
||||
|
||||
|
|
@ -381,10 +550,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_ConventionallyRoutedActionWithHttpConstraints_AndInvalidRouteTemplateProvider()
|
||||
public void BuildActionModels_ConventionallyRoutedActionWithHttpConstraints_AndInvalidRouteTemplateProvider()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
|
||||
var actionName = nameof(ConventionallyRoutedController.Delete);
|
||||
|
||||
|
|
@ -403,10 +572,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_ConventionallyRoutedAction_WithMultipleHttpConstraints()
|
||||
public void BuildActionModels_ConventionallyRoutedAction_WithMultipleHttpConstraints()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
|
||||
var actionName = nameof(ConventionallyRoutedController.Details);
|
||||
|
||||
|
|
@ -422,10 +591,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_ConventionallyRoutedAction_WithMultipleOverlappingHttpConstraints()
|
||||
public void BuildActionModels_ConventionallyRoutedAction_WithMultipleOverlappingHttpConstraints()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
|
||||
var actionName = nameof(ConventionallyRoutedController.List);
|
||||
|
||||
|
|
@ -442,10 +611,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_AttributeRouteOnAction()
|
||||
public void BuildActionModels_AttributeRouteOnAction()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
|
||||
var actionName = nameof(NoRouteAttributeOnControllerController.Edit);
|
||||
|
||||
|
|
@ -467,10 +636,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_AttributeRouteOnAction_RouteAttribute()
|
||||
public void BuildActionModels_AttributeRouteOnAction_RouteAttribute()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
|
||||
var actionName = nameof(NoRouteAttributeOnControllerController.Update);
|
||||
|
||||
|
|
@ -491,10 +660,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_AttributeRouteOnAction_AcceptVerbsAttributeWithTemplate()
|
||||
public void BuildActionModels_AttributeRouteOnAction_AcceptVerbsAttributeWithTemplate()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
|
||||
var actionName = nameof(NoRouteAttributeOnControllerController.List);
|
||||
|
||||
|
|
@ -515,10 +684,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_AttributeRouteOnAction_CreatesOneActionInforPerRouteTemplate()
|
||||
public void BuildActionModels_AttributeRouteOnAction_CreatesOneActionInforPerRouteTemplate()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
|
||||
var actionName = nameof(NoRouteAttributeOnControllerController.Index);
|
||||
|
||||
|
|
@ -546,10 +715,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_NoRouteOnController_AllowsConventionallyRoutedActions_OnTheSameController()
|
||||
public void BuildActionModels_NoRouteOnController_AllowsConventionallyRoutedActions_OnTheSameController()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
|
||||
var actionName = nameof(NoRouteAttributeOnControllerController.Remove);
|
||||
|
||||
|
|
@ -571,10 +740,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
[Theory]
|
||||
[InlineData(typeof(SingleRouteAttributeController))]
|
||||
[InlineData(typeof(MultipleRouteAttributeController))]
|
||||
public void GetActions_RouteAttributeOnController_CreatesAttributeRoute_ForNonAttributedActions(Type controller)
|
||||
public void BuildActionModels_RouteAttributeOnController_CreatesAttributeRoute_ForNonAttributedActions(Type controller)
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = controller.GetTypeInfo();
|
||||
|
||||
// Act
|
||||
|
|
@ -595,10 +764,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
[Theory]
|
||||
[InlineData(typeof(SingleRouteAttributeController))]
|
||||
[InlineData(typeof(MultipleRouteAttributeController))]
|
||||
public void GetActions_RouteOnController_CreatesOneActionInforPerRouteTemplateOnAction(Type controller)
|
||||
public void BuildActionModels_RouteOnController_CreatesOneActionInforPerRouteTemplateOnAction(Type controller)
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = controller.GetTypeInfo();
|
||||
|
||||
// Act
|
||||
|
|
@ -624,10 +793,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_MixedHttpVerbsAndRoutes_EmptyVerbWithRoute()
|
||||
public void BuildActionModels_MixedHttpVerbsAndRoutes_EmptyVerbWithRoute()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
|
||||
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.VerbAndRoute);
|
||||
|
||||
|
|
@ -641,10 +810,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_MixedHttpVerbsAndRoutes_MultipleEmptyVerbsWithMultipleRoutes()
|
||||
public void BuildActionModels_MixedHttpVerbsAndRoutes_MultipleEmptyVerbsWithMultipleRoutes()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
|
||||
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.MultipleVerbsAndRoutes);
|
||||
|
||||
|
|
@ -662,10 +831,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_MixedHttpVerbsAndRoutes_MultipleEmptyAndNonEmptyVerbsWithMultipleRoutes()
|
||||
public void BuildActionModels_MixedHttpVerbsAndRoutes_MultipleEmptyAndNonEmptyVerbsWithMultipleRoutes()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
|
||||
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.MultipleVerbsWithAnyWithoutTemplateAndRoutes);
|
||||
|
||||
|
|
@ -686,10 +855,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_MixedHttpVerbsAndRoutes_MultipleEmptyAndNonEmptyVerbs()
|
||||
public void BuildActionModels_MixedHttpVerbsAndRoutes_MultipleEmptyAndNonEmptyVerbs()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
|
||||
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.Invalid);
|
||||
|
||||
|
|
@ -707,10 +876,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_InheritedAttributeRoutes()
|
||||
public void BuildActionModels_InheritedAttributeRoutes()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(DerivedClassInheritsAttributeRoutesController).GetTypeInfo();
|
||||
var actionName = nameof(DerivedClassInheritsAttributeRoutesController.Edit);
|
||||
|
||||
|
|
@ -730,10 +899,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActions_InheritedAttributeRoutesOverridden()
|
||||
public void BuildActionModels_InheritedAttributeRoutesOverridden()
|
||||
{
|
||||
// Arrange
|
||||
var builder = CreateTestDefaultActionModelBuilder();
|
||||
var builder = new TestApplicationModelProvider();
|
||||
var typeInfo = typeof(DerivedClassOverridesAttributeRoutesController).GetTypeInfo();
|
||||
var actionName = nameof(DerivedClassOverridesAttributeRoutesController.Edit);
|
||||
|
||||
|
|
@ -752,31 +921,6 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
Assert.Contains(action.AttributeRouteModel.Attribute, action.Attributes);
|
||||
}
|
||||
|
||||
private static DefaultActionModelBuilder CreateTestDefaultActionModelBuilder(
|
||||
AuthorizationOptions authOptions = null)
|
||||
{
|
||||
var options = new Mock<IOptions<AuthorizationOptions>>();
|
||||
options.Setup(o => o.Options).Returns(authOptions ?? new AuthorizationOptions());
|
||||
return new DefaultActionModelBuilder(options.Object);
|
||||
}
|
||||
|
||||
private static AccessibleActionModelBuilder CreateTestAccessibleActionModelBuilder()
|
||||
{
|
||||
var options = new Mock<IOptions<AuthorizationOptions>>();
|
||||
options.Setup(o => o.Options).Returns(new AuthorizationOptions());
|
||||
return new AccessibleActionModelBuilder(options.Object);
|
||||
}
|
||||
|
||||
private class AccessibleActionModelBuilder : DefaultActionModelBuilder
|
||||
{
|
||||
public AccessibleActionModelBuilder(IOptions<AuthorizationOptions> options) : base(options) { }
|
||||
|
||||
public new bool IsAction([NotNull] TypeInfo typeInfo, [NotNull]MethodInfo methodInfo)
|
||||
{
|
||||
return base.IsAction(typeInfo, methodInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private class BaseClassWithAttributeRoutesController
|
||||
{
|
||||
[Route("A")]
|
||||
|
|
@ -1039,7 +1183,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
}
|
||||
|
||||
private class DisableCorsController
|
||||
private class DisableCorsActionController
|
||||
{
|
||||
[DisableCors]
|
||||
public void Action()
|
||||
|
|
@ -1087,5 +1231,147 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Route("A")]
|
||||
[Route("B")]
|
||||
private class BaseClassWithRoutesController
|
||||
{
|
||||
}
|
||||
|
||||
private class DerivedClassInheritingRoutesController : BaseClassWithRoutesController
|
||||
{
|
||||
}
|
||||
|
||||
[Route("C")]
|
||||
[Route("D")]
|
||||
private class DerivedClassHidingRoutesController : BaseClassWithRoutesController
|
||||
{
|
||||
}
|
||||
|
||||
private class StoreController : Mvc.Controller
|
||||
{
|
||||
}
|
||||
|
||||
[Produces("application/json")]
|
||||
public class NoFiltersController
|
||||
{
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public class AccountController
|
||||
{
|
||||
}
|
||||
|
||||
[EnableCors("policy")]
|
||||
public class CorsController
|
||||
{
|
||||
}
|
||||
|
||||
[DisableCors]
|
||||
public class DisableCorsController
|
||||
{
|
||||
}
|
||||
|
||||
public class ModelBinderController
|
||||
{
|
||||
[FromQuery]
|
||||
public string Bound { get; set; }
|
||||
|
||||
public string Unbound { get; set; }
|
||||
}
|
||||
|
||||
public class SomeFiltersController : IAsyncActionFilter, IResultFilter
|
||||
{
|
||||
public Task OnActionExecutionAsync(
|
||||
[NotNull] ActionExecutingContext context,
|
||||
[NotNull] ActionExecutionDelegate next)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void OnResultExecuted([NotNull] ResultExecutedContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnResultExecuting([NotNull]ResultExecutingContext context)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class UnsupportedFiltersController : IExceptionFilter, IAuthorizationFilter, IAsyncResourceFilter
|
||||
{
|
||||
public void OnAuthorization([NotNull]AuthorizationContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnException([NotNull]ExceptionContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task OnResourceExecutionAsync([NotNull]ResourceExecutingContext context, [NotNull]ResourceExecutionDelegate next)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private class TestApplicationModelProvider : DefaultApplicationModelProvider
|
||||
{
|
||||
public TestApplicationModelProvider()
|
||||
: this(
|
||||
new MockMvcOptionsAccessor(),
|
||||
new OptionsManager<AuthorizationOptions>(Enumerable.Empty<IConfigureOptions<AuthorizationOptions>>()))
|
||||
{
|
||||
}
|
||||
|
||||
public TestApplicationModelProvider(
|
||||
IOptions<MvcOptions> options,
|
||||
IOptions<AuthorizationOptions> authorizationOptions)
|
||||
: base(options, authorizationOptions)
|
||||
{
|
||||
Options = options.Options;
|
||||
AuthorizationOptions = authorizationOptions.Options;
|
||||
}
|
||||
|
||||
public AuthorizationOptions AuthorizationOptions { get; }
|
||||
|
||||
public MvcOptions Options { get; }
|
||||
|
||||
public new IEnumerable<ControllerModel> BuildControllerModels(TypeInfo typeInfo)
|
||||
{
|
||||
return base.BuildControllerModels(typeInfo);
|
||||
}
|
||||
|
||||
public new ControllerModel CreateControllerModel(TypeInfo typeInfo)
|
||||
{
|
||||
return base.CreateControllerModel(typeInfo);
|
||||
}
|
||||
|
||||
public new PropertyModel CreatePropertyModel(PropertyInfo propertyInfo)
|
||||
{
|
||||
return base.CreatePropertyModel(propertyInfo);
|
||||
}
|
||||
|
||||
public new IEnumerable<ActionModel> BuildActionModels(TypeInfo typeInfo, MethodInfo methodInfo)
|
||||
{
|
||||
return base.BuildActionModels(typeInfo, methodInfo);
|
||||
}
|
||||
|
||||
public new ActionModel CreateActionModel(MethodInfo methodInfo, IReadOnlyList<object> attributes)
|
||||
{
|
||||
return base.CreateActionModel(methodInfo, attributes);
|
||||
}
|
||||
|
||||
public new bool IsAction(TypeInfo typeInfo, MethodInfo methodInfo)
|
||||
{
|
||||
return base.IsAction(typeInfo, methodInfo);
|
||||
}
|
||||
|
||||
public new ParameterModel CreateParameterModel(ParameterInfo parameterInfo)
|
||||
{
|
||||
return base.CreateParameterModel(parameterInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,281 +0,0 @@
|
|||
// 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;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Authorization;
|
||||
using Microsoft.AspNet.Cors.Core;
|
||||
using Microsoft.AspNet.Mvc.Filters;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
using Microsoft.Framework.Internal;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||
{
|
||||
public class DefaultControllerModelBuilderTest
|
||||
{
|
||||
[Fact]
|
||||
public void BuildControllerModel_DerivedFromControllerClass_HasFilter()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
||||
var typeInfo = typeof(StoreController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.BuildControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
var filter = Assert.Single(model.Filters);
|
||||
Assert.IsType<ControllerActionFilter>(filter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildControllerModel_AuthorizeAttributeAddsAuthorizeFilter()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
||||
var typeInfo = typeof(AccountController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.BuildControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.True(model.Filters.Any(f => f is AuthorizeFilter));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildControllerModel_EnableCorsAttributeAddsCorsAuthorizationFilterFactory()
|
||||
{
|
||||
// Arrange
|
||||
var corsOptions = new CorsOptions();
|
||||
corsOptions.AddPolicy("policy", new CorsPolicy());
|
||||
var mockOptions = new Mock<IOptions<CorsOptions>>();
|
||||
mockOptions.SetupGet(o => o.Options)
|
||||
.Returns(corsOptions);
|
||||
var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null),
|
||||
authorizationOptions: null);
|
||||
var typeInfo = typeof(CorsController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.BuildControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.Single(model.Filters, f => f is CorsAuthorizationFilterFactory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildControllerModel_AddsControllerProperties()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
||||
var typeInfo = typeof(ModelBinderController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.BuildControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, model.ControllerProperties.Count);
|
||||
Assert.Equal("Bound", model.ControllerProperties[0].PropertyName);
|
||||
Assert.Equal(BindingSource.Query, model.ControllerProperties[0].BindingInfo.BindingSource);
|
||||
Assert.NotNull(model.ControllerProperties[0].Controller);
|
||||
var attribute = Assert.Single(model.ControllerProperties[0].Attributes);
|
||||
Assert.IsType<FromQueryAttribute>(attribute);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildControllerModel_DisableCorsAttributeAddsDisableCorsAuthorizationFilter()
|
||||
{
|
||||
// Arrange
|
||||
var corsOptions = new CorsOptions();
|
||||
corsOptions.AddPolicy("policy", new CorsPolicy());
|
||||
var mockOptions = new Mock<IOptions<CorsOptions>>();
|
||||
mockOptions.SetupGet(o => o.Options)
|
||||
.Returns(corsOptions);
|
||||
var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null),
|
||||
authorizationOptions: null);
|
||||
var typeInfo = typeof(DisableCorsController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.BuildControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.True(model.Filters.Any(f => f is DisableCorsAuthorizationFilter));
|
||||
}
|
||||
|
||||
// This class has a filter attribute, but doesn't implement any filter interfaces,
|
||||
// so ControllerFilter is not present.
|
||||
[Fact]
|
||||
public void BuildControllerModel_ClassWithoutFilterInterfaces_HasNoControllerFilter()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
||||
var typeInfo = typeof(NoFiltersController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.BuildControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
var filter = Assert.Single(model.Filters);
|
||||
Assert.IsType<ProducesAttribute>(filter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildControllerModel_ClassWithFilterInterfaces_HasFilter()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
||||
var typeInfo = typeof(SomeFiltersController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.BuildControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.Single(model.Filters, f => f is ControllerActionFilter);
|
||||
Assert.Single(model.Filters, f => f is ControllerResultFilter);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildControllerModel_ClassWithFilterInterfaces_UnsupportedType()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
||||
var typeInfo = typeof(UnsupportedFiltersController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.BuildControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.Empty(model.Filters);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildControllerModel_ClassWithInheritedRoutes()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
||||
var typeInfo = typeof(DerivedClassInheritingRoutesController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.BuildControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, model.AttributeRoutes.Count);
|
||||
Assert.Equal(2, model.Attributes.Count);
|
||||
|
||||
var route = Assert.Single(model.AttributeRoutes, r => r.Template == "A");
|
||||
Assert.Contains(route.Attribute, model.Attributes);
|
||||
|
||||
route = Assert.Single(model.AttributeRoutes, r => r.Template == "B");
|
||||
Assert.Contains(route.Attribute, model.Attributes);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildControllerModel_ClassWithHiddenInheritedRoutes()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
||||
var typeInfo = typeof(DerivedClassHidingRoutesController).GetTypeInfo();
|
||||
|
||||
// Act
|
||||
var model = builder.BuildControllerModel(typeInfo);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, model.AttributeRoutes.Count);
|
||||
Assert.Equal(2, model.Attributes.Count);
|
||||
|
||||
var route = Assert.Single(model.AttributeRoutes, r => r.Template == "C");
|
||||
Assert.Contains(route.Attribute, model.Attributes);
|
||||
|
||||
route = Assert.Single(model.AttributeRoutes, r => r.Template == "D");
|
||||
Assert.Contains(route.Attribute, model.Attributes);
|
||||
}
|
||||
|
||||
[Route("A")]
|
||||
[Route("B")]
|
||||
private class BaseClassWithRoutesController
|
||||
{
|
||||
}
|
||||
|
||||
private class DerivedClassInheritingRoutesController : BaseClassWithRoutesController
|
||||
{
|
||||
}
|
||||
|
||||
[Route("C")]
|
||||
[Route("D")]
|
||||
private class DerivedClassHidingRoutesController : BaseClassWithRoutesController
|
||||
{
|
||||
}
|
||||
|
||||
private class StoreController : Mvc.Controller
|
||||
{
|
||||
}
|
||||
|
||||
[Produces("application/json")]
|
||||
public class NoFiltersController
|
||||
{
|
||||
}
|
||||
|
||||
[Authorize]
|
||||
public class AccountController
|
||||
{
|
||||
}
|
||||
|
||||
[EnableCors("policy")]
|
||||
public class CorsController
|
||||
{
|
||||
}
|
||||
|
||||
[DisableCors]
|
||||
public class DisableCorsController
|
||||
{
|
||||
}
|
||||
|
||||
public class ModelBinderController
|
||||
{
|
||||
[FromQuery]
|
||||
public string Bound { get; set; }
|
||||
|
||||
public string Unbound { get; set; }
|
||||
}
|
||||
|
||||
public class SomeFiltersController : IAsyncActionFilter, IResultFilter
|
||||
{
|
||||
public Task OnActionExecutionAsync(
|
||||
[NotNull] ActionExecutingContext context,
|
||||
[NotNull] ActionExecutionDelegate next)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public void OnResultExecuted([NotNull] ResultExecutedContext context)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnResultExecuting([NotNull]ResultExecutingContext context)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class UnsupportedFiltersController : IExceptionFilter, IAuthorizationFilter, IAsyncResourceFilter
|
||||
{
|
||||
public void OnAuthorization([NotNull]AuthorizationContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnException([NotNull]ExceptionContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task OnResourceExecutionAsync([NotNull]ResourceExecutingContext context, [NotNull]ResourceExecutionDelegate next)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNet.Authorization;
|
||||
using Microsoft.AspNet.Mvc.ApiExplorer;
|
||||
using Microsoft.AspNet.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
|
|
@ -1449,61 +1450,63 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
TypeInfo controllerTypeInfo,
|
||||
IEnumerable<IFilter> filters = null)
|
||||
{
|
||||
var options = new MockMvcOptionsAccessor();
|
||||
if (filters != null)
|
||||
{
|
||||
foreach (var filter in filters)
|
||||
{
|
||||
options.Options.Filters.Add(filter);
|
||||
}
|
||||
}
|
||||
|
||||
var controllerTypeProvider = new FixedSetControllerTypeProvider(new[] { controllerTypeInfo });
|
||||
var controllerModelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
||||
var modelProvider = new DefaultApplicationModelProvider(options, new MockAuthorizationOptionsAccessor());
|
||||
|
||||
var provider = new ControllerActionDescriptorProvider(
|
||||
controllerTypeProvider,
|
||||
controllerModelBuilder,
|
||||
new TestGlobalFilterProvider(filters),
|
||||
new MockMvcOptionsAccessor());
|
||||
new[] { modelProvider },
|
||||
options);
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
private ControllerActionDescriptorProvider GetProvider(
|
||||
params TypeInfo[] controllerTypeInfo)
|
||||
params TypeInfo[] controllerTypeInfos)
|
||||
{
|
||||
var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypeInfo);
|
||||
var controllerModelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
||||
var options = new MockMvcOptionsAccessor();
|
||||
|
||||
var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypeInfos);
|
||||
var modelProvider = new DefaultApplicationModelProvider(options, new MockAuthorizationOptionsAccessor());
|
||||
|
||||
var provider = new ControllerActionDescriptorProvider(
|
||||
controllerTypeProvider,
|
||||
controllerModelBuilder,
|
||||
new TestGlobalFilterProvider(),
|
||||
new MockMvcOptionsAccessor());
|
||||
new[] { modelProvider },
|
||||
options);
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
private ControllerActionDescriptorProvider GetProvider(
|
||||
TypeInfo type,
|
||||
TypeInfo controllerTypeInfo,
|
||||
IApplicationModelConvention convention)
|
||||
{
|
||||
var controllerTypeProvider = new FixedSetControllerTypeProvider(new[] { type });
|
||||
var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
||||
|
||||
var options = new MockMvcOptionsAccessor();
|
||||
options.Options.Conventions.Add(convention);
|
||||
|
||||
return new ControllerActionDescriptorProvider(
|
||||
var controllerTypeProvider = new FixedSetControllerTypeProvider(new[] { controllerTypeInfo });
|
||||
var modelProvider = new DefaultApplicationModelProvider(options, new MockAuthorizationOptionsAccessor());
|
||||
|
||||
var provider = new ControllerActionDescriptorProvider(
|
||||
controllerTypeProvider,
|
||||
modelBuilder,
|
||||
new TestGlobalFilterProvider(),
|
||||
new[] { modelProvider },
|
||||
options);
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
private IEnumerable<ActionDescriptor> GetDescriptors(params TypeInfo[] controllerTypeInfos)
|
||||
{
|
||||
var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypeInfos);
|
||||
var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
||||
|
||||
var provider = new ControllerActionDescriptorProvider(
|
||||
controllerTypeProvider,
|
||||
modelBuilder,
|
||||
new TestGlobalFilterProvider(),
|
||||
new MockMvcOptionsAccessor());
|
||||
|
||||
var provider = GetProvider(controllerTypeInfos);
|
||||
return provider.GetDescriptors();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using System.ComponentModel.Design;
|
|||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Authorization;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Http.Internal;
|
||||
using Microsoft.AspNet.Mvc.ActionConstraints;
|
||||
|
|
@ -667,14 +668,17 @@ namespace Microsoft.AspNet.Mvc
|
|||
.Select(t => t.GetTypeInfo())
|
||||
.ToList();
|
||||
|
||||
var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypes);
|
||||
var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
||||
var options = new MockMvcOptionsAccessor();
|
||||
|
||||
return new ControllerActionDescriptorProvider(
|
||||
controllerTypeProvider,
|
||||
modelBuilder,
|
||||
new TestGlobalFilterProvider(),
|
||||
new MockMvcOptionsAccessor());
|
||||
var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypes);
|
||||
var modelProvider = new DefaultApplicationModelProvider(options, new MockAuthorizationOptionsAccessor());
|
||||
|
||||
var provider = new ControllerActionDescriptorProvider(
|
||||
controllerTypeProvider,
|
||||
new[] { modelProvider },
|
||||
options);
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
private static HttpContext GetHttpContext(string httpMethod)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
// 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.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Authorization
|
||||
{
|
||||
public class MockAuthorizationOptionsAccessor : IOptions<AuthorizationOptions>
|
||||
{
|
||||
public AuthorizationOptions Options { get; } = new AuthorizationOptions();
|
||||
|
||||
public AuthorizationOptions GetNamedOptions(string name)
|
||||
{
|
||||
return Options;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
// 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 Microsoft.AspNet.Mvc.Filters;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class TestGlobalFilterProvider : IGlobalFilterProvider
|
||||
{
|
||||
public TestGlobalFilterProvider()
|
||||
: this(null)
|
||||
{
|
||||
}
|
||||
|
||||
public TestGlobalFilterProvider(IEnumerable<IFilter> filters)
|
||||
{
|
||||
var filterList = new List<IFilter>();
|
||||
Filters = filterList;
|
||||
|
||||
if (filters != null)
|
||||
{
|
||||
filterList.AddRange(filters);
|
||||
}
|
||||
}
|
||||
|
||||
public IReadOnlyList<IFilter> Filters { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using Microsoft.AspNet.Mvc.ActionConstraints;
|
||||
using Microsoft.AspNet.Mvc.ApiExplorer;
|
||||
using Microsoft.AspNet.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.MvcServiceCollectionExtensionsTestControllers;
|
||||
using Microsoft.AspNet.Mvc.Razor;
|
||||
|
|
@ -140,7 +141,8 @@ namespace Microsoft.AspNet.Mvc
|
|||
typeof(IActionDescriptorProvider),
|
||||
typeof(IActionInvokerProvider),
|
||||
typeof(IFilterProvider),
|
||||
typeof(IApiDescriptionProvider)
|
||||
typeof(IApiDescriptionProvider),
|
||||
typeof(IApplicationModelProvider),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNet.Authorization;
|
||||
using Microsoft.AspNet.Mvc;
|
||||
using Microsoft.AspNet.Mvc.ApplicationModels;
|
||||
using Microsoft.AspNet.Mvc.Core;
|
||||
|
|
@ -372,12 +373,6 @@ namespace System.Web.Http
|
|||
var assemblyProvider = new FixedSetAssemblyProvider();
|
||||
assemblyProvider.CandidateAssemblies.Add(GetType().GetTypeInfo().Assembly);
|
||||
var controllerTypeProvider = new NamespaceFilteredControllerTypeProvider(assemblyProvider);
|
||||
var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
||||
|
||||
var filterProvider = new Mock<IGlobalFilterProvider>();
|
||||
filterProvider
|
||||
.SetupGet(fp => fp.Filters)
|
||||
.Returns(new List<IFilter>());
|
||||
|
||||
var options = new MvcOptions();
|
||||
|
||||
|
|
@ -389,10 +384,18 @@ namespace System.Web.Http
|
|||
.SetupGet(o => o.Options)
|
||||
.Returns(options);
|
||||
|
||||
var authorizationOptionsAccessor = new Mock<IOptions<AuthorizationOptions>>();
|
||||
authorizationOptionsAccessor
|
||||
.SetupGet(o => o.Options)
|
||||
.Returns(new AuthorizationOptions());
|
||||
|
||||
var modelProvider = new DefaultApplicationModelProvider(
|
||||
optionsAccessor.Object,
|
||||
authorizationOptionsAccessor.Object);
|
||||
|
||||
var provider = new ControllerActionDescriptorProvider(
|
||||
controllerTypeProvider,
|
||||
modelBuilder,
|
||||
filterProvider.Object,
|
||||
new[] { modelProvider },
|
||||
optionsAccessor.Object);
|
||||
|
||||
return provider;
|
||||
|
|
|
|||
Loading…
Reference in New Issue