csharp RouteTestingExtensions仅限WebAPI
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csharp RouteTestingExtensions仅限WebAPI相关的知识,希望对你有一定的参考价值。
/// <summary>
/// Used to simplify testing routes and restful testing routes
/// <example>
/// This tests that incoming PUT on resource is handled by the update method of the Banner controller
/// "~/banner/1"
/// .WithMethod(HttpVerbs.Put)
/// .ShouldMapTo<BannerController>(action => action.Update(1));
/// </example>
/// </summary>
public static class RouteTestingExtensions
{
/// <summary>
/// Will return the name of the action specified in the ActionNameAttribute for a method if it has an
/// ActionNameAttribute.
/// Will return the name of the method otherwise.
/// </summary>
public static string ActionName(this MethodInfo method)
{
return method.IsDecoratedWith<ActionNameAttribute>() ? method.GetAttribute<ActionNameAttribute>().Name : method.Name;
}
/// <summary>
/// Will return true if the attributeTarget is decorated with an attribute of type TAttribute. Or false if not
/// </summary>
public static bool IsDecoratedWith<TAttribute>(this ICustomAttributeProvider attributeTarget) where TAttribute : Attribute
{
return attributeTarget.GetCustomAttributes(typeof(TAttribute), false).Length > 0;
}
/// <summary>
/// Will return the first attribute of type TAttribute on the attributeTarget.
/// </summary>
public static TAttribute GetAttribute<TAttribute>(this ICustomAttributeProvider attributeTarget) where TAttribute : Attribute
{
return (TAttribute)attributeTarget.GetCustomAttributes(typeof(TAttribute), false)[0];
}
/// <summary>
/// Returns the corresponding http route for the URL. Returns null if no route was found.
/// </summary>
/// <param name="url">The app relative url to test.</param>
/// <param name="config"></param>
/// <returns>A matching <see cref="RouteData" />, or null.</returns>
public static HttpRouteTester Route(this string url, HttpConfiguration config)
{
return Route(url, config, HttpMethod.Get);
}
/// <summary>
/// Returns the corresponding http route for the URL. Returns null if no route was found.
/// </summary>
/// <param name="url">The app relative url to test.</param>
/// <param name="config"></param>
/// <param name="httpMethod">HttpMethod</param>
/// <returns>A matching <see cref="RouteData" />, or null.</returns>
public static HttpRouteTester Route(this string url, HttpConfiguration config, HttpMethod httpMethod)
{
var httpRequestMessage = new HttpRequestMessage(httpMethod, url);
return new HttpRouteTester(config, httpRequestMessage);
}
/// <summary>
/// Converts the URL to matching web api route and verifies that it will match a route with the values specified by the
/// expression.
/// </summary>
/// <typeparam name="TController">The type of web api controller</typeparam>
/// <param name="url">The ~/ based url</param>
/// <param name="config"></param>
/// <param name="action">The expression that defines what action gets called (and with which parameters)</param>
public static HttpRouteTester ShouldMapTo<TController>(this string url, HttpConfiguration config, Expression<Func<TController, HttpResponseMessage>> action) where TController : ApiController
{
url = ConvertRelativeUrlToAbsolute(url);
return url.Route(config).ShouldMapTo(action);
}
/// <summary>
/// Converts the URL to matching web api route and verifies that it will match a route with the values specified by the
/// expression.
/// </summary>
/// <typeparam name="TController">The type of web api controller</typeparam>
/// <param name="url">The ~/ based url</param>
/// <param name="config"></param>
/// <param name="action">The expression that defines what action gets called (and with which parameters)</param>
public static HttpRouteTester ShouldMapTo<TController>(this string url, HttpConfiguration config, Expression<Func<TController, Task<HttpResponseMessage>>> action)
where TController : ApiController
{
url = ConvertRelativeUrlToAbsolute(url);
return url.Route(config).ShouldMapTo(action);
}
private static string ConvertRelativeUrlToAbsolute(string url)
{
return url.StartsWith("~") ? url.Replace("~", "http://www.site.com") : url;
}
/// <summary>
/// Verifies the <see cref="RouteData">routeData</see> maps to the controller type specified.
/// </summary>
/// <typeparam name="TController"></typeparam>
/// <param name="routeTester"></param>
/// <returns></returns>
public static HttpRouteTester ShouldMapTo<TController>(this HttpRouteTester routeTester) where TController : ApiController
{
var expecting = typeof(TController);
if (expecting != routeTester.GetControllerType())
throw new RouteTestingException(string.Format("Controller types do not match expecting:{0} actual:{1}", expecting, routeTester.GetControllerType()));
return routeTester;
}
/// <summary>
/// Asserts that the route matches the expression specified. Checks controller, action, and any method arguments
/// into the action as route values.
/// </summary>
/// <typeparam name="TController">The controller.</typeparam>
/// <param name="routeTester">The routeData to check</param>
/// <param name="action">The action to call on TController.</param>
public static HttpRouteTester ShouldMapTo<TController>(this HttpRouteTester routeTester, Expression<Func<TController, HttpResponseMessage>> action)
where TController : ApiController
{
if (routeTester == null)
throw new ArgumentException("The URL did not match any route");
routeTester.ShouldMapTo<TController>();
CheckActionMaps(routeTester, action);
return routeTester;
}
/// <summary>
/// Asserts that the route matches the expression specified. Checks controller, action, and any method arguments
/// into the action as route values.
/// </summary>
/// <typeparam name="TController">The controller.</typeparam>
/// <param name="routeTester">The routeData to check</param>
/// <param name="action">The action to call on TController.</param>
public static HttpRouteTester ShouldMapTo<TController>(this HttpRouteTester routeTester, Expression<Func<TController, Task<HttpResponseMessage>>> action)
where TController : ApiController
{
if (routeTester == null)
throw new ArgumentException("The URL did not match any route");
routeTester.ShouldMapTo<TController>();
CheckActionMaps(routeTester, action);
return routeTester;
}
private static void CheckActionMaps<TController>(HttpRouteTester routeTester, Expression<Func<TController, Task<HttpResponseMessage>>> action) where TController : ApiController
{
var methodCall = (MethodCallExpression)action.Body;
var actualAction = routeTester.GetActionName();
var expectedAction = methodCall.Method.ActionName();
if (expectedAction != actualAction)
throw new RouteTestingException(string.Format("Action did not match expecting:{0} actual:{1}", expectedAction, actualAction));
}
private static void CheckActionMaps<TController>(HttpRouteTester routeTester, Expression<Func<TController, HttpResponseMessage>> action) where TController : ApiController
{
var methodCall = (MethodCallExpression)action.Body;
var actualAction = routeTester.GetActionName();
var expectedAction = methodCall.Method.ActionName();
if (expectedAction != actualAction)
throw new RouteTestingException(string.Format("Action did not match expecting:{0} actual:{1}", expectedAction, actualAction));
}
/// <summary>
/// A way to start the fluent interface and and which method to use
/// since you have a method constraint in the route.
/// </summary>
/// <param name="url"></param>
/// <param name="config"></param>
/// <param name="httpMethod"></param>
/// <returns></returns>
public static HttpRouteTester WithMethod(this string url, HttpConfiguration config, HttpMethod httpMethod)
{
return Route(url, config, httpMethod);
}
}
public class RouteTestingException : Exception
{
public RouteTestingException(string message)
: base(message)
{
}
public RouteTestingException(string format, params object[] args)
: base(string.Format(format, args))
{
}
}
public class HttpRouteTester
{
private readonly HttpControllerContext _controllerContext;
private readonly IHttpControllerSelector _controllerSelector;
private readonly HttpRequestMessage _request;
public HttpRouteTester(HttpConfiguration config, HttpRequestMessage request)
{
if (config.Routes.Count == 0)
throw new ArgumentException("No routes found in route table make sure you register routes before testing route matching");
_request = request;
RouteData = config.Routes.GetRouteData(request);
if (RouteData == null)
throw new ArgumentException("No route data found for this route");
request.Properties[HttpPropertyKeys.HttpRouteDataKey] = RouteData;
_controllerSelector = new DefaultHttpControllerSelector(config);
_controllerContext = new HttpControllerContext(config, RouteData, request);
}
public IHttpRouteData RouteData { get; private set; }
public string GetActionName()
{
if (_controllerContext.ControllerDescriptor == null)
GetControllerType();
var actionSelector = new ApiControllerActionSelector();
var descriptor = actionSelector.SelectAction(_controllerContext);
return descriptor.ActionName;
}
public Type GetControllerType()
{
var descriptor = _controllerSelector.SelectController(_request);
_controllerContext.ControllerDescriptor = descriptor;
return descriptor.ControllerType;
}
}
以上是关于csharp RouteTestingExtensions仅限WebAPI的主要内容,如果未能解决你的问题,请参考以下文章
csharp 例如-CSHARP-GroupDocs.Conversion.Examples.CSharp渲染,RenderPSDImageAsPath.cs
csharp 实例-CSHARP-GroupDocs.Conversion.Examples.CSharp变频-ConvertTopresentationAsPath.cs
csharp 实例-CSHARP-GroupDocs.Conversion.Examples.CSharp变频-ConvertTopresentationAsPath.cs
csharp 实例-CSHARP-GroupDocs.Conversion.Examples.CSharp变频-ConvertTopresentationAsPath.cs
csharp 例如-CSHARP-GroupDocs.Search.Examples.CSharp索引,AddDocumentToIndex.cs
csharp 例如-CSHARP-GroupDocs.Search.Examples.CSharp索引,AddDocumentToIndexAsynchronously.cs