mccalltd/AttributeRouting — Issue #24: GetHttpMethod() uses Unvalidated() which cannot be used in unit tests.
Author: davebrace
Created: 2011-11-23 15:44:03+00:00
State: open

The most recent release of AttributeRouting updated the GetHttpMethod extension method to be defined as:

public static string GetHttpMethod(this HttpRequestBase request)
{
return request.Headers["X-HTTP-Method-Override"] ??
request.Unvalidated().Form["X-HTTP-Method-Override"] ??
request.Unvalidated().QueryString["X-HTTP-Method-Override"] ??
request.HttpMethod;
}

The use of the Unvalidated() method prevents this code from being executed in a unit test. A null reference exception will be thrown because the Unvalidated() method tries to access HttpContext. For example:

var context = new HttpContextMock(requestPath: "shorturl/test");
var routes = new RouteCollection();
routes.MapAttributeRoutes(config => config.ScanAssemblyOf());
RouteData routeData = routes.GetRouteData(context);

That will throw an exception with the following stack trace:

System.NullReferenceException : Object reference not set to an instance of an object.
at Microsoft.Web.Infrastructure.DynamicValidationHelper.ValidationUtility.CollectionReplacer.GetUnvalidatedCollections(HttpContext context)
at System.Web.Helpers.Validation.Unvalidated(HttpRequest request)
at AttributeRouting.Extensions.MvcExtensions.GetHttpMethod(HttpRequestBase request) in C:\Development\AttributeRouting\src\AttributeRouting\Extensions\MvcExtensions.cs: line 17
at AttributeRouting.RestfulHttpMethodConstraint.Match(HttpContextBase httpContext, Route route, String parameterName, RouteValueDictionary values, RouteDirection routeDirection) in C:\Development\AttributeRouting\src\AttributeRouting\RestfulHttpMethodConstraint.cs: line 27
at System.Web.Routing.Route.ProcessConstraint(HttpContextBase httpContext, Object constraint, String parameterName, RouteValueDictionary values, RouteDirection routeDirection)
at System.Web.Routing.Route.ProcessConstraints(HttpContextBase httpContext, RouteValueDictionary values, RouteDirection routeDirection)
at System.Web.Routing.Route.GetRouteData(HttpContextBase httpContext)
at System.Web.Routing.RouteCollection.GetRouteData(HttpContextBase httpContext)

I am not sure what the best solution to this problem will be besides to create a version of Unvalidated that does not depend on HttpContext.