K. Todorov
K. Todorov

Reputation: 57

.NET WebApi breaks when url ends with ampersand

I have an ApiController - for example 'Home' controller, with action 'Test' which accepts two parameters - test1 and test2, both with default values

[System.Web.Http.HttpGet]
public ActionResult Test(int test1 = 3, int test2 = 5)
{
    var a = 0;
    return null;
}

Now when I call Home/Test?test1=1, everything is OK.
But when I call Home/Test?test1=1&, the server throws exception

The parameters dictionary contains a null entry for parameter 'test2' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult Test(Int32, Int32)' in 'TestAPI.Controllers.ValuesController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.

My route configuration is currently like this:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

This also happens on a brand new WebApi project so it is not something from my configuration.
The big problem is that this ampersand comes from a client project and I cannot change it there, although I am aware that this is a bad request.

The strangest thing is that if Home controller is inheriting Controller instead of ApiController - everything is fine.

Edit 1
I forgot to mention that if I make the parameters nullable (i.e. int?) then the error dissapears but test2 has value of null instead of 5 when calling the bad URL, so this is not an option for me.

Upvotes: 3

Views: 584

Answers (1)

PinBack
PinBack

Reputation: 2574

You can use a custom DelegatingHandler and remove trailing '&':

public class SanitizeHandler : System.Net.Http.DelegatingHandler
{
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (request.RequestUri.ToString().EndsWith("&"))
            request.RequestUri = new Uri(request.RequestUri.ToString().TrimEnd('&'));

        return base.SendAsync(request, cancellationToken);
    }
}

Register the new Handler in Application_Start:

GlobalConfiguration.Configuration.MessageHandlers.Add(new SanitizeHandler());

Or add it to your HttpConfiguration(then it is only called with Webapi calls):

public static void Register(HttpConfiguration config)
{
    ...
    config.MessageHandlers.Add(new SanitizeHandler());
    ...   
}

Upvotes: 2

Related Questions