ReadOnly attributes for Action, Controller, and Parameter
This commit is contained in:
parent
38b3b61485
commit
7b58d569eb
|
|
@ -9,12 +9,13 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
{
|
||||
public class ActionModel
|
||||
{
|
||||
public ActionModel([NotNull] MethodInfo actionMethod)
|
||||
public ActionModel([NotNull] MethodInfo actionMethod,
|
||||
[NotNull] IReadOnlyList<object> attributes)
|
||||
{
|
||||
ActionMethod = actionMethod;
|
||||
|
||||
ApiExplorer = new ApiExplorerModel();
|
||||
Attributes = new List<object>();
|
||||
Attributes = new List<object>(attributes);
|
||||
ActionConstraints = new List<IActionConstraintMetadata>();
|
||||
Filters = new List<IFilter>();
|
||||
HttpMethods = new List<string>();
|
||||
|
|
@ -45,9 +46,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
AttributeRouteModel = new AttributeRouteModel(other.AttributeRouteModel);
|
||||
}
|
||||
}
|
||||
|
||||
public List<IActionConstraintMetadata> ActionConstraints { get; private set; }
|
||||
|
||||
public MethodInfo ActionMethod { get; private set; }
|
||||
public MethodInfo ActionMethod { get; }
|
||||
|
||||
public string ActionName { get; set; }
|
||||
|
||||
|
|
@ -60,7 +62,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
/// </remarks>
|
||||
public ApiExplorerModel ApiExplorer { get; set; }
|
||||
|
||||
public List<object> Attributes { get; private set; }
|
||||
public IReadOnlyList<object> Attributes { get; }
|
||||
|
||||
public ControllerModel Controller { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
{
|
||||
public class ControllerModel
|
||||
{
|
||||
public ControllerModel([NotNull] TypeInfo controllerType)
|
||||
public ControllerModel([NotNull] TypeInfo controllerType,
|
||||
[NotNull] IReadOnlyList<object> attributes)
|
||||
{
|
||||
ControllerType = controllerType;
|
||||
|
||||
Actions = new List<ActionModel>();
|
||||
ApiExplorer = new ApiExplorerModel();
|
||||
Attributes = new List<object>();
|
||||
Attributes = new List<object>(attributes);
|
||||
AttributeRoutes = new List<AttributeRouteModel>();
|
||||
ActionConstraints = new List<IActionConstraintMetadata>();
|
||||
Filters = new List<IFilter>();
|
||||
|
|
@ -56,7 +57,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
|
||||
public List<AttributeRouteModel> AttributeRoutes { get; private set; }
|
||||
|
||||
public List<object> Attributes { get; private set; }
|
||||
public IReadOnlyList<object> Attributes { get; }
|
||||
|
||||
public string ControllerName { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -213,13 +213,11 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
[NotNull] MethodInfo methodInfo,
|
||||
[NotNull] IReadOnlyList<object> attributes)
|
||||
{
|
||||
var actionModel = new ActionModel(methodInfo)
|
||||
var actionModel = new ActionModel(methodInfo, attributes)
|
||||
{
|
||||
IsActionNameMatchRequired = true,
|
||||
};
|
||||
|
||||
actionModel.Attributes.AddRange(attributes);
|
||||
|
||||
actionModel.ActionConstraints.AddRange(attributes.OfType<IActionConstraintMetadata>());
|
||||
actionModel.Filters.AddRange(attributes.OfType<IFilter>());
|
||||
|
||||
|
|
@ -268,12 +266,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
/// <returns>A <see cref="ParameterModel"/> for the given <see cref="ParameterInfo"/>.</returns>
|
||||
protected virtual ParameterModel CreateParameterModel([NotNull] ParameterInfo parameterInfo)
|
||||
{
|
||||
var parameterModel = new ParameterModel(parameterInfo);
|
||||
|
||||
// CoreCLR returns IEnumerable<Attribute> from GetCustomAttributes - the OfType<object>
|
||||
// is needed to so that the result of ToArray() is object
|
||||
var attributes = parameterInfo.GetCustomAttributes(inherit: true).OfType<object>().ToArray();
|
||||
parameterModel.Attributes.AddRange(attributes);
|
||||
var parameterModel = new ParameterModel(parameterInfo, attributes);
|
||||
|
||||
parameterModel.BinderMetadata = attributes.OfType<IBinderMetadata>().FirstOrDefault();
|
||||
|
||||
|
|
|
|||
|
|
@ -88,12 +88,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
/// <returns>A <see cref="ControllerModel"/> for the given <see cref="TypeInfo"/>.</returns>
|
||||
protected virtual ControllerModel CreateControllerModel([NotNull] TypeInfo typeInfo)
|
||||
{
|
||||
var controllerModel = new ControllerModel(typeInfo);
|
||||
|
||||
// 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();
|
||||
controllerModel.Attributes.AddRange(attributes);
|
||||
var controllerModel = new ControllerModel(typeInfo, attributes);
|
||||
|
||||
controllerModel.ControllerName =
|
||||
typeInfo.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) ?
|
||||
|
|
|
|||
|
|
@ -9,11 +9,12 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
{
|
||||
public class ParameterModel
|
||||
{
|
||||
public ParameterModel(ParameterInfo parameterInfo)
|
||||
public ParameterModel(ParameterInfo parameterInfo,
|
||||
IReadOnlyList<object> attributes)
|
||||
{
|
||||
ParameterInfo = parameterInfo;
|
||||
|
||||
Attributes = new List<object>();
|
||||
Attributes = new List<object>(attributes);
|
||||
}
|
||||
|
||||
public ParameterModel([NotNull] ParameterModel other)
|
||||
|
|
@ -28,7 +29,7 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
|
||||
public ActionModel Action { get; set; }
|
||||
|
||||
public List<object> Attributes { get; private set; }
|
||||
public IReadOnlyList<object> Attributes { get; }
|
||||
|
||||
public IBinderMetadata BinderMetadata { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -14,9 +14,11 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void CopyConstructor_DoesDeepCopyOfOtherModels()
|
||||
{
|
||||
// Arrange
|
||||
var action = new ActionModel(typeof(TestController).GetMethod("Edit"));
|
||||
var action = new ActionModel(typeof(TestController).GetMethod("Edit"),
|
||||
new List<object>());
|
||||
|
||||
var parameter = new ParameterModel(action.ActionMethod.GetParameters()[0]);
|
||||
var parameter = new ParameterModel(action.ActionMethod.GetParameters()[0],
|
||||
new List<object>());
|
||||
parameter.Action = action;
|
||||
action.Parameters.Add(parameter);
|
||||
|
||||
|
|
@ -40,13 +42,14 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void CopyConstructor_CopiesAllProperties()
|
||||
{
|
||||
// Arrange
|
||||
var action = new ActionModel(typeof(TestController).GetMethod("Edit"));
|
||||
var action = new ActionModel(typeof(TestController).GetMethod("Edit"),
|
||||
new List<object>() { new HttpGetAttribute() });
|
||||
|
||||
action.ActionConstraints.Add(new HttpMethodConstraint(new string[] { "GET" }));
|
||||
action.ActionName = "Edit";
|
||||
|
||||
action.Attributes.Add(new HttpGetAttribute());
|
||||
action.Controller = new ControllerModel(typeof(TestController).GetTypeInfo());
|
||||
action.Controller = new ControllerModel(typeof(TestController).GetTypeInfo(),
|
||||
new List<object>());
|
||||
action.Filters.Add(new AuthorizeAttribute());
|
||||
action.HttpMethods.Add("GET");
|
||||
action.IsActionNameMatchRequired = true;
|
||||
|
|
|
|||
|
|
@ -14,9 +14,11 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void CopyConstructor_DoesDeepCopyOfOtherModels()
|
||||
{
|
||||
// Arrange
|
||||
var controller = new ControllerModel(typeof(TestController).GetTypeInfo());
|
||||
var controller = new ControllerModel(typeof(TestController).GetTypeInfo(),
|
||||
new List<object>());
|
||||
|
||||
var action = new ActionModel(typeof(TestController).GetMethod("Edit"));
|
||||
var action = new ActionModel(typeof(TestController).GetMethod("Edit"),
|
||||
new List<object>());
|
||||
controller.Actions.Add(action);
|
||||
action.Controller = controller;
|
||||
|
||||
|
|
@ -46,11 +48,11 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void CopyConstructor_CopiesAllProperties()
|
||||
{
|
||||
// Arrange
|
||||
var controller = new ControllerModel(typeof(TestController).GetTypeInfo());
|
||||
var controller = new ControllerModel(typeof(TestController).GetTypeInfo(),
|
||||
new List<object>() { new HttpGetAttribute() });
|
||||
|
||||
controller.ActionConstraints.Add(new HttpMethodConstraint(new string[] { "GET" }));
|
||||
controller.Application = new ApplicationModel();
|
||||
controller.Attributes.Add(new HttpGetAttribute());
|
||||
controller.ControllerName = "cool";
|
||||
controller.Filters.Add(new AuthorizeAttribute());
|
||||
controller.RouteConstraints.Add(new AreaAttribute("Admin"));
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ namespace Microsoft.AspNet.Mvc.ApplicationModels
|
|||
public void CopyConstructor_CopiesAllProperties()
|
||||
{
|
||||
// Arrange
|
||||
var parameter = new ParameterModel(typeof(TestController).GetMethod("Edit").GetParameters()[0]);
|
||||
var parameter = new ParameterModel(typeof(TestController).GetMethod("Edit").GetParameters()[0],
|
||||
new List<object>() { new FromBodyAttribute() });
|
||||
|
||||
parameter.Action = new ActionModel(typeof(TestController).GetMethod("Edit"));
|
||||
parameter.Attributes.Add(new FromBodyAttribute());
|
||||
parameter.Action = new ActionModel(typeof(TestController).GetMethod("Edit"), new List<object>());
|
||||
parameter.BinderMetadata = (IBinderMetadata)parameter.Attributes[0];
|
||||
parameter.IsOptional = true;
|
||||
parameter.ParameterName = "id";
|
||||
|
|
|
|||
|
|
@ -1136,19 +1136,25 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
|
||||
var options = new MockMvcOptionsAccessor();
|
||||
options.Options.ApplicationModelConventions.Add(applicationConvention.Object);
|
||||
|
||||
|
||||
var provider = GetProvider(typeof(ConventionsController).GetTypeInfo(), options);
|
||||
|
||||
var model = provider.BuildModel();
|
||||
|
||||
var controller = model.Controllers.Single();
|
||||
controller.Attributes.Add(controllerConvention.Object);
|
||||
model.Controllers.Remove(controller);
|
||||
controller = BuildControllerModel(controller, controllerConvention.Object);
|
||||
model.Controllers.Add(controller);
|
||||
|
||||
var action = controller.Actions.Single();
|
||||
action.Attributes.Add(actionConvention.Object);
|
||||
controller.Actions.Remove(action);
|
||||
action = BuildActionModel(action, actionConvention.Object);
|
||||
controller.Actions.Add(action);
|
||||
|
||||
var parameter = action.Parameters.Single();
|
||||
parameter.Attributes.Add(parameterConvention.Object);
|
||||
action.Parameters.Remove(parameter);
|
||||
parameter = BuildParameterModel(parameter, parameterConvention.Object);
|
||||
action.Parameters.Add(parameter);
|
||||
|
||||
// Act
|
||||
ApplicationModelConventions.ApplyConventions(model, options.Options.ApplicationModelConventions);
|
||||
|
|
@ -1300,6 +1306,33 @@ namespace Microsoft.AspNet.Mvc.Test
|
|||
Assert.Single(action.ActionConstraints, a => a is ConstraintAttribute);
|
||||
}
|
||||
|
||||
private ActionModel BuildActionModel(ActionModel action, IActionModelConvention actionConvention)
|
||||
{
|
||||
var t = new ActionModel(action.ActionMethod,
|
||||
new List<object>(action.Attributes) { actionConvention });
|
||||
t.Parameters.AddRange(action.Parameters);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
private ParameterModel BuildParameterModel(ParameterModel parameter, IParameterModelConvention parameterConvention)
|
||||
{
|
||||
var t = new ParameterModel(parameter.ParameterInfo,
|
||||
new List<object>(parameter.Attributes) { parameterConvention });
|
||||
t.Action = parameter.Action;
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
private ControllerModel BuildControllerModel(ControllerModel controller, IControllerModelConvention controllerConvention)
|
||||
{
|
||||
var t = new ControllerModel(controller.ControllerType,
|
||||
new List<object>(controller.Attributes) { controllerConvention });
|
||||
t.Actions.AddRange(controller.Actions);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
private ControllerActionDescriptorProvider GetProvider(
|
||||
TypeInfo controllerTypeInfo,
|
||||
IEnumerable<IFilter> filters = null)
|
||||
|
|
|
|||
Loading…
Reference in New Issue