Why is my .net Core API Attribute Routing not working?

245 Views Asked by At

I am experimenting with a "Hosted Blazor WASM" project. This problem does not concern the Blazor client router (that is working fine). This concerns the "server-side" router not working as expecting when doing Attribute Routing.

This is my project file:

using Microsoft.AspNetCore.ResponseCompression;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseWebAssemblyDebugging();
}
else
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days. You may want to change this for production 
    scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseBlazorFrameworkFiles();
app.UseStaticFiles();

app.UseRouting();

app.MapRazorPages();
app.MapControllers();
app.MapFallbackToFile("index.html");

app.Run();

I added the following controller:

[ApiController]
public class PagesController : ControllerBase
{

public PagesController()
{
}

// GET: api/pages
[HttpGet]
[Route("api/{controller}")]
[Route("api/{controller}/{action}")]
[Route("api/{controller}/{action}/{param}")]
public async Task<PageVm> Get(string controller, string? action, string? param, string? WebsiteId)
{
    DomainLogic dl = new DomainLogic();

    PageVm PageVm = new PageVm();

    PageVm.WebsiteId = await dl.GetWebsiteIdFromDomainAsync(db, Request);

    Console.WriteLine($"{controller} Get() was called");
    return PageVm;
}
}

[Route("api/{controller}")] <-- this is working with https://localhost:7237/api/pages/

[Route("api/{controller}/{action}")] <-- this is NOT working https://localhost:7237/api/pages/something

This latter path simply is not recognized because we are routed to index.html which is the fallback.

Thanks in advance!

3

There are 3 best solutions below

1
Qiang Fu On BEST ANSWER

{contoller} ="Pages" //The controller of this method belongs to
{action}= "Get" //The method function name which your put attributes on.
{param}= "any string"
{websiteId} ="anystring"

{controller}/{action}/{param} would be "pages/get/something"

0
Dimitris Maragkos On

[controller] and [action] are preserved keywords when used in a Route attribute. By convention when you use [controller] in a route it means the controller name and when you use [action] it means the method name. So the resulting route for "api/[controller]/[action]" in your case is api/pages/get because the controller name is PagesController and the method name is Get.

1
Serge On

you have a wrong syntax, should be

[HttpGet]
[Route("~/api/[controller]")]
[Route("~/api/[controller]/[action]")]
[Route("~/api/[controller]/[action]/{param}")]
[Route("~/api/[controller]/[action]/{param}/{WebsiteId}")]
public async Task<PageVm> Get(string? param, string? WebsiteId)
{
}