Can not route directly to an api endpoint.
My api controller "TestController" should be found at localhost:5511/api/Test/getCollection?testCode=A but it wont route and retuns a 404.
I've a .net core 3.0 RazorPages app but need to include a few api endpoints. I don't think my endpoint is getting routed.
In Startup.cs Configure method I have this:
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
});
Here is my route attribute on controller:
[Route("api/[controller]/[action]")]
GetCollection Action:
[HttpGet]
public IActionResult GetCollection(string testCode)
{
List<string> retval = ...get a string list
return Ok(retval);
}
[Edit]
------- ok a simpler example, wont route to api ---------
Razor pages .net core 3.0 app, add a new folder /api with a controller
Get a 404 when going to
https://localhost:44340/api/lookup/getsomething
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddMvc();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
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();
});
}
api controller
namespace aspnetcore1.Api
{
[Route("api/[controller]")]
[ApiController]
public class LookupController : ControllerBase
{
[HttpGet]
[Route("GetSomething")]
public IActionResult GetSomething()
{
return Ok("this is a test");
}
}
}
Your route attribute on the controller should be:
[Route("api/Test")]
And the route attribute on the method should be:
[HttpGet]
[Route("GetCollection")]
public IActionResult GetCollection(string testCode)
{
List<string> retval = ...get a string list
return Ok(retval);
}
Edit
It looks like this is missing in the Configure(IApplicationBuilder app, IWebHostEnvironment env) method:
app.UseMvc();
Related
when I create an admin folder and then add an empty razor page and do /admin, it tells me the page cannot be found. However I have another User folder and when I do /User it works.
These folders are listed in a Views folder.
I tried duplicating the User folder and renaming it to Admin but it didn't work.
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Admin";
});
//services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddDbContext<ApplicationDbContext>(options=>options.UseSqlServer(Configuration.GetConnectionString("DefaultConnectionSqlite")));
services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();
services.AddTransient<IEmailSender, MailJetEmailSender>();
services.AddControllersWithViews();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/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.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
If you have a view named Index.cshtml in the path Views\Admin\Index.cshtml then you should create a Controller named AdminController:
public class AdminController : Controller
{
public IActionResult Index()
{
return View();
}
}
Notice the method name (Index) is the same as the view name.
If you want to have different method name and view name then you need to specify the view name when you return the view:
public class AdminController : Controller
{
public IActionResult View()
{
return View("Index");
}
}
https://learn.microsoft.com/en-us/aspnet/core/tutorials/first-mvc-app/adding-controller?view=aspnetcore-6.0&tabs=visual-studio
I have a small ASP.NET Core web app project named "OdeToFood". The dev environment includes:
IDE: Visual Studio 2019 on Windows 10 PC
ASP.NET Core 3.1
Use Dapper for data access from SQL DB
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:
https://localhost:44361/api/Restaurants
https://localhost:44361/api/Restaurants/8
https://localhost:44361/api/RestaurantsController
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();
});
}
Try below in your startup.cs
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
Comment below;
endpoints.MapRazorPages();
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 have a look here also if you want which a
conventional route.
Output:
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.
I Have a controller called Home and it contain 3 methods.
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
[Authorize]
public IActionResult Secret()
{
return View();
}
public IActionResult Authenticate()
{
return RedirectToAction(nameof(Index));
}
}
and in my ConfigureServices ,i have this code:
services.AddAuthentication("CookieAuth")
.AddCookie("CookieAuth", config => {
config.Cookie.Name = "Ali.Cookie";
config.LoginPath = "/Home/Authenticate";
});
and in my Configure,i have this code:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
Now my question is, What is injected to UseAuthorization Middleware from AddAuthentication Service? and how that happened ?
UseAuthorization is adding authorization middleware to application . If the app doesn't use authorization, you can safely remove the call to app.UseAuthorization().
If you want to use Authorization feature (e.g. Authorize attribute or other code) , then app.UseAuthorization() is needed , and apply Authorize attribute on controller/action means the controller/action requires a signed in user , if user is not authenticated , the authentication schema "CookieAuth" fires which will redirect user to default login page for sign in . But the problem of your code is UseAuthentication should add before the UseAuthorization middleware , otherwise authentication won't work and user may face infinite loop to your login method :
app.UseRouting();
app.UseAuthentication(); <-- add this line
app.UseAuthorization();
You can check document for more details .
My endpoint routing is not working in my asp.net core 3.0 Api. I have seen similar questions but I am still not sure what is missing here.
I have the following in Startup.cs
{
public void ConfigureServices(IServiceCollection services)
{
services.AddOptions();
services.AddControllers()
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.Formatting = Formatting.Indented;
options.SerializerSettings.Converters.Add(
new Newtonsoft.Json.Converters.StringEnumConverter());
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
app.UseDeveloperExceptionPage();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
"test",
"api/v1.0/{controller}/{id?}");
});
}
}
My Ping controller looks like:
public class PingController : ControllerBase
{
public IActionResult Get()
{
return Ok(true);
}
}
navigating to http://localhost//api/v1.0/Ping returns 404 page not found.
What am I missing here ? I also saw that MS suggests attribute routing for Web Apis but wanted to figure out why this is not working in the first place.
#rfcdejong was correct, it was missing {action} token.
The following correction fixed the problem.
endpoints.MapControllerRoute( "test", "api/v1.0/{controller}/{action=Get}/{id?}");
Follow this to add additional routing in .Net Core 3.1
endpoints.MapControllerRoute(
name: "prod", pattern: "product/item", new { controller="Product", action="Index"});
I have migrated an existing API project from 2.2 to 3.0 based on guidelines from this page.
Thus I've removed:
app.UseMvc(options =>
{
options.MapRoute("Default", "{controller=Default}/{action=Index}/{id?}");
});
and inserted:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(name: "Default", pattern: "{controller=Default}/{action=Index}/{id?}");
});
But no controller and action would be bound. All I get for any API I call is 404.
How should I debug it and what do I miss here?
Update: The Startup.cs file is located in another assembly. We reuse a centralized Startup.cs file across many projects.
From Attribute routing vs conventional routing:
It's typical to use conventional routes for controllers serving HTML pages for browsers, and attribute routing for controllers serving REST APIs.
From Build web APIs with ASP.NET Core: Attribute routing requirement:
The [ApiController] attribute makes attribute routing a requirement. For example:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
Actions are inaccessible via conventional routes defined by UseEndpoints, UseMvc, or UseMvcWithDefaultRoute in Startup.Configure.
If you want to use conventional routes for web api , you need to disable attribute route on web api.
StartUp:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "Default",
pattern: "{controller=default}/{action=Index}/{id?}");
});
}
Web api controller:
//[Route("api/[controller]")]
//[ApiController]
public class DefaultController : ControllerBase
{
public ActionResult<string> Index()
{
return "value";
}
//[HttpGet("{id}")]
public ActionResult<int> GetById(int id)
{
return id;
}
}
This could be requested by http://localhost:44888/default/getbyid/123
I can recommend my solution.
Create your CUSTOM base controller like that.
[Route("api/[controller]/[action]/{id?}")]
[ApiController]
public class CustomBaseController : ControllerBase
{
}
And use CustomBaseController
public class TestController : CustomBaseController
{
public IActionResult Test()
{
return Ok($"Test {DateTime.UtcNow}");
}
}
Rout` api/Test/test
You should try:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
It seems to not support conventional routing even in middleware like UseEndpoints and UseMvc
You can find that here