Home > front end >  How to fix routing failure with ApiController?
How to fix routing failure with ApiController?

Time:12-27

I have a small ASP.NET Core web app project named "OdeToFood". The dev environment includes:

  1. IDE: Visual Studio 2019 on Windows 10 PC
  2. ASP.NET Core 3.1
  3. Use Dapper for data access from SQL DB
  4. Not using MVC

In one of web pages, the jQuery .ajax will be used retrive a record from DB. I added an ApiController with type of "API controller with read/write actions" because the EF is not used in this project.

Here is the code auto generated by VS (no change was made).

namespace OdeToFood.Api
{
    [Route("api/[controller]")]
    [ApiController]
    public class RestaurantsController : ControllerBase
    {
        // GET: api/<RestaurantsController>
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET api/<RestaurantsController>/5
        [HttpGet("{id}")]
        public string Get(int id)
        {
            return "value";
        }

        // POST api/<RestaurantsController>
        [HttpPost]
        public void Post([FromBody] string value)
        {
        }

        // PUT api/<RestaurantsController>/5
        [HttpPut("{id}")]
        public void Put(int id, [FromBody] string value)
        {
        }

        // DELETE api/<RestaurantsController>/5
        [HttpDelete("{id}")]
        public void Delete(int id)
        {
        }
    }
}

I tried to test it from the brower with following URLs:

  1. https://localhost:44361/api/Restaurants
  2. https://localhost:44361/api/Restaurants/8
  3. https://localhost:44361/api/RestaurantsController
  4. https://localhost:44361/api/RestaurantsController/8

They all failed with HTTP 404 error.

Since above code is already using the "Attribute Routing' with [Route ...], I think the first 2 URLs int test should work. But they didn't. I could not figure out why. Any help or suggestion will be greatly appreciated.

In the startup.cs file, the configure section has following settings:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    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.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

CodePudding user response:

Try below in your startup.cs

 app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    });

Comment below;

endpoints.MapRazorPages();

CodePudding user response:

Your Scenario:

Though the solution is very straight forward, I felt more explanation for you to get rid of any further confustions.

As you said "Visual Studio 2019" so if you have taken asp.net core web api project, it would be created with weather forecast api controller with default startup.cs like below:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }

So if you directly run the project it should run with the default action like below:

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }

So now come to your projects configuration which is containing like below:

app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });

Means its looking for simple mvc razor page and when you are trying to hit either of this URLs 1. https://localhost:44361/api/Restaurants or 2.https://localhost:44361/api/Restaurants/8 it should get 404 because it's not routed accordingly. So your routing template is not correct to route api controller directly. endpoints.MapRazorPages() is usually used for Razor mvc page routing.

Solution:

If you could add the API controller while you were taking your RestaurantsController I think it would be look like what you posted. and request should route as expected if you replace the below service

       app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });

Note: You even can override your route template if you want. You could enter image description here

What I tried show you is what mislead you and sharpen your idea. If you have any further query you have a look our official document here. Hope it would help you accordingly.

  • Related