refactor of action descriptor pipeline
(cherry picked from commit 634f756e7fd303fc3022563fcd8fb9b1cb47fba2)
This commit is contained in:
parent
172dcd179b
commit
e6ba1f23a2
|
|
@ -1,68 +0,0 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class ReflectedRouteConstraintsActionDescriptorProvider : IActionDescriptorProvider
|
||||
{
|
||||
public int Order
|
||||
{
|
||||
get { return ReflectedActionDescriptorProvider.DefaultOrder + 100; }
|
||||
}
|
||||
|
||||
public void Invoke([NotNull]ActionDescriptorProviderContext context, Action callNext)
|
||||
{
|
||||
var removalConstraints = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// Iterate all the Reflected Action Descriptor providers and add area or other route constraints
|
||||
foreach (var actionDescriptor in context.Results.OfType<ReflectedActionDescriptor>())
|
||||
{
|
||||
var routeConstraints = actionDescriptor
|
||||
.ControllerDescriptor
|
||||
.ControllerTypeInfo
|
||||
.GetCustomAttributes<RouteConstraintAttribute>()
|
||||
.ToArray();
|
||||
|
||||
foreach (var routeConstraint in routeConstraints)
|
||||
{
|
||||
if (routeConstraint.BlockNonAttributedActions)
|
||||
{
|
||||
removalConstraints.Add(routeConstraint.RouteKey);
|
||||
}
|
||||
|
||||
// Skip duplicates
|
||||
if (!HasConstraint(actionDescriptor, routeConstraint.RouteKey))
|
||||
{
|
||||
actionDescriptor.RouteConstraints.Add(new RouteDataActionConstraint(
|
||||
routeConstraint.RouteKey, routeConstraint.RouteValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var actionDescriptor in context.Results.OfType<ReflectedActionDescriptor>())
|
||||
{
|
||||
foreach (var key in removalConstraints)
|
||||
{
|
||||
if (!HasConstraint(actionDescriptor, key))
|
||||
{
|
||||
actionDescriptor.RouteConstraints.Add(
|
||||
new RouteDataActionConstraint(key, RouteKeyHandling.DenyKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
callNext();
|
||||
}
|
||||
|
||||
private bool HasConstraint(ActionDescriptor actionDescript, string routeKey)
|
||||
{
|
||||
return actionDescript.RouteConstraints.Any(
|
||||
rc => string.Equals(rc.RouteKey, routeKey, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class DefaultControllerDescriptorFactory : IControllerDescriptorFactory
|
||||
{
|
||||
public ControllerDescriptor CreateControllerDescriptor(TypeInfo typeInfo)
|
||||
{
|
||||
return new ControllerDescriptor(typeInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public class DefaultParameterDescriptorFactory : IParameterDescriptorFactory
|
||||
{
|
||||
public ParameterDescriptor GetDescriptor(ParameterInfo parameter)
|
||||
{
|
||||
var isFromBody = IsFromBody(parameter);
|
||||
|
||||
return new ParameterDescriptor
|
||||
{
|
||||
Name = parameter.Name,
|
||||
IsOptional = parameter.IsOptional || parameter.HasDefaultValue,
|
||||
ParameterBindingInfo = isFromBody ? null : GetParameterBindingInfo(parameter),
|
||||
BodyParameterInfo = isFromBody ? GetBodyParameterInfo(parameter) : null
|
||||
};
|
||||
}
|
||||
public virtual bool IsFromBody(ParameterInfo parameter)
|
||||
{
|
||||
return parameter.GetCustomAttribute<FromBodyAttribute>() != null;
|
||||
}
|
||||
|
||||
private ParameterBindingInfo GetParameterBindingInfo(ParameterInfo parameter)
|
||||
{
|
||||
return new ParameterBindingInfo(parameter.Name, parameter.ParameterType);
|
||||
}
|
||||
|
||||
private BodyParameterInfo GetBodyParameterInfo(ParameterInfo parameter)
|
||||
{
|
||||
return new BodyParameterInfo(parameter.ParameterType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public interface IControllerDescriptorFactory
|
||||
{
|
||||
ControllerDescriptor CreateControllerDescriptor(TypeInfo type);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
public interface IParameterDescriptorFactory
|
||||
{
|
||||
ParameterDescriptor GetDescriptor(ParameterInfo parameter);
|
||||
}
|
||||
}
|
||||
|
|
@ -27,6 +27,10 @@
|
|||
<Compile Include="ActionDescriptor.cs" />
|
||||
<Compile Include="ActionDescriptorProviderContext.cs" />
|
||||
<Compile Include="ActionDescriptorsCollection.cs" />
|
||||
<Compile Include="ReflectedModelBuilder\IReflectedApplicationModelConvention.cs" />
|
||||
<Compile Include="ReflectedModelBuilder\ReflectedActionModel.cs" />
|
||||
<Compile Include="ReflectedModelBuilder\ReflectedControllerModel.cs" />
|
||||
<Compile Include="ReflectedModelBuilder\ReflectedApplicationModel.cs" />
|
||||
<Compile Include="ActionInvokerFactory.cs" />
|
||||
<Compile Include="ActionInvokerProviderContext.cs" />
|
||||
<Compile Include="ActionMethodSelectorAttribute.cs" />
|
||||
|
|
@ -61,7 +65,6 @@
|
|||
<Compile Include="AntiForgery\ITokenValidator.cs" />
|
||||
<Compile Include="AntiForgery\TokenProvider.cs" />
|
||||
<Compile Include="Areas\AreaAttribute.cs" />
|
||||
<Compile Include="Areas\ReflectedRouteConstraintsActionDescriptorProvider.cs" />
|
||||
<Compile Include="BodyParameterInfo.cs" />
|
||||
<Compile Include="Controller.cs" />
|
||||
<Compile Include="ControllerDescriptor.cs" />
|
||||
|
|
@ -69,9 +72,8 @@
|
|||
<Compile Include="DefaultActionDiscoveryConventions.cs" />
|
||||
<Compile Include="DefaultActionSelector.cs" />
|
||||
<Compile Include="DefaultControllerAssemblyProvider.cs" />
|
||||
<Compile Include="DefaultControllerDescriptorFactory.cs" />
|
||||
<Compile Include="DefaultControllerFactory.cs" />
|
||||
<Compile Include="DefaultParameterDescriptorFactory.cs" />
|
||||
<Compile Include="ReflectedModelBuilder\ReflectedParameterModel.cs" />
|
||||
<Compile Include="Extensions\IEnumerableExtensions.cs" />
|
||||
<Compile Include="Filters\FilterItemOrderComparer.cs" />
|
||||
<Compile Include="Filters\TypeFilterAttribute.cs" />
|
||||
|
|
@ -129,13 +131,11 @@
|
|||
<Compile Include="IActionResult.cs" />
|
||||
<Compile Include="IActionSelector.cs" />
|
||||
<Compile Include="IControllerAssemblyProvider.cs" />
|
||||
<Compile Include="IControllerDescriptorFactory.cs" />
|
||||
<Compile Include="IControllerFactory.cs" />
|
||||
<Compile Include="Injector.cs" />
|
||||
<Compile Include="Internal\PropertyHelper.cs" />
|
||||
<Compile Include="Internal\TypeHelper.cs" />
|
||||
<Compile Include="Internal\UTF8EncodingWithoutBOM.cs" />
|
||||
<Compile Include="IParameterDescriptorFactory.cs" />
|
||||
<Compile Include="IUrlHelper.cs" />
|
||||
<Compile Include="JsonOutputFormatter.cs" />
|
||||
<Compile Include="MvcOptions.cs" />
|
||||
|
|
@ -233,4 +233,4 @@
|
|||
<Compile Include="ViewDataDictionaryOfT.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VSToolsPath)\AspNet\Microsoft.Web.AspNet.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
@ -2,7 +2,9 @@
|
|||
// 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 Microsoft.AspNet.Mvc.Core;
|
||||
using Microsoft.AspNet.Mvc.ReflectedModelBuilder;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
|
|
@ -10,6 +12,11 @@ namespace Microsoft.AspNet.Mvc
|
|||
{
|
||||
private AntiForgeryOptions _antiForgeryOptions = new AntiForgeryOptions();
|
||||
|
||||
public MvcOptions()
|
||||
{
|
||||
ApplicationModelConventions = new List<IReflectedApplicationModelConvention>();
|
||||
}
|
||||
|
||||
public AntiForgeryOptions AntiForgeryOptions
|
||||
{
|
||||
get
|
||||
|
|
@ -29,5 +36,7 @@ namespace Microsoft.AspNet.Mvc
|
|||
_antiForgeryOptions = value;
|
||||
}
|
||||
}
|
||||
|
||||
public List<IReflectedApplicationModelConvention> ApplicationModelConventions { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
#if K10
|
||||
using System.Reflection;
|
||||
#endif
|
||||
using Microsoft.AspNet.Mvc.ReflectedModelBuilder;
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
|
|
@ -14,23 +18,18 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
private readonly IControllerAssemblyProvider _controllerAssemblyProvider;
|
||||
private readonly IActionDiscoveryConventions _conventions;
|
||||
private readonly IControllerDescriptorFactory _controllerDescriptorFactory;
|
||||
private readonly IParameterDescriptorFactory _parameterDescriptorFactory;
|
||||
private readonly IEnumerable<FilterDescriptor> _globalFilters;
|
||||
private readonly IEnumerable<IFilter> _globalFilters;
|
||||
private readonly IEnumerable<IReflectedApplicationModelConvention> _modelConventions;
|
||||
|
||||
public ReflectedActionDescriptorProvider(IControllerAssemblyProvider controllerAssemblyProvider,
|
||||
IActionDiscoveryConventions conventions,
|
||||
IControllerDescriptorFactory controllerDescriptorFactory,
|
||||
IParameterDescriptorFactory parameterDescriptorFactory,
|
||||
IEnumerable<IFilter> globalFilters)
|
||||
IEnumerable<IFilter> globalFilters,
|
||||
IOptionsAccessor<MvcOptions> optionsAccessor)
|
||||
{
|
||||
_controllerAssemblyProvider = controllerAssemblyProvider;
|
||||
_conventions = conventions;
|
||||
_controllerDescriptorFactory = controllerDescriptorFactory;
|
||||
_parameterDescriptorFactory = parameterDescriptorFactory;
|
||||
var filters = globalFilters ?? Enumerable.Empty<IFilter>();
|
||||
|
||||
_globalFilters = filters.Select(f => new FilterDescriptor(f, FilterScope.Global));
|
||||
_globalFilters = globalFilters ?? Enumerable.Empty<IFilter>();
|
||||
_modelConventions = optionsAccessor.Options.ApplicationModelConventions;
|
||||
}
|
||||
|
||||
public int Order
|
||||
|
|
@ -44,34 +43,35 @@ namespace Microsoft.AspNet.Mvc
|
|||
callNext();
|
||||
}
|
||||
|
||||
public IEnumerable<ActionDescriptor> GetDescriptors()
|
||||
public IEnumerable<ReflectedActionDescriptor> GetDescriptors()
|
||||
{
|
||||
var assemblies = _controllerAssemblyProvider.CandidateAssemblies;
|
||||
var types = assemblies.SelectMany(a => a.DefinedTypes);
|
||||
var controllers = types.Where(_conventions.IsController);
|
||||
var controllerDescriptors = controllers
|
||||
.Select(t => _controllerDescriptorFactory.CreateControllerDescriptor(t))
|
||||
.ToArray();
|
||||
var model = BuildModel();
|
||||
|
||||
return GetDescriptors(controllerDescriptors);
|
||||
foreach (var convention in _modelConventions)
|
||||
{
|
||||
convention.OnModelCreated(model);
|
||||
}
|
||||
|
||||
return Build(model);
|
||||
}
|
||||
|
||||
// Internal for unit testing.
|
||||
internal IEnumerable<ActionDescriptor> GetDescriptors(IEnumerable<ControllerDescriptor> controllerDescriptors)
|
||||
public ReflectedApplicationModel BuildModel()
|
||||
{
|
||||
foreach (var cd in controllerDescriptors)
|
||||
{
|
||||
var controllerAttributes = cd.ControllerTypeInfo.GetCustomAttributes(inherit: true).ToArray();
|
||||
var globalAndControllerFilters =
|
||||
controllerAttributes.OfType<IFilter>()
|
||||
.Select(filter => new FilterDescriptor(filter, FilterScope.Controller))
|
||||
.Concat(_globalFilters)
|
||||
.OrderBy(d => d, FilterDescriptorOrderComparer.Comparer)
|
||||
.ToArray();
|
||||
var applicationModel = new ReflectedApplicationModel();
|
||||
applicationModel.Filters.AddRange(_globalFilters);
|
||||
|
||||
foreach (var methodInfo in cd.ControllerTypeInfo.AsType().GetMethods())
|
||||
var assemblies = _controllerAssemblyProvider.CandidateAssemblies;
|
||||
var types = assemblies.SelectMany(a => a.DefinedTypes);
|
||||
var controllerTypes = types.Where(_conventions.IsController);
|
||||
|
||||
foreach (var controllerType in controllerTypes)
|
||||
{
|
||||
var controllerModel = new ReflectedControllerModel(controllerType);
|
||||
applicationModel.Controllers.Add(controllerModel);
|
||||
|
||||
foreach (var methodInfo in controllerType.AsType().GetMethods())
|
||||
{
|
||||
var actionInfos = _conventions.GetActions(methodInfo, cd.ControllerTypeInfo);
|
||||
var actionInfos = _conventions.GetActions(methodInfo, controllerType);
|
||||
if (actionInfos == null)
|
||||
{
|
||||
continue;
|
||||
|
|
@ -79,62 +79,140 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
foreach (var actionInfo in actionInfos)
|
||||
{
|
||||
yield return BuildDescriptor(cd, methodInfo, actionInfo, globalAndControllerFilters);
|
||||
var actionModel = new ReflectedActionModel(methodInfo);
|
||||
|
||||
actionModel.ActionName = actionInfo.ActionName;
|
||||
actionModel.IsActionNameMatchRequired = actionInfo.RequireActionNameMatch;
|
||||
actionModel.HttpMethods.AddRange(actionInfo.HttpMethods ?? Enumerable.Empty<string>());
|
||||
|
||||
foreach (var parameter in methodInfo.GetParameters())
|
||||
{
|
||||
actionModel.Parameters.Add(new ReflectedParameterModel(parameter));
|
||||
}
|
||||
|
||||
controllerModel.Actions.Add(actionModel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return applicationModel;
|
||||
}
|
||||
|
||||
private ReflectedActionDescriptor BuildDescriptor(ControllerDescriptor controllerDescriptor,
|
||||
MethodInfo methodInfo,
|
||||
ActionInfo actionInfo,
|
||||
FilterDescriptor[] globalAndControllerFilters)
|
||||
private bool HasConstraint(List<RouteDataActionConstraint> constraints, string routeKey)
|
||||
{
|
||||
var ad = new ReflectedActionDescriptor
|
||||
return constraints.Any(
|
||||
rc => string.Equals(rc.RouteKey, routeKey, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
public List<ReflectedActionDescriptor> Build(ReflectedApplicationModel model)
|
||||
{
|
||||
var actions = new List<ReflectedActionDescriptor>();
|
||||
|
||||
var removalConstraints = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var controller in model.Controllers)
|
||||
{
|
||||
RouteConstraints = new List<RouteDataActionConstraint>
|
||||
var controllerDescriptor = new ControllerDescriptor(controller.ControllerType);
|
||||
foreach (var action in controller.Actions)
|
||||
{
|
||||
new RouteDataActionConstraint("controller", controllerDescriptor.Name)
|
||||
},
|
||||
var parameterDescriptors = new List<ParameterDescriptor>();
|
||||
foreach (var parameter in action.Parameters)
|
||||
{
|
||||
var isFromBody = parameter.Attributes.OfType<FromBodyAttribute>().Any();
|
||||
|
||||
Name = actionInfo.ActionName,
|
||||
ControllerDescriptor = controllerDescriptor,
|
||||
MethodInfo = methodInfo,
|
||||
};
|
||||
parameterDescriptors.Add(new ParameterDescriptor()
|
||||
{
|
||||
Name = parameter.ParameterName,
|
||||
IsOptional = parameter.IsOptional,
|
||||
|
||||
var httpMethods = actionInfo.HttpMethods;
|
||||
if (httpMethods != null && httpMethods.Length > 0)
|
||||
ParameterBindingInfo = isFromBody
|
||||
? null
|
||||
: new ParameterBindingInfo(
|
||||
parameter.ParameterName,
|
||||
parameter.ParameterInfo.ParameterType),
|
||||
|
||||
BodyParameterInfo = isFromBody
|
||||
? new BodyParameterInfo(parameter.ParameterInfo.ParameterType)
|
||||
: null
|
||||
});
|
||||
}
|
||||
|
||||
var actionDescriptor = new ReflectedActionDescriptor()
|
||||
{
|
||||
Name = action.ActionName,
|
||||
ControllerDescriptor = controllerDescriptor,
|
||||
MethodInfo = action.ActionMethod,
|
||||
Parameters = new List<ParameterDescriptor>(),
|
||||
RouteConstraints = new List<RouteDataActionConstraint>(),
|
||||
};
|
||||
|
||||
var httpMethods = action.HttpMethods;
|
||||
if (httpMethods != null && httpMethods.Count > 0)
|
||||
{
|
||||
actionDescriptor.MethodConstraints = new List<HttpMethodConstraint>()
|
||||
{
|
||||
new HttpMethodConstraint(httpMethods)
|
||||
};
|
||||
}
|
||||
|
||||
actionDescriptor.RouteConstraints.Add(new RouteDataActionConstraint(
|
||||
"controller",
|
||||
controller.ControllerName));
|
||||
|
||||
if (action.IsActionNameMatchRequired)
|
||||
{
|
||||
actionDescriptor.RouteConstraints.Add(new RouteDataActionConstraint(
|
||||
"action",
|
||||
action.ActionName));
|
||||
}
|
||||
else
|
||||
{
|
||||
actionDescriptor.RouteConstraints.Add(new RouteDataActionConstraint(
|
||||
"action",
|
||||
RouteKeyHandling.DenyKey));
|
||||
}
|
||||
|
||||
foreach (var constraintAttribute in controller.RouteConstraints)
|
||||
{
|
||||
if (constraintAttribute.BlockNonAttributedActions)
|
||||
{
|
||||
removalConstraints.Add(constraintAttribute.RouteKey);
|
||||
}
|
||||
|
||||
// Skip duplicates
|
||||
if (!HasConstraint(actionDescriptor.RouteConstraints, constraintAttribute.RouteKey))
|
||||
{
|
||||
actionDescriptor.RouteConstraints.Add(new RouteDataActionConstraint(
|
||||
constraintAttribute.RouteKey,
|
||||
constraintAttribute.RouteValue));
|
||||
}
|
||||
}
|
||||
|
||||
actionDescriptor.FilterDescriptors =
|
||||
action.Filters.Select(f => new FilterDescriptor(f, FilterScope.Action))
|
||||
.Concat(controller.Filters.Select(f => new FilterDescriptor(f, FilterScope.Controller)))
|
||||
.Concat(model.Filters.Select(f => new FilterDescriptor(f, FilterScope.Global)))
|
||||
.OrderBy(d => d, FilterDescriptorOrderComparer.Comparer)
|
||||
.ToList();
|
||||
|
||||
actions.Add(actionDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var actionDescriptor in actions)
|
||||
{
|
||||
ad.MethodConstraints = new List<HttpMethodConstraint>
|
||||
foreach (var key in removalConstraints)
|
||||
{
|
||||
new HttpMethodConstraint(httpMethods)
|
||||
};
|
||||
if (!HasConstraint(actionDescriptor.RouteConstraints, key))
|
||||
{
|
||||
actionDescriptor.RouteConstraints.Add(new RouteDataActionConstraint(
|
||||
key,
|
||||
RouteKeyHandling.DenyKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (actionInfo.RequireActionNameMatch)
|
||||
{
|
||||
ad.RouteConstraints.Add(new RouteDataActionConstraint("action", actionInfo.ActionName));
|
||||
}
|
||||
else
|
||||
{
|
||||
ad.RouteConstraints.Add(new RouteDataActionConstraint("action", RouteKeyHandling.DenyKey));
|
||||
}
|
||||
|
||||
ad.Parameters = methodInfo.GetParameters()
|
||||
.Select(p => _parameterDescriptorFactory.GetDescriptor(p))
|
||||
.ToList();
|
||||
|
||||
var attributes = methodInfo.GetCustomAttributes(inherit: true).ToArray();
|
||||
|
||||
var filtersFromAction = attributes
|
||||
.OfType<IFilter>()
|
||||
.Select(filter => new FilterDescriptor(filter, FilterScope.Action));
|
||||
|
||||
ad.FilterDescriptors = filtersFromAction.Concat(globalAndControllerFilters)
|
||||
.OrderBy(d => d, FilterDescriptorOrderComparer.Comparer)
|
||||
.ToList();
|
||||
|
||||
return ad;
|
||||
return actions;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ReflectedModelBuilder
|
||||
{
|
||||
public interface IReflectedApplicationModelConvention
|
||||
{
|
||||
void OnModelCreated([NotNull] ReflectedApplicationModel model);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ReflectedModelBuilder
|
||||
{
|
||||
public class ReflectedActionModel
|
||||
{
|
||||
public ReflectedActionModel([NotNull] MethodInfo actionMethod)
|
||||
{
|
||||
ActionMethod = actionMethod;
|
||||
|
||||
// CoreCLR returns IEnumerable<Attribute> from GetCustomAttributes - the OfType<object>
|
||||
// is needed to so that the result of ToList() is List<object>
|
||||
Attributes = actionMethod.GetCustomAttributes(inherit: true).OfType<object>().ToList();
|
||||
|
||||
Filters = Attributes.OfType<IFilter>().ToList();
|
||||
|
||||
HttpMethods = new List<string>();
|
||||
Parameters = new List<ReflectedParameterModel>();
|
||||
}
|
||||
|
||||
public MethodInfo ActionMethod { get; private set; }
|
||||
|
||||
public string ActionName { get; set; }
|
||||
|
||||
public List<object> Attributes { get; private set; }
|
||||
|
||||
public List<IFilter> Filters { get; private set; }
|
||||
|
||||
public List<string> HttpMethods { get; private set; }
|
||||
|
||||
public bool IsActionNameMatchRequired { get; set; }
|
||||
|
||||
public List<ReflectedParameterModel> Parameters { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ReflectedModelBuilder
|
||||
{
|
||||
public class ReflectedApplicationModel
|
||||
{
|
||||
public ReflectedApplicationModel()
|
||||
{
|
||||
Controllers = new List<ReflectedControllerModel>();
|
||||
Filters = new List<IFilter>();
|
||||
}
|
||||
|
||||
public List<ReflectedControllerModel> Controllers { get; private set; }
|
||||
|
||||
public List<IFilter> Filters { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ReflectedModelBuilder
|
||||
{
|
||||
public class ReflectedControllerModel
|
||||
{
|
||||
public ReflectedControllerModel([NotNull] TypeInfo controllerType)
|
||||
{
|
||||
ControllerType = controllerType;
|
||||
|
||||
Actions = new List<ReflectedActionModel>();
|
||||
|
||||
// CoreCLR returns IEnumerable<Attribute> from GetCustomAttributes - the OfType<object>
|
||||
// is needed to so that the result of ToList() is List<object>
|
||||
Attributes = ControllerType.GetCustomAttributes(inherit: true).OfType<object>().ToList();
|
||||
|
||||
Filters = Attributes.OfType<IFilter>().ToList();
|
||||
RouteConstraints = Attributes.OfType<RouteConstraintAttribute>().ToList();
|
||||
|
||||
ControllerName = controllerType.Name.EndsWith("Controller", StringComparison.Ordinal)
|
||||
? controllerType.Name.Substring(0, controllerType.Name.Length - "Controller".Length)
|
||||
: controllerType.Name;
|
||||
}
|
||||
|
||||
public List<ReflectedActionModel> Actions { get; private set; }
|
||||
|
||||
public List<object> Attributes { get; private set; }
|
||||
|
||||
public string ControllerName { get; set; }
|
||||
|
||||
public TypeInfo ControllerType { get; private set; }
|
||||
|
||||
public List<IFilter> Filters { get; private set; }
|
||||
|
||||
public List<RouteConstraintAttribute> RouteConstraints { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ReflectedModelBuilder
|
||||
{
|
||||
public class ReflectedParameterModel
|
||||
{
|
||||
public ReflectedParameterModel(ParameterInfo parameterInfo)
|
||||
{
|
||||
ParameterInfo = parameterInfo;
|
||||
|
||||
// CoreCLR returns IEnumerable<Attribute> from GetCustomAttributes - the OfType<object>
|
||||
// is needed to so that the result of ToList() is List<object>
|
||||
Attributes = parameterInfo.GetCustomAttributes(inherit: true).OfType<object>().ToList();
|
||||
|
||||
ParameterName = parameterInfo.Name;
|
||||
IsOptional = ParameterInfo.HasDefaultValue;
|
||||
}
|
||||
|
||||
public List<object> Attributes { get; private set; }
|
||||
|
||||
public bool IsOptional { get; set; }
|
||||
|
||||
public ParameterInfo ParameterInfo { get; private set; }
|
||||
|
||||
public string ParameterName { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -26,10 +26,8 @@ namespace Microsoft.AspNet.Mvc
|
|||
var describe = new ServiceDescriber(configuration);
|
||||
|
||||
yield return describe.Transient<IControllerFactory, DefaultControllerFactory>();
|
||||
yield return describe.Transient<IControllerDescriptorFactory, DefaultControllerDescriptorFactory>();
|
||||
yield return describe.Scoped<IActionSelector, DefaultActionSelector>();
|
||||
yield return describe.Transient<IActionInvokerFactory, ActionInvokerFactory>();
|
||||
yield return describe.Transient<IParameterDescriptorFactory, DefaultParameterDescriptorFactory>();
|
||||
yield return describe.Transient<IControllerAssemblyProvider, DefaultControllerAssemblyProvider>();
|
||||
yield return describe.Transient<IActionDiscoveryConventions, DefaultActionDiscoveryConventions>();
|
||||
|
||||
|
|
@ -43,8 +41,6 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
yield return describe.Transient<INestedProvider<ActionDescriptorProviderContext>,
|
||||
ReflectedActionDescriptorProvider>();
|
||||
yield return describe.Transient<INestedProvider<ActionDescriptorProviderContext>,
|
||||
ReflectedRouteConstraintsActionDescriptorProvider>();
|
||||
yield return describe.Transient<INestedProvider<ActionInvokerProviderContext>,
|
||||
ReflectedActionInvokerProvider>();
|
||||
yield return describe.Singleton<IActionDescriptorsCollectionProvider,
|
||||
|
|
|
|||
|
|
@ -10,19 +10,17 @@ using System.Linq;
|
|||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Routing;
|
||||
using Microsoft.Framework.DependencyInjection;
|
||||
using Microsoft.Framework.DependencyInjection.NestedProviders;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
using Microsoft.AspNet.Routing;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Core.Test
|
||||
namespace Microsoft.AspNet.Mvc.Test
|
||||
{
|
||||
public class ActionAttributeTests
|
||||
{
|
||||
private DefaultActionDiscoveryConventions _actionDiscoveryConventions = new DefaultActionDiscoveryConventions();
|
||||
private IControllerDescriptorFactory _controllerDescriptorFactory = new DefaultControllerDescriptorFactory();
|
||||
private IParameterDescriptorFactory _parameterDescriptorFactory = new DefaultParameterDescriptorFactory();
|
||||
private IEnumerable<Assembly> _controllerAssemblies = new[] { Assembly.GetExecutingAssembly() };
|
||||
|
||||
[Theory]
|
||||
|
|
@ -217,12 +215,12 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
{
|
||||
var controllerAssemblyProvider = new Mock<IControllerAssemblyProvider>();
|
||||
controllerAssemblyProvider.SetupGet(x => x.CandidateAssemblies).Returns(_controllerAssemblies);
|
||||
|
||||
return new ReflectedActionDescriptorProvider(
|
||||
controllerAssemblyProvider.Object,
|
||||
actionDiscoveryConventions,
|
||||
_controllerDescriptorFactory,
|
||||
_parameterDescriptorFactory,
|
||||
null);
|
||||
null,
|
||||
new MockMvcOptionsAccessor());
|
||||
}
|
||||
|
||||
private static HttpContext GetHttpContext(string httpMethod)
|
||||
|
|
|
|||
|
|
@ -15,13 +15,11 @@ using Microsoft.Framework.DependencyInjection.NestedProviders;
|
|||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Core.Test
|
||||
namespace Microsoft.AspNet.Mvc.Test
|
||||
{
|
||||
public class ActionSelectionConventionTests
|
||||
{
|
||||
private DefaultActionDiscoveryConventions _actionDiscoveryConventions = new DefaultActionDiscoveryConventions();
|
||||
private IControllerDescriptorFactory _controllerDescriptorFactory = new DefaultControllerDescriptorFactory();
|
||||
private IParameterDescriptorFactory _parameterDescriptorFactory = new DefaultParameterDescriptorFactory();
|
||||
private IEnumerable<Assembly> _controllerAssemblies = new[] { Assembly.GetExecutingAssembly() };
|
||||
|
||||
[Theory]
|
||||
|
|
@ -188,9 +186,8 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
return new ReflectedActionDescriptorProvider(
|
||||
controllerAssemblyProvider.Object,
|
||||
actionDiscoveryConventions,
|
||||
_controllerDescriptorFactory,
|
||||
_parameterDescriptorFactory,
|
||||
null);
|
||||
null,
|
||||
new MockMvcOptionsAccessor());
|
||||
}
|
||||
|
||||
private static HttpContext GetHttpContext(string httpMethod)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,10 @@
|
|||
<Compile Include="ActionResults\RedirectResultTest.cs" />
|
||||
<Compile Include="ActionSelectionConventionTests.cs" />
|
||||
<Compile Include="AntiXsrf\AntiForgeryOptionsTests.cs" />
|
||||
<Compile Include="ReflectedModelBuilder\ReflectedParameterModelTests.cs" />
|
||||
<Compile Include="ReflectedModelBuilder\ReflectedActionModelTests.cs" />
|
||||
<Compile Include="ReflectedModelBuilder\ReflectedControllerModelTests.cs" />
|
||||
<Compile Include="MockMvcOptionsAccessor.cs" />
|
||||
<Compile Include="MvcOptionsTests.cs" />
|
||||
<Compile Include="AntiXsrf\AntiForgeryTokenSerializerTest.cs" />
|
||||
<Compile Include="AntiXsrf\ITokenProvider.cs" />
|
||||
|
|
@ -60,6 +64,7 @@
|
|||
<Compile Include="KnownRouteValueConstraintTests.cs" />
|
||||
<Compile Include="TestController.cs" />
|
||||
<Compile Include="TypeHelperTest.cs" />
|
||||
<Compile Include="StaticActionDiscoveryConventions.cs" />
|
||||
<Compile Include="UrlHelperTest.cs" />
|
||||
<Compile Include="ViewResultTest.cs" />
|
||||
<Compile Include="ViewComponentTests.cs" />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using Microsoft.Framework.OptionsModel;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Test
|
||||
{
|
||||
public class MockMvcOptionsAccessor : IOptionsAccessor<MvcOptions>
|
||||
{
|
||||
public MockMvcOptionsAccessor()
|
||||
{
|
||||
Options = new MvcOptions();
|
||||
}
|
||||
|
||||
public MvcOptions Options { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,21 +1,17 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
namespace Microsoft.AspNet.Mvc.Test
|
||||
{
|
||||
public class ReflectedActionDescriptorProviderTests
|
||||
{
|
||||
private DefaultActionDiscoveryConventions _actionDiscoveryConventions =
|
||||
new DefaultActionDiscoveryConventions();
|
||||
private IControllerDescriptorFactory _controllerDescriptorFactory = new DefaultControllerDescriptorFactory();
|
||||
private IParameterDescriptorFactory _parameterDescriptorFactory = new DefaultParameterDescriptorFactory();
|
||||
|
||||
[Fact]
|
||||
public void GetDescriptors_GetsDescriptorsOnlyForValidActionsInBaseAndDerivedController()
|
||||
{
|
||||
|
|
@ -130,25 +126,209 @@ namespace Microsoft.AspNet.Mvc
|
|||
Assert.DoesNotContain("PrivateStaticMethod", actionNames);
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetActionNamesFromDerivedController()
|
||||
[Fact]
|
||||
public void GetDescriptors_IncludesFilters()
|
||||
{
|
||||
return GetDescriptors(typeof(DerivedController).GetTypeInfo()).Select(a => a.Name);
|
||||
// Arrange
|
||||
var globalFilter = new MyFilterAttribute(1);
|
||||
var provider = GetProvider(typeof(FiltersController).GetTypeInfo(), new IFilter[]
|
||||
{
|
||||
globalFilter,
|
||||
});
|
||||
|
||||
// Act
|
||||
var descriptors = provider.GetDescriptors();
|
||||
var descriptor = Assert.Single(descriptors);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(3, descriptor.FilterDescriptors.Count);
|
||||
|
||||
var filter1 = descriptor.FilterDescriptors[2];
|
||||
Assert.Same(globalFilter, filter1.Filter);
|
||||
Assert.Equal(FilterScope.Global, filter1.Scope);
|
||||
|
||||
var filter2 = descriptor.FilterDescriptors[1];
|
||||
Assert.Equal(2, Assert.IsType<MyFilterAttribute>(filter2.Filter).Value);
|
||||
Assert.Equal(FilterScope.Controller, filter2.Scope);
|
||||
|
||||
var filter3 = descriptor.FilterDescriptors[0];
|
||||
Assert.Equal(3, Assert.IsType<MyFilterAttribute>(filter3.Filter).Value); ;
|
||||
Assert.Equal(FilterScope.Action, filter3.Scope);
|
||||
}
|
||||
|
||||
private IEnumerable<ActionDescriptor> GetDescriptors(TypeInfo controllerTypeInfo)
|
||||
[Fact]
|
||||
public void GetDescriptors_AddsHttpMethodConstraints()
|
||||
{
|
||||
var provider = new ReflectedActionDescriptorProvider(null,
|
||||
_actionDiscoveryConventions,
|
||||
_controllerDescriptorFactory,
|
||||
_parameterDescriptorFactory,
|
||||
null);
|
||||
var testControllers = new TypeInfo[]
|
||||
// Arrange
|
||||
var provider = GetProvider(typeof(HttpMethodController).GetTypeInfo());
|
||||
|
||||
// Act
|
||||
var descriptors = provider.GetDescriptors();
|
||||
var descriptor = Assert.Single(descriptors);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("OnlyPost", descriptor.Name);
|
||||
|
||||
Assert.Single(descriptor.MethodConstraints);
|
||||
Assert.Equal(new string[] { "POST" }, descriptor.MethodConstraints[0].HttpMethods);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDescriptors_WithRouteDataConstraint_WithBlockNonAttributedActions()
|
||||
{
|
||||
// Arrange & Act
|
||||
var descriptors = GetDescriptors(
|
||||
typeof(HttpMethodController).GetTypeInfo(),
|
||||
typeof(BlockNonAttributedActionsController).GetTypeInfo()).ToArray();
|
||||
|
||||
var descriptorWithoutConstraint = Assert.Single(
|
||||
descriptors,
|
||||
ad => ad.RouteConstraints.Any(
|
||||
c => c.RouteKey == "key" && c.KeyHandling == RouteKeyHandling.DenyKey));
|
||||
|
||||
var descriptorWithConstraint = Assert.Single(
|
||||
descriptors,
|
||||
ad => ad.RouteConstraints.Any(
|
||||
c =>
|
||||
c.KeyHandling == RouteKeyHandling.RequireKey &&
|
||||
c.RouteKey == "key" &&
|
||||
c.RouteValue == "value"));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, descriptors.Length);
|
||||
|
||||
Assert.Equal(3, descriptorWithConstraint.RouteConstraints.Count);
|
||||
Assert.Single(
|
||||
descriptorWithConstraint.RouteConstraints,
|
||||
c =>
|
||||
c.RouteKey == "controller" &&
|
||||
c.RouteValue == "BlockNonAttributedActions");
|
||||
Assert.Single(
|
||||
descriptorWithConstraint.RouteConstraints,
|
||||
c =>
|
||||
c.RouteKey == "action" &&
|
||||
c.RouteValue == "Edit");
|
||||
|
||||
Assert.Equal(3, descriptorWithoutConstraint.RouteConstraints.Count);
|
||||
Assert.Single(
|
||||
descriptorWithoutConstraint.RouteConstraints,
|
||||
c =>
|
||||
c.RouteKey == "controller" &&
|
||||
c.RouteValue == "HttpMethod");
|
||||
Assert.Single(
|
||||
descriptorWithoutConstraint.RouteConstraints,
|
||||
c =>
|
||||
c.RouteKey == "action" &&
|
||||
c.RouteValue == "OnlyPost");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetDescriptors_WithRouteDataConstraint_WithoutBlockNonAttributedActions()
|
||||
{
|
||||
// Arrange & Act
|
||||
var descriptors = GetDescriptors(
|
||||
typeof(HttpMethodController).GetTypeInfo(),
|
||||
typeof(DontBlockNonAttributedActionsController).GetTypeInfo()).ToArray();
|
||||
|
||||
var descriptorWithConstraint = Assert.Single(
|
||||
descriptors,
|
||||
ad => ad.RouteConstraints.Any(
|
||||
c =>
|
||||
c.KeyHandling == RouteKeyHandling.RequireKey &&
|
||||
c.RouteKey == "key" &&
|
||||
c.RouteValue == "value"));
|
||||
|
||||
var descriptorWithoutConstraint = Assert.Single(
|
||||
descriptors,
|
||||
ad => !ad.RouteConstraints.Any(c => c.RouteKey == "key"));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, descriptors.Length);
|
||||
|
||||
Assert.Equal(3, descriptorWithConstraint.RouteConstraints.Count);
|
||||
Assert.Single(
|
||||
descriptorWithConstraint.RouteConstraints,
|
||||
c =>
|
||||
c.RouteKey == "controller" &&
|
||||
c.RouteValue == "DontBlockNonAttributedActions");
|
||||
Assert.Single(
|
||||
descriptorWithConstraint.RouteConstraints,
|
||||
c =>
|
||||
c.RouteKey == "action" &&
|
||||
c.RouteValue == "Create");
|
||||
|
||||
Assert.Equal(2, descriptorWithoutConstraint.RouteConstraints.Count);
|
||||
Assert.Single(
|
||||
descriptorWithoutConstraint.RouteConstraints,
|
||||
c =>
|
||||
c.RouteKey == "controller" &&
|
||||
c.RouteValue == "HttpMethod");
|
||||
Assert.Single(
|
||||
descriptorWithoutConstraint.RouteConstraints,
|
||||
c =>
|
||||
c.RouteKey == "action" &&
|
||||
c.RouteValue == "OnlyPost");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildModel_IncludesGlobalFilters()
|
||||
{
|
||||
// Arrange
|
||||
var filter = new MyFilterAttribute(1);
|
||||
var provider = GetProvider(typeof(BaseController).GetTypeInfo(), new IFilter[]
|
||||
{
|
||||
controllerTypeInfo,
|
||||
};
|
||||
var controllerDescriptors = testControllers
|
||||
.Select(t => _controllerDescriptorFactory.CreateControllerDescriptor(t));
|
||||
return provider.GetDescriptors(controllerDescriptors);
|
||||
filter,
|
||||
});
|
||||
|
||||
// Act
|
||||
var model = provider.BuildModel();
|
||||
|
||||
// Assert
|
||||
var filters = model.Filters;
|
||||
Assert.Same(filter, Assert.Single(filters));
|
||||
}
|
||||
|
||||
private IEnumerable<string> GetActionNamesFromDerivedController()
|
||||
{
|
||||
return GetDescriptors(typeof(DerivedController).GetTypeInfo()).Select(a => a.Name).ToArray();
|
||||
}
|
||||
|
||||
private ReflectedActionDescriptorProvider GetProvider(
|
||||
TypeInfo controllerTypeInfo,
|
||||
IEnumerable<IFilter> filters = null)
|
||||
{
|
||||
var assemblyProvider = new Mock<IControllerAssemblyProvider>();
|
||||
assemblyProvider
|
||||
.SetupGet(ap => ap.CandidateAssemblies)
|
||||
.Returns(new Assembly[] { controllerTypeInfo.Assembly });
|
||||
|
||||
var conventions = new StaticActionDiscoveryConventions(controllerTypeInfo);
|
||||
|
||||
var provider = new ReflectedActionDescriptorProvider(
|
||||
assemblyProvider.Object,
|
||||
conventions,
|
||||
filters,
|
||||
new MockMvcOptionsAccessor());
|
||||
|
||||
return provider;
|
||||
}
|
||||
|
||||
private IEnumerable<ActionDescriptor> GetDescriptors(params TypeInfo[] controllerTypeInfos)
|
||||
{
|
||||
var assemblyProvider = new Mock<IControllerAssemblyProvider>();
|
||||
assemblyProvider
|
||||
.SetupGet(ap => ap.CandidateAssemblies)
|
||||
.Returns(controllerTypeInfos.Select(cti => cti.Assembly).Distinct());
|
||||
|
||||
var conventions = new StaticActionDiscoveryConventions(controllerTypeInfos);
|
||||
|
||||
var provider = new ReflectedActionDescriptorProvider(
|
||||
assemblyProvider.Object,
|
||||
conventions,
|
||||
null,
|
||||
new MockMvcOptionsAccessor());
|
||||
|
||||
return provider.GetDescriptors();
|
||||
}
|
||||
|
||||
private class DerivedController : BaseController
|
||||
|
|
@ -218,5 +398,56 @@ namespace Microsoft.AspNet.Mvc
|
|||
return base.Redirect(url + "#RedirectOverride");
|
||||
}
|
||||
}
|
||||
|
||||
[MyFilter(2)]
|
||||
private class FiltersController
|
||||
{
|
||||
[MyFilter(3)]
|
||||
public void FilterAction()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class MyFilterAttribute : Attribute, IFilter
|
||||
{
|
||||
public MyFilterAttribute(int value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public int Value { get; private set; }
|
||||
}
|
||||
|
||||
private class HttpMethodController
|
||||
{
|
||||
[HttpPost]
|
||||
public void OnlyPost()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[MyRouteConstraintAttribute(blockNonAttributedActions: true)]
|
||||
private class BlockNonAttributedActionsController
|
||||
{
|
||||
public void Edit()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[MyRouteConstraintAttribute(blockNonAttributedActions: false)]
|
||||
private class DontBlockNonAttributedActionsController
|
||||
{
|
||||
public void Create()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class MyRouteConstraintAttribute : RouteConstraintAttribute
|
||||
{
|
||||
public MyRouteConstraintAttribute(bool blockNonAttributedActions)
|
||||
: base("key", "value", blockNonAttributedActions)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ReflectedModelBuilder.Test
|
||||
{
|
||||
public class ReflectedActionModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void ReflectedActionModel_PopulatesAttributes()
|
||||
{
|
||||
// Arrange
|
||||
var actionMethod = typeof(BlogController).GetMethod("Edit");
|
||||
|
||||
// Act
|
||||
var model = new ReflectedActionModel(actionMethod);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, model.Attributes.Count);
|
||||
Assert.Single(model.Attributes, a => a is MyFilterAttribute);
|
||||
Assert.Single(model.Attributes, a => a is MyOtherAttribute);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReflectedActionModel_PopulatesFilters()
|
||||
{
|
||||
// Arrange
|
||||
var actionMethod = typeof(BlogController).GetMethod("Edit");
|
||||
|
||||
// Act
|
||||
var model = new ReflectedActionModel(actionMethod);
|
||||
|
||||
// Assert
|
||||
Assert.Single(model.Filters);
|
||||
Assert.IsType<MyFilterAttribute>(model.Filters[0]);
|
||||
}
|
||||
|
||||
private class BlogController
|
||||
{
|
||||
[MyOther]
|
||||
[MyFilter]
|
||||
public void Edit()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class MyFilterAttribute : Attribute, IFilter
|
||||
{
|
||||
}
|
||||
|
||||
private class MyOtherAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ReflectedModelBuilder.Test
|
||||
{
|
||||
public class ReflectedControllerModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void ReflectedControllerModel_PopulatesAttributes()
|
||||
{
|
||||
// Arrange
|
||||
var controllerType = typeof(BlogController);
|
||||
|
||||
// Act
|
||||
var model = new ReflectedControllerModel(controllerType.GetTypeInfo());
|
||||
|
||||
// Assert
|
||||
Assert.Equal(3, model.Attributes.Count);
|
||||
|
||||
Assert.Single(model.Attributes, a => a is MyOtherAttribute);
|
||||
Assert.Single(model.Attributes, a => a is MyFilterAttribute);
|
||||
Assert.Single(model.Attributes, a => a is MyRouteConstraintAttribute);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReflectedControllerModel_PopulatesFilters()
|
||||
{
|
||||
// Arrange
|
||||
var controllerType = typeof(BlogController);
|
||||
|
||||
// Act
|
||||
var model = new ReflectedControllerModel(controllerType.GetTypeInfo());
|
||||
|
||||
// Assert
|
||||
Assert.Single(model.Filters);
|
||||
Assert.IsType<MyFilterAttribute>(model.Filters[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReflectedControllerModel_PopulatesRouteConstraintAttributes()
|
||||
{
|
||||
// Arrange
|
||||
var controllerType = typeof(BlogController);
|
||||
|
||||
// Act
|
||||
var model = new ReflectedControllerModel(controllerType.GetTypeInfo());
|
||||
|
||||
// Assert
|
||||
Assert.Single(model.RouteConstraints);
|
||||
Assert.IsType<MyRouteConstraintAttribute>(model.RouteConstraints[0]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReflectedControllerModel_ComputesControllerName()
|
||||
{
|
||||
// Arrange
|
||||
var controllerType = typeof(BlogController);
|
||||
|
||||
// Act
|
||||
var model = new ReflectedControllerModel(controllerType.GetTypeInfo());
|
||||
|
||||
// Assert
|
||||
Assert.Equal("Blog", model.ControllerName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReflectedControllerModel_ComputesControllerName_WithoutSuffix()
|
||||
{
|
||||
// Arrange
|
||||
var controllerType = typeof(Store);
|
||||
|
||||
// Act
|
||||
var model = new ReflectedControllerModel(controllerType.GetTypeInfo());
|
||||
|
||||
// Assert
|
||||
Assert.Equal("Store", model.ControllerName);
|
||||
}
|
||||
|
||||
[MyOther]
|
||||
[MyFilter]
|
||||
[MyRouteConstraint]
|
||||
private class BlogController
|
||||
{
|
||||
}
|
||||
|
||||
private class Store
|
||||
{
|
||||
}
|
||||
|
||||
private class MyRouteConstraintAttribute : RouteConstraintAttribute
|
||||
{
|
||||
public MyRouteConstraintAttribute()
|
||||
: base("MyRouteConstraint", "MyRouteConstraint", false)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class MyFilterAttribute : Attribute, IFilter
|
||||
{
|
||||
}
|
||||
|
||||
private class MyOtherAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.ReflectedModelBuilder.Test
|
||||
{
|
||||
public class ReflectedParameterModelTests
|
||||
{
|
||||
[Fact]
|
||||
public void ReflectedParameterModel_PopulatesAttributes()
|
||||
{
|
||||
// Arrange
|
||||
var parameterInfo = typeof(BlogController).GetMethod("Edit").GetParameters()[0];
|
||||
|
||||
// Act
|
||||
var model = new ReflectedParameterModel(parameterInfo);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1, model.Attributes.Count);
|
||||
Assert.Single(model.Attributes, a => a is MyOtherAttribute);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReflectedParameterModel_PopulatesParameterName()
|
||||
{
|
||||
// Arrange
|
||||
var parameterInfo = typeof(BlogController).GetMethod("Edit").GetParameters()[0];
|
||||
|
||||
// Act
|
||||
var model = new ReflectedParameterModel(parameterInfo);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("name", model.ParameterName);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0, false)]
|
||||
[InlineData(1, true)]
|
||||
public void ReflectedParameterModel_PopulatesIsOptional(int parameterIndex, bool expected)
|
||||
{
|
||||
// Arrange
|
||||
var parameterInfo = typeof(BlogController).GetMethod("Edit").GetParameters()[parameterIndex];
|
||||
|
||||
// Act
|
||||
var model = new ReflectedParameterModel(parameterInfo);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expected, model.IsOptional);
|
||||
}
|
||||
|
||||
private class BlogController
|
||||
{
|
||||
public void Edit([MyOther] string name, int age = 17)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class MyOtherAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Test
|
||||
{
|
||||
/// <summary>
|
||||
/// An implementation of DefaultActionDiscoveryConventions that only allows controllers
|
||||
/// from a fixed set of types.
|
||||
/// </summary>
|
||||
public class StaticActionDiscoveryConventions : DefaultActionDiscoveryConventions
|
||||
{
|
||||
public StaticActionDiscoveryConventions(params TypeInfo[] controllerTypes)
|
||||
{
|
||||
ControllerTypes = new List<TypeInfo>(controllerTypes ?? Enumerable.Empty<TypeInfo>());
|
||||
}
|
||||
|
||||
public List<TypeInfo> ControllerTypes { get; private set; }
|
||||
|
||||
public override bool IsController([NotNull]TypeInfo typeInfo)
|
||||
{
|
||||
return ControllerTypes.Contains(typeInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue