Search code examples
c#asp.net.netasp.net-web-apiattributerouting

Passing Complex Objects to ASP.NET Web API Using FromUri


I want to bind the URL parameters to my Point object using attribute routing and the [FromUri] attribute such that the following URL is possible:

/foo-1,2

public IHttpActionResult PostFoo(
    [FromBody] string content,
    [FromUri] Point point)
{
}

public class Point
{
    public int A { get; set; }
    public int B { get; set; }

    // ...Other properties omitted for simplicity
}

I have tried the following Route attributes but none of these work:

[Route("foo-{a},{b}")]
[Route("foo-{A},{B}")]
[Route("foo-{point.A},{point.B}")]

Note that I can't use query string parameters because a badly built third party service does not accept ampersands in their URL's (Yes it's that bad). So I'm trying to build all query string parameters into the URL itself.


Solution

  • The two Options I'm aware of is:

    Use URL Rewriter to Globally take care of every and all routes. The advantage is that (I would hope) your publisher does have some type of standard url you can transform into a friendly MVC route.

    If not then you'll probably have to write your own RouteHandler. Not sure if you could use this globally, but you'd have to register it a lot (not that hard really).

    public class CustomRouteHandler : MvcRouteHandler
    {
      protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
      {
        var acceptValue = requestContext.HttpContext.Request.Headers["Accept"];
    
        if( /* do something with the accept value */)
        {
            // Set the new route value in the
            // requestContext.RouteData.Values dictionary
            // e.g. requestContext.RouteData.Values["action"] = "Customer";
        }
    
        return base.GetHttpHandler(requestContext);
      }
    }
    

    Then register it:

    RouteTable.Routes.MapRoute(
      name: "Custom",
      url: "{controller}/{action}",
      defaults: new { controller = "Home", action = "Index" }
    ).RouteHandler = new CustomRouteHandler();