0

I'm struggling with this for some time now. I've searched all over the internet, didn't find any solution.

I'd like to create a webapi project with somewhat custom routing. Using VS 2019, project is of type ASP.NET WebApi on .NET Core 2.2. Routing should be like this:

Basic application must reside on url similar to "https://my.server.com/myapi". URLs which will be called are in form "https://my.server.com/myapi/{InstanceName}/{CommandName}?{customParams}"

I have one controller defined in my project and I would like to redirect all requests to that controller, where instanceName could be parameter of all the methods contained in a controller, so I would get a value for that parameter. CommandName is basicly the same as "action" RouteData by MVC principles. As you can see there is no controller specified, since all is handled by one controller.

So far I've tried setup routing like this:

Startup.cs

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "MyRoute",
        template: "{instance}/{action}",
        defaults: new { controller = "MyController" });
    });
}

MyController.cs

[Route("/")]
[ApiController]
public class MyController : ControllerBase
{
    [HttpGet("{instance}/info")]
    public JsonResult Info(string instance, InfoCommand model)
    {
        // Just return serialized model for now.
        var result = new JsonResult(model);

        return result;
    }
}

But this does not work. I get 415 response from (I think) web server when I call for example

https://my.server.com/myapi/MYINSTANCE/info?param1=value1&param2=value2

While debugging from VS this URL looks like this:

https://localhost:12345/MYINSTANCE/info?param1=value1&param2=value2

but I think it shouldn't matter for routing.

In best case scenario (putting [Route("{instance}")] above controller and [HttpGet("info")] above Info method) I get 404 response, which is also what I do not want.

I've even tried creating my own ControllerFactory, but that didn't work either (changing controller inside ControllerFactory's create method and adding another parameter to RouteData).

How to setup routing like that? Is it even possible? I would still like to use all other MVC features (model binding, proper routing, auth features, etc.), it's just this routing I cannot figure it out.

0

1 Answer 1

2

Your attempt resulting a in 415 Unsupported Media Type error was your best one.
You were only missing the FromQuery as shown below.

The error indicates that the complex type InfoCommand could not be resolved.
You must specify that it must be parsed from the querystring.

Note that the route defined via MapRoute doesn't have effect, since you are using attribute-based routing; it's only one or the other.

[Route("/")]
[ApiController]
public class MyController : ControllerBase
{
    [HttpGet("{instance}/info")]
    public JsonResult Info(string instance, [FromQuery] InfoCommand model)
    {
        var result = new JsonResult(model);
        return result;
    }
}

public class InfoCommand
{
    public InfoCommand()
    {}

    public string Param1 { get; set; }
    public string Param2 { get; set; }
}
Sign up to request clarification or add additional context in comments.

4 Comments

It works! Still don't quite understand why it matters from where InfoCommand is resolved. It's POCO, so no fancy stuff is inside. A couple of strings and DateTime nullable (DateTime?). And thanks for MapRoute remark. Will remove it, if not needed.
Without the FromQuery Web Api would try to resolve it from the body/payload, which is missing because of a GET request.
One question though about using MapRoute: I would still need this MapRoute call, since the info about which controller is handling requests, is specified only there? Or is there any other way to specify it? Or will ASP.NET look through all the methods with HttpGet or HttpPost attributes?
In your case, the routing is configured via the info given in the attributes, which gets handled via attribute routing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.