Dedicated route in .NET Core not recognized producing 404

Viewed 268

I'm using a health checkup strategy that returns a certaing pong while I ping on the following URL.

localhost/util/ping

This works as supposed to. Then, I was considering that a lazy user might miss to type in util or pehaps get confused typing utils, utility or utilities. That can be frustrating, especially for new developers, who don't know of Swagger.

localhost/ping

So I decided to introduce a dedicated pseudo route only containing ping aiming at the URL above. There are no other routes (except the default one) nor controllers with the name that would collide, as far I can see.

app.UseEndpoints(endpoints =>
{
  endpoints.MapControllerRoute(
    name: "ping",
    pattern: "ping",
    defaults: new { controller = "util", action = "ping" });
  endpoints.MapControllerRoute(
    name: "default",
    pattern: "{controller}/{action=Index}/{id?}");
});

Regrettably, the above code doesn't seem to work. It produces status code 404 and I can't see what I'm missing that could differ from the example in MSDN.

The controller is declared as follows.

namespace Api.Controllers
{
  [ApiController]
  [Route("[controller]")]
  public class UtilController : ControllerBase
  {
    [HttpGet("ping")]
    public ActionResult Ping() { return Ok("pong"); }
  }
}
2 Answers

You can override it with a tilde (~) for your own particular method. In this manner, the routing mechanism also responds for any other method with the common route.

[Route("[controller]")]
[ApiController]
public class UtilController : ControllerBase {

    [HttpGet("~/[action]")]// http://localhost:5000/ping
    public ActionResult Ping() {
        return Ok("pong");
    }
    
    [HttpGet("[action]")]// http://localhost:5000/util/ping2 
    public ActionResult Ping2() {
        return Ok("pong2");
    }
}

postman test result

Even more apparent is to shove both paths on the same method.

[ApiController, Route("[controller]")]
public class UtilController : ControllerBase {

  [HttpGet("ping"), HttpGet("/ping")]
  public ActionResult Ping3() {
    return Ok("pong");
  }

}

Have you tried

app.UseEndpoints(endpoints =>
{
  endpoints.MapControllerRoute(
    name: "ping",
    pattern: "ping",
    defaults: new { controller = "util", action = "ping" });
  endpoints.MapControllerRoute(
    name: "default",
    pattern: "{controller=util}/{action=Index}/{id?}");
});

Based on what i see in the example on microsoft doc that you provided, the pattern for the default route has to have {controller=/*something*/}, not just {controller}. In my own app, i have :

endpoints.MapControllerRoute(name: "Default",
                    pattern: "{controller=Home}/{action=/*myaction*/}/{id?}");

And my controller is HomeController.cs That way i don't have to have [Route("[controller]")] at the beginning of my controller's class. However if you want to keep it, than maybe you should try:

endpoints.MapControllerRoute(name: "Default",
                    pattern: "controller/{action=/*myaction*/}/{id?}");

Hope it helps your situation!

Related