Adding ActionName Attribute
This commit is contained in:
parent
1da2d6d9dc
commit
53b76380eb
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
||||
public sealed class ActionNameAttribute : Attribute
|
||||
{
|
||||
public ActionNameAttribute(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public string Name { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -104,38 +104,43 @@ namespace Microsoft.AspNet.Mvc
|
|||
private bool HasCustomAttributes(MethodInfo methodInfo)
|
||||
{
|
||||
var actionAttributes = GetActionCustomAttributes(methodInfo);
|
||||
return actionAttributes.HttpMethodProviderAttributes.Any();
|
||||
return actionAttributes.Any();
|
||||
}
|
||||
|
||||
private ActionAttributes GetActionCustomAttributes(MethodInfo methodInfo)
|
||||
{
|
||||
var httpMethodConstraints = methodInfo.GetCustomAttributes().OfType<IActionHttpMethodProvider>();
|
||||
var attributes = methodInfo.GetCustomAttributes();
|
||||
var actionNameAttribute = attributes.OfType<ActionNameAttribute>().FirstOrDefault();
|
||||
var httpMethodConstraints = attributes.OfType<IActionHttpMethodProvider>();
|
||||
return new ActionAttributes()
|
||||
{
|
||||
HttpMethodProviderAttributes = httpMethodConstraints
|
||||
HttpMethodProviderAttributes = httpMethodConstraints,
|
||||
ActionNameAttribute = actionNameAttribute
|
||||
};
|
||||
}
|
||||
|
||||
private IEnumerable<ActionInfo> GetActionsForMethodsWithCustomAttributes(MethodInfo methodInfo)
|
||||
{
|
||||
var httpMethodConstraints = GetActionCustomAttributes(methodInfo).HttpMethodProviderAttributes;
|
||||
if (!httpMethodConstraints.Any())
|
||||
var actionAttributes = GetActionCustomAttributes(methodInfo);
|
||||
if (!actionAttributes.Any())
|
||||
{
|
||||
// If the action is not decorated with any of the attributes,
|
||||
// it would be handled by convention.
|
||||
yield break;
|
||||
}
|
||||
|
||||
var httpMethods = httpMethodConstraints.SelectMany(x => x.HttpMethods).Distinct().ToArray();
|
||||
if (httpMethods.Any())
|
||||
var actionNameAttribute = actionAttributes.ActionNameAttribute;
|
||||
var actionName = actionNameAttribute != null ? actionNameAttribute.Name : methodInfo.Name;
|
||||
|
||||
var httpMethodProviders = actionAttributes.HttpMethodProviderAttributes;
|
||||
var httpMethods = httpMethodProviders.SelectMany(x => x.HttpMethods).Distinct().ToArray();
|
||||
|
||||
yield return new ActionInfo()
|
||||
{
|
||||
// Any method which does not follow convention and does not have
|
||||
// an explicit NoAction attribute is exposed as a method with action name.
|
||||
yield return new ActionInfo()
|
||||
{
|
||||
HttpMethods = httpMethods,
|
||||
ActionName = methodInfo.Name,
|
||||
RequireActionNameMatch = true
|
||||
};
|
||||
}
|
||||
HttpMethods = httpMethods,
|
||||
ActionName = actionName,
|
||||
RequireActionNameMatch = true
|
||||
};
|
||||
}
|
||||
|
||||
private IEnumerable<ActionInfo> GetActionsForMethodsWithoutCustomAttributes(MethodInfo methodInfo, TypeInfo controllerTypeInfo)
|
||||
|
|
@ -201,7 +206,13 @@ namespace Microsoft.AspNet.Mvc
|
|||
|
||||
private class ActionAttributes
|
||||
{
|
||||
public IEnumerable<IActionHttpMethodProvider> HttpMethodProviderAttributes { get; set; }
|
||||
public IEnumerable<IActionHttpMethodProvider> HttpMethodProviderAttributes { get; set; }
|
||||
public ActionNameAttribute ActionNameAttribute { get; set; }
|
||||
|
||||
public bool Any()
|
||||
{
|
||||
return ActionNameAttribute != null || HttpMethodProviderAttributes.Any();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -108,6 +108,64 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
Assert.Equal("Index", result.Name);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("GET")]
|
||||
[InlineData("PUT")]
|
||||
[InlineData("POST")]
|
||||
[InlineData("DELETE")]
|
||||
[InlineData("PATCH")]
|
||||
public async Task ActionNameAttribute_ActionGetsExposedViaActionName_UnreachableByConvention(string verb)
|
||||
{
|
||||
// Arrange
|
||||
var requestContext = new RequestContext(
|
||||
GetHttpContext(verb),
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{ "controller", "ActionName" },
|
||||
{ "action", "RPCMethodWithHttpGet" }
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = await InvokeActionSelector(requestContext);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(null, result);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("GET", "CustomActionName_Verb")]
|
||||
[InlineData("PUT", "CustomActionName_Verb")]
|
||||
[InlineData("POST", "CustomActionName_Verb")]
|
||||
[InlineData("DELETE", "CustomActionName_Verb")]
|
||||
[InlineData("PATCH", "CustomActionName_Verb")]
|
||||
[InlineData("GET", "CustomActionName_DefaultMethod")]
|
||||
[InlineData("PUT", "CustomActionName_DefaultMethod")]
|
||||
[InlineData("POST", "CustomActionName_DefaultMethod")]
|
||||
[InlineData("DELETE", "CustomActionName_DefaultMethod")]
|
||||
[InlineData("PATCH", "CustomActionName_DefaultMethod")]
|
||||
[InlineData("GET", "CustomActionName_RpcMethod")]
|
||||
[InlineData("PUT", "CustomActionName_RpcMethod")]
|
||||
[InlineData("POST", "CustomActionName_RpcMethod")]
|
||||
[InlineData("DELETE", "CustomActionName_RpcMethod")]
|
||||
[InlineData("PATCH", "CustomActionName_RpcMethod")]
|
||||
public async Task ActionNameAttribute_DifferentActionName_UsesActionNameFromActionNameAttribute(string verb, string actionName)
|
||||
{
|
||||
// Arrange
|
||||
var requestContext = new RequestContext(
|
||||
GetHttpContext(verb),
|
||||
new Dictionary<string, object>
|
||||
{
|
||||
{ "controller", "ActionName" },
|
||||
{ "action", actionName }
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = await InvokeActionSelector(requestContext);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(actionName, result.Name);
|
||||
}
|
||||
|
||||
private async Task<ActionDescriptor> InvokeActionSelector(RequestContext context)
|
||||
{
|
||||
return await InvokeActionSelector(context, _actionDiscoveryConventions);
|
||||
|
|
@ -178,6 +236,24 @@ namespace Microsoft.AspNet.Mvc.Core.Test
|
|||
{ }
|
||||
}
|
||||
|
||||
private class ActionNameController
|
||||
{
|
||||
[ActionName("CustomActionName_Verb")]
|
||||
public void Put()
|
||||
{
|
||||
}
|
||||
|
||||
[ActionName("CustomActionName_DefaultMethod")]
|
||||
public void Index()
|
||||
{
|
||||
}
|
||||
|
||||
[ActionName("CustomActionName_RpcMethod")]
|
||||
public void RPCMethodWithHttpGet()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class HttpMethodAttributeTests_RestOnlyController
|
||||
{
|
||||
[HttpGet]
|
||||
|
|
|
|||
Loading…
Reference in New Issue