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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
|
@ -6,31 +6,262 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Microsoft.AspNet.Authorization;
|
using Microsoft.AspNet.Authorization;
|
||||||
using Microsoft.AspNet.Cors;
|
|
||||||
using Microsoft.AspNet.Cors.Core;
|
using Microsoft.AspNet.Cors.Core;
|
||||||
using Microsoft.AspNet.Mvc.ApiExplorer;
|
using Microsoft.AspNet.Mvc.ApiExplorer;
|
||||||
|
using Microsoft.AspNet.Mvc.Filters;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
|
|
||||||
using Microsoft.AspNet.Mvc.Routing;
|
using Microsoft.AspNet.Mvc.Routing;
|
||||||
using Microsoft.Framework.Internal;
|
using Microsoft.Framework.Internal;
|
||||||
using Microsoft.Framework.OptionsModel;
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
{
|
{
|
||||||
/// <summary>
|
public class DefaultApplicationModelProvider : IApplicationModelProvider
|
||||||
/// A default implementation of <see cref="IActionModelBuilder"/>.
|
|
||||||
/// </summary>
|
|
||||||
public class DefaultActionModelBuilder : IActionModelBuilder
|
|
||||||
{
|
{
|
||||||
private readonly AuthorizationOptions _authorizationOptions;
|
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 />
|
/// <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))
|
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;
|
return actionModels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,15 +503,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return methodInfo.IsPublic;
|
||||||
methodInfo.IsPublic;
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool IsIDisposableMethod(MethodInfo methodInfo, TypeInfo typeInfo)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
(typeof(IDisposable).GetTypeInfo().IsAssignableFrom(typeInfo) &&
|
|
||||||
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0] == methodInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -402,6 +612,13 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
return parameterModel;
|
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)
|
private bool IsSilentRouteAttribute(IRouteTemplateProvider routeTemplateProvider)
|
||||||
{
|
{
|
||||||
return
|
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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Microsoft.AspNet.Mvc.ApplicationModels;
|
using Microsoft.AspNet.Mvc.ApplicationModels;
|
||||||
using Microsoft.AspNet.Mvc.Filters;
|
|
||||||
using Microsoft.Framework.Internal;
|
using Microsoft.Framework.Internal;
|
||||||
using Microsoft.Framework.OptionsModel;
|
using Microsoft.Framework.OptionsModel;
|
||||||
|
|
||||||
|
|
@ -11,19 +11,17 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
{
|
{
|
||||||
public class ControllerActionDescriptorProvider : IActionDescriptorProvider
|
public class ControllerActionDescriptorProvider : IActionDescriptorProvider
|
||||||
{
|
{
|
||||||
private readonly IControllerModelBuilder _applicationModelBuilder;
|
private readonly IApplicationModelProvider[] _applicationModelProviders;
|
||||||
private readonly IControllerTypeProvider _controllerTypeProvider;
|
private readonly IControllerTypeProvider _controllerTypeProvider;
|
||||||
private readonly IReadOnlyList<IFilter> _globalFilters;
|
|
||||||
private readonly IEnumerable<IApplicationModelConvention> _conventions;
|
private readonly IEnumerable<IApplicationModelConvention> _conventions;
|
||||||
|
|
||||||
public ControllerActionDescriptorProvider([NotNull] IControllerTypeProvider controllerTypeProvider,
|
public ControllerActionDescriptorProvider(
|
||||||
[NotNull] IControllerModelBuilder applicationModelBuilder,
|
[NotNull] IControllerTypeProvider controllerTypeProvider,
|
||||||
[NotNull] IGlobalFilterProvider globalFilters,
|
[NotNull] IEnumerable<IApplicationModelProvider> applicationModelProviders,
|
||||||
[NotNull] IOptions<MvcOptions> optionsAccessor)
|
[NotNull] IOptions<MvcOptions> optionsAccessor)
|
||||||
{
|
{
|
||||||
_controllerTypeProvider = controllerTypeProvider;
|
_controllerTypeProvider = controllerTypeProvider;
|
||||||
_applicationModelBuilder = applicationModelBuilder;
|
_applicationModelProviders = applicationModelProviders.OrderBy(p => p.Order).ToArray();
|
||||||
_globalFilters = globalFilters.Filters;
|
|
||||||
_conventions = optionsAccessor.Options.Conventions;
|
_conventions = optionsAccessor.Options.Conventions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,23 +53,20 @@ namespace Microsoft.AspNet.Mvc.Core
|
||||||
|
|
||||||
internal protected ApplicationModel BuildModel()
|
internal protected ApplicationModel BuildModel()
|
||||||
{
|
{
|
||||||
var applicationModel = new ApplicationModel();
|
var controllerTypes = _controllerTypeProvider.ControllerTypes;
|
||||||
foreach (var filter in _globalFilters)
|
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);
|
_applicationModelProviders[i].OnProvidersExecuted(context);
|
||||||
if (controllerModel != null)
|
|
||||||
{
|
|
||||||
controllerModel.Application = applicationModel;
|
|
||||||
applicationModel.Controllers.Add(controllerModel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
// Core action discovery, filters and action execution.
|
||||||
|
|
||||||
// These are consumed only when creating action descriptors, then they can be de-allocated
|
// This are consumed only when creating action descriptors, then they can be de-allocated
|
||||||
services.TryAdd(ServiceDescriptor.Transient<IControllerTypeProvider, DefaultControllerTypeProvider>());
|
services.TryAdd(ServiceDescriptor.Transient<IControllerTypeProvider, DefaultControllerTypeProvider>());;
|
||||||
services.TryAdd(ServiceDescriptor.Transient<IControllerModelBuilder, DefaultControllerModelBuilder>());
|
|
||||||
services.TryAdd(ServiceDescriptor.Transient<IActionModelBuilder, DefaultActionModelBuilder>());
|
|
||||||
|
|
||||||
// This has a cache, so it needs to be a singleton
|
// This has a cache, so it needs to be a singleton
|
||||||
services.TryAdd(ServiceDescriptor.Singleton<IControllerFactory, DefaultControllerFactory>());
|
services.TryAdd(ServiceDescriptor.Singleton<IControllerFactory, DefaultControllerFactory>());
|
||||||
|
|
@ -155,12 +153,12 @@ namespace Microsoft.Framework.DependencyInjection
|
||||||
services.TryAdd(ServiceDescriptor
|
services.TryAdd(ServiceDescriptor
|
||||||
.Singleton<IActionDescriptorsCollectionProvider, DefaultActionDescriptorsCollectionProvider>());
|
.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
|
// multiple registration service
|
||||||
services.AddTransient<IFilterProvider, DefaultFilterProvider>();
|
services.AddTransient<IFilterProvider, DefaultFilterProvider>();
|
||||||
|
|
||||||
|
// multiple registration service
|
||||||
|
services.AddTransient<IApplicationModelProvider, DefaultApplicationModelProvider>();
|
||||||
|
|
||||||
services.TryAdd(ServiceDescriptor.Transient<FormatFilter, FormatFilter>());
|
services.TryAdd(ServiceDescriptor.Transient<FormatFilter, FormatFilter>());
|
||||||
services.TryAdd(ServiceDescriptor.Transient<CorsAuthorizationFilter, CorsAuthorizationFilter>());
|
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.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Authorization;
|
using Microsoft.AspNet.Authorization;
|
||||||
using Microsoft.AspNet.Cors.Core;
|
using Microsoft.AspNet.Cors.Core;
|
||||||
|
using Microsoft.AspNet.Mvc.Filters;
|
||||||
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.Framework.Internal;
|
using Microsoft.Framework.Internal;
|
||||||
using Microsoft.Framework.OptionsModel;
|
using Microsoft.Framework.OptionsModel;
|
||||||
using Moq;
|
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace Microsoft.AspNet.Mvc.ApplicationModels
|
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]
|
[Theory]
|
||||||
[InlineData("GetFromDerived", true)]
|
[InlineData("GetFromDerived", true)]
|
||||||
[InlineData("NewMethod", true)] // "NewMethod" is a public method declared with keyword "new".
|
[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)
|
public void IsAction_WithInheritedMethods(string methodName, bool expected)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestAccessibleActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var method = typeof(DerivedController).GetMethod(methodName);
|
var method = typeof(DerivedController).GetMethod(methodName);
|
||||||
Assert.NotNull(method);
|
Assert.NotNull(method);
|
||||||
|
|
||||||
|
|
@ -38,7 +207,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
public void IsAction_OverridenMethodControllerClass()
|
public void IsAction_OverridenMethodControllerClass()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestAccessibleActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var method = typeof(BaseController).GetMethod(nameof(BaseController.Redirect));
|
var method = typeof(BaseController).GetMethod(nameof(BaseController.Redirect));
|
||||||
Assert.NotNull(method);
|
Assert.NotNull(method);
|
||||||
|
|
||||||
|
|
@ -53,7 +222,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
public void IsAction_PrivateMethod_FromUserDefinedController()
|
public void IsAction_PrivateMethod_FromUserDefinedController()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestAccessibleActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var method = typeof(DerivedController).GetMethod(
|
var method = typeof(DerivedController).GetMethod(
|
||||||
"PrivateMethod",
|
"PrivateMethod",
|
||||||
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||||
|
|
@ -70,7 +239,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
public void IsAction_OperatorOverloadingMethod_FromOperatorOverloadingController()
|
public void IsAction_OperatorOverloadingMethod_FromOperatorOverloadingController()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestAccessibleActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var method = typeof(OperatorOverloadingController).GetMethod("op_Addition");
|
var method = typeof(OperatorOverloadingController).GetMethod("op_Addition");
|
||||||
Assert.NotNull(method);
|
Assert.NotNull(method);
|
||||||
Assert.True(method.IsSpecialName);
|
Assert.True(method.IsSpecialName);
|
||||||
|
|
@ -86,7 +255,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
public void IsAction_GenericMethod_FromUserDefinedController()
|
public void IsAction_GenericMethod_FromUserDefinedController()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestAccessibleActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var method = typeof(DerivedController).GetMethod("GenericMethod");
|
var method = typeof(DerivedController).GetMethod("GenericMethod");
|
||||||
Assert.NotNull(method);
|
Assert.NotNull(method);
|
||||||
|
|
||||||
|
|
@ -101,7 +270,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
public void IsAction_OverridenNonActionMethod()
|
public void IsAction_OverridenNonActionMethod()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestAccessibleActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var method = typeof(DerivedController).GetMethod("OverridenNonActionMethod");
|
var method = typeof(DerivedController).GetMethod("OverridenNonActionMethod");
|
||||||
Assert.NotNull(method);
|
Assert.NotNull(method);
|
||||||
|
|
||||||
|
|
@ -120,7 +289,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
public void IsAction_OverriddenMethodsFromObjectClass(string methodName)
|
public void IsAction_OverriddenMethodsFromObjectClass(string methodName)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestAccessibleActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var method = typeof(DerivedController).GetMethod(
|
var method = typeof(DerivedController).GetMethod(
|
||||||
methodName,
|
methodName,
|
||||||
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
||||||
|
|
@ -137,7 +306,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
public void IsAction_DerivedControllerIDisposableDisposeMethod()
|
public void IsAction_DerivedControllerIDisposableDisposeMethod()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestAccessibleActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(DerivedController).GetTypeInfo();
|
var typeInfo = typeof(DerivedController).GetTypeInfo();
|
||||||
var methodInfo =
|
var methodInfo =
|
||||||
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
|
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
|
||||||
|
|
@ -155,7 +324,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
public void IsAction_DerivedControllerDisposeMethod()
|
public void IsAction_DerivedControllerDisposeMethod()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestAccessibleActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(DerivedController).GetTypeInfo();
|
var typeInfo = typeof(DerivedController).GetTypeInfo();
|
||||||
var methodInfo =
|
var methodInfo =
|
||||||
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
|
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
|
||||||
|
|
@ -177,7 +346,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
public void IsAction_OverriddenDisposeMethod()
|
public void IsAction_OverriddenDisposeMethod()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestAccessibleActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(DerivedOverriddenDisposeController).GetTypeInfo();
|
var typeInfo = typeof(DerivedOverriddenDisposeController).GetTypeInfo();
|
||||||
var method = typeInfo.GetDeclaredMethods("Dispose").SingleOrDefault();
|
var method = typeInfo.GetDeclaredMethods("Dispose").SingleOrDefault();
|
||||||
Assert.NotNull(method);
|
Assert.NotNull(method);
|
||||||
|
|
@ -193,7 +362,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
public void IsAction_NewDisposeMethod()
|
public void IsAction_NewDisposeMethod()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestAccessibleActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(DerivedNewDisposeController).GetTypeInfo();
|
var typeInfo = typeof(DerivedNewDisposeController).GetTypeInfo();
|
||||||
var method = typeInfo.GetDeclaredMethods("Dispose").SingleOrDefault();
|
var method = typeInfo.GetDeclaredMethods("Dispose").SingleOrDefault();
|
||||||
Assert.NotNull(method);
|
Assert.NotNull(method);
|
||||||
|
|
@ -209,7 +378,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
public void IsAction_PocoControllerIDisposableDisposeMethod()
|
public void IsAction_PocoControllerIDisposableDisposeMethod()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestAccessibleActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(IDisposablePocoController).GetTypeInfo();
|
var typeInfo = typeof(IDisposablePocoController).GetTypeInfo();
|
||||||
var methodInfo =
|
var methodInfo =
|
||||||
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
|
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
|
||||||
|
|
@ -227,7 +396,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
public void IsAction_PocoControllerDisposeMethod()
|
public void IsAction_PocoControllerDisposeMethod()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestAccessibleActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(IDisposablePocoController).GetTypeInfo();
|
var typeInfo = typeof(IDisposablePocoController).GetTypeInfo();
|
||||||
var methodInfo =
|
var methodInfo =
|
||||||
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
|
typeInfo.GetRuntimeInterfaceMap(typeof(IDisposable)).TargetMethods[0];
|
||||||
|
|
@ -249,7 +418,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
public void IsAction_SimplePocoControllerDisposeMethod()
|
public void IsAction_SimplePocoControllerDisposeMethod()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestAccessibleActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(SimplePocoController).GetTypeInfo();
|
var typeInfo = typeof(SimplePocoController).GetTypeInfo();
|
||||||
var methods = typeInfo.GetMethods().Where(m => m.Name.Equals("Dispose"));
|
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)
|
public void IsAction_StaticMethods(string methodName)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestAccessibleActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var method = typeof(DerivedController).GetMethod(
|
var method = typeof(DerivedController).GetMethod(
|
||||||
methodName,
|
methodName,
|
||||||
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
|
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
|
||||||
|
|
@ -289,7 +458,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
public void BuildActionModel_EnableCorsAttributeAddsCorsAuthorizationFilterFactory()
|
public void BuildActionModel_EnableCorsAttributeAddsCorsAuthorizationFilterFactory()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = new DefaultActionModelBuilder(authorizationOptions: null);
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(EnableCorsController).GetTypeInfo();
|
var typeInfo = typeof(EnableCorsController).GetTypeInfo();
|
||||||
var method = typeInfo.GetMethod("Action");
|
var method = typeInfo.GetMethod("Action");
|
||||||
|
|
||||||
|
|
@ -305,8 +474,8 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
public void BuildActionModel_DisableCorsAttributeAddsDisableCorsAuthorizationFilter()
|
public void BuildActionModel_DisableCorsAttributeAddsDisableCorsAuthorizationFilter()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = new DefaultActionModelBuilder(authorizationOptions: null);
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(DisableCorsController).GetTypeInfo();
|
var typeInfo = typeof(DisableCorsActionController).GetTypeInfo();
|
||||||
var method = typeInfo.GetMethod("Action");
|
var method = typeInfo.GetMethod("Action");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -318,10 +487,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_ConventionallyRoutedAction_WithoutHttpConstraints()
|
public void BuildActionModels_ConventionallyRoutedAction_WithoutHttpConstraints()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
|
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
|
||||||
var actionName = nameof(ConventionallyRoutedController.Edit);
|
var actionName = nameof(ConventionallyRoutedController.Edit);
|
||||||
|
|
||||||
|
|
@ -337,10 +506,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_ConventionallyRoutedAction_WithHttpConstraints()
|
public void BuildActionModels_ConventionallyRoutedAction_WithHttpConstraints()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
|
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
|
||||||
var actionName = nameof(ConventionallyRoutedController.Update);
|
var actionName = nameof(ConventionallyRoutedController.Update);
|
||||||
|
|
||||||
|
|
@ -358,13 +527,13 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_BaseAuthorizeFiltersAreStillValidWhenOverriden()
|
public void BuildActionModels_BaseAuthorizeFiltersAreStillValidWhenOverriden()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var options = new AuthorizationOptions();
|
var builder = new TestApplicationModelProvider();
|
||||||
options.AddPolicy("Base", policy => policy.RequireClaim("Basic").RequireClaim("Basic2"));
|
builder.AuthorizationOptions.AddPolicy("Base", policy => policy.RequireClaim("Basic").RequireClaim("Basic2"));
|
||||||
options.AddPolicy("Derived", policy => policy.RequireClaim("Derived"));
|
builder.AuthorizationOptions.AddPolicy("Derived", policy => policy.RequireClaim("Derived"));
|
||||||
var builder = CreateTestDefaultActionModelBuilder(options);
|
|
||||||
var typeInfo = typeof(DerivedController).GetTypeInfo();
|
var typeInfo = typeof(DerivedController).GetTypeInfo();
|
||||||
var actionName = nameof(DerivedController.Authorize);
|
var actionName = nameof(DerivedController.Authorize);
|
||||||
|
|
||||||
|
|
@ -381,10 +550,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_ConventionallyRoutedActionWithHttpConstraints_AndInvalidRouteTemplateProvider()
|
public void BuildActionModels_ConventionallyRoutedActionWithHttpConstraints_AndInvalidRouteTemplateProvider()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
|
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
|
||||||
var actionName = nameof(ConventionallyRoutedController.Delete);
|
var actionName = nameof(ConventionallyRoutedController.Delete);
|
||||||
|
|
||||||
|
|
@ -403,10 +572,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_ConventionallyRoutedAction_WithMultipleHttpConstraints()
|
public void BuildActionModels_ConventionallyRoutedAction_WithMultipleHttpConstraints()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
|
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
|
||||||
var actionName = nameof(ConventionallyRoutedController.Details);
|
var actionName = nameof(ConventionallyRoutedController.Details);
|
||||||
|
|
||||||
|
|
@ -422,10 +591,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_ConventionallyRoutedAction_WithMultipleOverlappingHttpConstraints()
|
public void BuildActionModels_ConventionallyRoutedAction_WithMultipleOverlappingHttpConstraints()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
|
var typeInfo = typeof(ConventionallyRoutedController).GetTypeInfo();
|
||||||
var actionName = nameof(ConventionallyRoutedController.List);
|
var actionName = nameof(ConventionallyRoutedController.List);
|
||||||
|
|
||||||
|
|
@ -442,10 +611,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_AttributeRouteOnAction()
|
public void BuildActionModels_AttributeRouteOnAction()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
|
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
|
||||||
var actionName = nameof(NoRouteAttributeOnControllerController.Edit);
|
var actionName = nameof(NoRouteAttributeOnControllerController.Edit);
|
||||||
|
|
||||||
|
|
@ -467,10 +636,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_AttributeRouteOnAction_RouteAttribute()
|
public void BuildActionModels_AttributeRouteOnAction_RouteAttribute()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
|
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
|
||||||
var actionName = nameof(NoRouteAttributeOnControllerController.Update);
|
var actionName = nameof(NoRouteAttributeOnControllerController.Update);
|
||||||
|
|
||||||
|
|
@ -491,10 +660,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_AttributeRouteOnAction_AcceptVerbsAttributeWithTemplate()
|
public void BuildActionModels_AttributeRouteOnAction_AcceptVerbsAttributeWithTemplate()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
|
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
|
||||||
var actionName = nameof(NoRouteAttributeOnControllerController.List);
|
var actionName = nameof(NoRouteAttributeOnControllerController.List);
|
||||||
|
|
||||||
|
|
@ -515,10 +684,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_AttributeRouteOnAction_CreatesOneActionInforPerRouteTemplate()
|
public void BuildActionModels_AttributeRouteOnAction_CreatesOneActionInforPerRouteTemplate()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
|
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
|
||||||
var actionName = nameof(NoRouteAttributeOnControllerController.Index);
|
var actionName = nameof(NoRouteAttributeOnControllerController.Index);
|
||||||
|
|
||||||
|
|
@ -546,10 +715,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_NoRouteOnController_AllowsConventionallyRoutedActions_OnTheSameController()
|
public void BuildActionModels_NoRouteOnController_AllowsConventionallyRoutedActions_OnTheSameController()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
|
var typeInfo = typeof(NoRouteAttributeOnControllerController).GetTypeInfo();
|
||||||
var actionName = nameof(NoRouteAttributeOnControllerController.Remove);
|
var actionName = nameof(NoRouteAttributeOnControllerController.Remove);
|
||||||
|
|
||||||
|
|
@ -571,10 +740,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(typeof(SingleRouteAttributeController))]
|
[InlineData(typeof(SingleRouteAttributeController))]
|
||||||
[InlineData(typeof(MultipleRouteAttributeController))]
|
[InlineData(typeof(MultipleRouteAttributeController))]
|
||||||
public void GetActions_RouteAttributeOnController_CreatesAttributeRoute_ForNonAttributedActions(Type controller)
|
public void BuildActionModels_RouteAttributeOnController_CreatesAttributeRoute_ForNonAttributedActions(Type controller)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = controller.GetTypeInfo();
|
var typeInfo = controller.GetTypeInfo();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -595,10 +764,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(typeof(SingleRouteAttributeController))]
|
[InlineData(typeof(SingleRouteAttributeController))]
|
||||||
[InlineData(typeof(MultipleRouteAttributeController))]
|
[InlineData(typeof(MultipleRouteAttributeController))]
|
||||||
public void GetActions_RouteOnController_CreatesOneActionInforPerRouteTemplateOnAction(Type controller)
|
public void BuildActionModels_RouteOnController_CreatesOneActionInforPerRouteTemplateOnAction(Type controller)
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = controller.GetTypeInfo();
|
var typeInfo = controller.GetTypeInfo();
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|
@ -624,10 +793,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_MixedHttpVerbsAndRoutes_EmptyVerbWithRoute()
|
public void BuildActionModels_MixedHttpVerbsAndRoutes_EmptyVerbWithRoute()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
|
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
|
||||||
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.VerbAndRoute);
|
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.VerbAndRoute);
|
||||||
|
|
||||||
|
|
@ -641,10 +810,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_MixedHttpVerbsAndRoutes_MultipleEmptyVerbsWithMultipleRoutes()
|
public void BuildActionModels_MixedHttpVerbsAndRoutes_MultipleEmptyVerbsWithMultipleRoutes()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
|
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
|
||||||
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.MultipleVerbsAndRoutes);
|
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.MultipleVerbsAndRoutes);
|
||||||
|
|
||||||
|
|
@ -662,10 +831,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_MixedHttpVerbsAndRoutes_MultipleEmptyAndNonEmptyVerbsWithMultipleRoutes()
|
public void BuildActionModels_MixedHttpVerbsAndRoutes_MultipleEmptyAndNonEmptyVerbsWithMultipleRoutes()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
|
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
|
||||||
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.MultipleVerbsWithAnyWithoutTemplateAndRoutes);
|
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.MultipleVerbsWithAnyWithoutTemplateAndRoutes);
|
||||||
|
|
||||||
|
|
@ -686,10 +855,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_MixedHttpVerbsAndRoutes_MultipleEmptyAndNonEmptyVerbs()
|
public void BuildActionModels_MixedHttpVerbsAndRoutes_MultipleEmptyAndNonEmptyVerbs()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
|
var typeInfo = typeof(MixedHttpVerbsAndRouteAttributeController).GetTypeInfo();
|
||||||
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.Invalid);
|
var actionName = nameof(MixedHttpVerbsAndRouteAttributeController.Invalid);
|
||||||
|
|
||||||
|
|
@ -707,10 +876,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_InheritedAttributeRoutes()
|
public void BuildActionModels_InheritedAttributeRoutes()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(DerivedClassInheritsAttributeRoutesController).GetTypeInfo();
|
var typeInfo = typeof(DerivedClassInheritsAttributeRoutesController).GetTypeInfo();
|
||||||
var actionName = nameof(DerivedClassInheritsAttributeRoutesController.Edit);
|
var actionName = nameof(DerivedClassInheritsAttributeRoutesController.Edit);
|
||||||
|
|
||||||
|
|
@ -730,10 +899,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void GetActions_InheritedAttributeRoutesOverridden()
|
public void BuildActionModels_InheritedAttributeRoutesOverridden()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var builder = CreateTestDefaultActionModelBuilder();
|
var builder = new TestApplicationModelProvider();
|
||||||
var typeInfo = typeof(DerivedClassOverridesAttributeRoutesController).GetTypeInfo();
|
var typeInfo = typeof(DerivedClassOverridesAttributeRoutesController).GetTypeInfo();
|
||||||
var actionName = nameof(DerivedClassOverridesAttributeRoutesController.Edit);
|
var actionName = nameof(DerivedClassOverridesAttributeRoutesController.Edit);
|
||||||
|
|
||||||
|
|
@ -752,31 +921,6 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
Assert.Contains(action.AttributeRouteModel.Attribute, action.Attributes);
|
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
|
private class BaseClassWithAttributeRoutesController
|
||||||
{
|
{
|
||||||
[Route("A")]
|
[Route("A")]
|
||||||
|
|
@ -1039,7 +1183,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DisableCorsController
|
private class DisableCorsActionController
|
||||||
{
|
{
|
||||||
[DisableCors]
|
[DisableCors]
|
||||||
public void Action()
|
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.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Microsoft.AspNet.Authorization;
|
||||||
using Microsoft.AspNet.Mvc.ApiExplorer;
|
using Microsoft.AspNet.Mvc.ApiExplorer;
|
||||||
using Microsoft.AspNet.Mvc.ApplicationModels;
|
using Microsoft.AspNet.Mvc.ApplicationModels;
|
||||||
using Microsoft.AspNet.Mvc.Core;
|
using Microsoft.AspNet.Mvc.Core;
|
||||||
|
|
@ -1449,61 +1450,63 @@ namespace Microsoft.AspNet.Mvc.Test
|
||||||
TypeInfo controllerTypeInfo,
|
TypeInfo controllerTypeInfo,
|
||||||
IEnumerable<IFilter> filters = null)
|
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 controllerTypeProvider = new FixedSetControllerTypeProvider(new[] { controllerTypeInfo });
|
||||||
var controllerModelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
var modelProvider = new DefaultApplicationModelProvider(options, new MockAuthorizationOptionsAccessor());
|
||||||
|
|
||||||
var provider = new ControllerActionDescriptorProvider(
|
var provider = new ControllerActionDescriptorProvider(
|
||||||
controllerTypeProvider,
|
controllerTypeProvider,
|
||||||
controllerModelBuilder,
|
new[] { modelProvider },
|
||||||
new TestGlobalFilterProvider(filters),
|
options);
|
||||||
new MockMvcOptionsAccessor());
|
|
||||||
|
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ControllerActionDescriptorProvider GetProvider(
|
private ControllerActionDescriptorProvider GetProvider(
|
||||||
params TypeInfo[] controllerTypeInfo)
|
params TypeInfo[] controllerTypeInfos)
|
||||||
{
|
{
|
||||||
var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypeInfo);
|
var options = new MockMvcOptionsAccessor();
|
||||||
var controllerModelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
|
||||||
|
var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypeInfos);
|
||||||
|
var modelProvider = new DefaultApplicationModelProvider(options, new MockAuthorizationOptionsAccessor());
|
||||||
|
|
||||||
var provider = new ControllerActionDescriptorProvider(
|
var provider = new ControllerActionDescriptorProvider(
|
||||||
controllerTypeProvider,
|
controllerTypeProvider,
|
||||||
controllerModelBuilder,
|
new[] { modelProvider },
|
||||||
new TestGlobalFilterProvider(),
|
options);
|
||||||
new MockMvcOptionsAccessor());
|
|
||||||
|
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ControllerActionDescriptorProvider GetProvider(
|
private ControllerActionDescriptorProvider GetProvider(
|
||||||
TypeInfo type,
|
TypeInfo controllerTypeInfo,
|
||||||
IApplicationModelConvention convention)
|
IApplicationModelConvention convention)
|
||||||
{
|
{
|
||||||
var controllerTypeProvider = new FixedSetControllerTypeProvider(new[] { type });
|
|
||||||
var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
|
||||||
|
|
||||||
var options = new MockMvcOptionsAccessor();
|
var options = new MockMvcOptionsAccessor();
|
||||||
options.Options.Conventions.Add(convention);
|
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,
|
controllerTypeProvider,
|
||||||
modelBuilder,
|
new[] { modelProvider },
|
||||||
new TestGlobalFilterProvider(),
|
|
||||||
options);
|
options);
|
||||||
|
|
||||||
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<ActionDescriptor> GetDescriptors(params TypeInfo[] controllerTypeInfos)
|
private IEnumerable<ActionDescriptor> GetDescriptors(params TypeInfo[] controllerTypeInfos)
|
||||||
{
|
{
|
||||||
var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypeInfos);
|
var provider = GetProvider(controllerTypeInfos);
|
||||||
var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
|
||||||
|
|
||||||
var provider = new ControllerActionDescriptorProvider(
|
|
||||||
controllerTypeProvider,
|
|
||||||
modelBuilder,
|
|
||||||
new TestGlobalFilterProvider(),
|
|
||||||
new MockMvcOptionsAccessor());
|
|
||||||
|
|
||||||
return provider.GetDescriptors();
|
return provider.GetDescriptors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ using System.ComponentModel.Design;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNet.Authorization;
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
using Microsoft.AspNet.Http.Internal;
|
using Microsoft.AspNet.Http.Internal;
|
||||||
using Microsoft.AspNet.Mvc.ActionConstraints;
|
using Microsoft.AspNet.Mvc.ActionConstraints;
|
||||||
|
|
@ -667,14 +668,17 @@ namespace Microsoft.AspNet.Mvc
|
||||||
.Select(t => t.GetTypeInfo())
|
.Select(t => t.GetTypeInfo())
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypes);
|
var options = new MockMvcOptionsAccessor();
|
||||||
var modelBuilder = new DefaultControllerModelBuilder(new DefaultActionModelBuilder(null), null);
|
|
||||||
|
|
||||||
return new ControllerActionDescriptorProvider(
|
var controllerTypeProvider = new FixedSetControllerTypeProvider(controllerTypes);
|
||||||
controllerTypeProvider,
|
var modelProvider = new DefaultApplicationModelProvider(options, new MockAuthorizationOptionsAccessor());
|
||||||
modelBuilder,
|
|
||||||
new TestGlobalFilterProvider(),
|
var provider = new ControllerActionDescriptorProvider(
|
||||||
new MockMvcOptionsAccessor());
|
controllerTypeProvider,
|
||||||
|
new[] { modelProvider },
|
||||||
|
options);
|
||||||
|
|
||||||
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static HttpContext GetHttpContext(string httpMethod)
|
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 System.Reflection;
|
||||||
using Microsoft.AspNet.Mvc.ActionConstraints;
|
using Microsoft.AspNet.Mvc.ActionConstraints;
|
||||||
using Microsoft.AspNet.Mvc.ApiExplorer;
|
using Microsoft.AspNet.Mvc.ApiExplorer;
|
||||||
|
using Microsoft.AspNet.Mvc.ApplicationModels;
|
||||||
using Microsoft.AspNet.Mvc.Core;
|
using Microsoft.AspNet.Mvc.Core;
|
||||||
using Microsoft.AspNet.Mvc.MvcServiceCollectionExtensionsTestControllers;
|
using Microsoft.AspNet.Mvc.MvcServiceCollectionExtensionsTestControllers;
|
||||||
using Microsoft.AspNet.Mvc.Razor;
|
using Microsoft.AspNet.Mvc.Razor;
|
||||||
|
|
@ -140,7 +141,8 @@ namespace Microsoft.AspNet.Mvc
|
||||||
typeof(IActionDescriptorProvider),
|
typeof(IActionDescriptorProvider),
|
||||||
typeof(IActionInvokerProvider),
|
typeof(IActionInvokerProvider),
|
||||||
typeof(IFilterProvider),
|
typeof(IFilterProvider),
|
||||||
typeof(IApiDescriptionProvider)
|
typeof(IApiDescriptionProvider),
|
||||||
|
typeof(IApplicationModelProvider),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Microsoft.AspNet.Authorization;
|
||||||
using Microsoft.AspNet.Mvc;
|
using Microsoft.AspNet.Mvc;
|
||||||
using Microsoft.AspNet.Mvc.ApplicationModels;
|
using Microsoft.AspNet.Mvc.ApplicationModels;
|
||||||
using Microsoft.AspNet.Mvc.Core;
|
using Microsoft.AspNet.Mvc.Core;
|
||||||
|
|
@ -372,12 +373,6 @@ namespace System.Web.Http
|
||||||
var assemblyProvider = new FixedSetAssemblyProvider();
|
var assemblyProvider = new FixedSetAssemblyProvider();
|
||||||
assemblyProvider.CandidateAssemblies.Add(GetType().GetTypeInfo().Assembly);
|
assemblyProvider.CandidateAssemblies.Add(GetType().GetTypeInfo().Assembly);
|
||||||
var controllerTypeProvider = new NamespaceFilteredControllerTypeProvider(assemblyProvider);
|
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();
|
var options = new MvcOptions();
|
||||||
|
|
||||||
|
|
@ -389,10 +384,18 @@ namespace System.Web.Http
|
||||||
.SetupGet(o => o.Options)
|
.SetupGet(o => o.Options)
|
||||||
.Returns(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(
|
var provider = new ControllerActionDescriptorProvider(
|
||||||
controllerTypeProvider,
|
controllerTypeProvider,
|
||||||
modelBuilder,
|
new[] { modelProvider },
|
||||||
filterProvider.Object,
|
|
||||||
optionsAccessor.Object);
|
optionsAccessor.Object);
|
||||||
|
|
||||||
return provider;
|
return provider;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue