I have an issue with Delete Method in WebApi. It's not hitting from controller.
This is a Web Api Code having attribute routing and Get and Delete Method accepting same parameter.
When debugger goes to controller it does not go from DeleteAsync() to Delete Method in Web Api.
WebApi Code:
[Route("api/Products/{id}")]
public IHttpActionResult Get(int id)
{
List<ProductModel> showProductById = dbOperations.ShowProductById(id);
return Ok(showProductById);
}
[Route("api/Products/{id}")]
public IHttpActionResult Delete(int id)
{
int rowId = dbOperations.DeleteProduct(id);
return Ok(rowId);
}
Controller Code:
public ActionResult DeleteProduct(int id)
{
productApiClient.BaseAddress = new Uri(ConfigurationManager.AppSettings["BaseAddress"]);
var response = productApiClient.DeleteAsync("Products/" + id).Result;
return RedirectToAction("Index");
}
You need to mark what HTTP verb can be used to access that methods. You can do this by setting the corresponding attribute:
[HttpGet("api/Products/{id}")]
public IHttpActionResult Get(int id)
...
[HttpDelete("api/Products/{id}")]
public IHttpActionResult Delete(int id)
...
Edit: using AspNetCore Version 5.0.0
Related
Please let me know the exact method to ensure that correct parameters are sent in URL in order to navigate correctly in dot net core.
[HttpGet("{id},{id2}",Name ="Edit")]
[AllowAnonymous]
public ActionResult Edit(int id, int id2)
{
return Ok(3);
}
[HttpGet("{id}")]
public string Get(int id)
{
return "value";
}
When i try navigating to following url:
/api/test/Edit?id=1&id2=4
it gets navigated to the other method Get and returns value as string.
Startup.cs file has the following contents
app.UseMvcWithDefaultRoute();
Ensure that the correct route templates are applied to the actions
[Route("api/[controller]")]
public class TestController: Controller {
//GET api/test/edit?id=1&id2=4
[HttpGet("Edit")]
[AllowAnonymous]
public ActionResult Edit(int id, int id2) {
//...
return Ok(3);
}
//GET api/test/5
[HttpGet("{id}")]
public string Get(int id) {
return "value";
}
}
Reference Routing to controller actions in ASP.NET Core
.Net Core 3.1.3
In the Startup.Configure Method:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
Controller Annotation: [Route("[controller]/[action]")]
Action Method Annotation: [HttpGet("{param1:int}/{param2:int}")]
From the postman: https://localhost:5001/controller/action/param1/param2
Hope this helps!
I am working on Web API project and have the following problem:
I have tried to call the action method called 'GetUserBy' with the following Url (https://localhost:44328/api/Users/GetUserBy?username=myusername&password=mypassword), but the result I received in the browser looks like this:
{"id":["The value 'GetUserBy' is not valid."]}
Below is my UsersController:
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase
{
// GET: api/Users
[HttpGet]
public IEnumerable<User> GetUsers()
{
//this works
//code removed for simplicity
}
//GET: api/Users/5
[HttpGet("{id}")]
public async Task<IActionResult> GetUser([FromRoute] int id)
{
//this works too
}
[HttpGet("Users/GetUserBy")]
public async Task<IActionResult> GetUserBy([FromQuery]string username, [FromQuery]string password)
{
//this doesn't work
}
}
when I insert the breakpoint on this method, code execution never seems to come there regardless I call it or not.
I added the following code in startup.cs file, but nothing has changed.
app.UseMvc(
routes =>
{
routes.MapRoute("GetUserBy", "{controller=Users}/{action=GetUserBy}");
}
);
I have also visited the following web page, but I can't find the answer.
https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing?view=aspnetcore-2.1
try changing your Tag from this:
[HttpGet("Users/GetUserBy")]
to this:
[HttpGet("GetUserBy")]
you already have it routing to the Controller Users
You are experiencing route conflicts.
api/Users/GetUserBy
matches this route
//GET: api/Users/5
[HttpGet("{id}")]
public async Task<IActionResult> GetUser([FromRoute] int id)
{
//this works too
}
but it is treating the GetUserBy string in the URL as the {id} in the route template.
Since "GetUserBy" is not an int you get that invalid value error message.
add a route constraint so that it will only match for an integer.
//GET: api/Users/5
[HttpGet("{id:int}")]
public async Task<IActionResult> GetUser([FromRoute] int id) {
//...
}
The current GetUserBy action has Users/GetUserBy as its route template, which would resolve to api/Users/Users/GetUserBy given the current api/[controller] route template on the controller.
Consider using the action token to get the desired behavior.
Here is the completed code with the changes suggested above.
[Route("api/[controller]")]
[ApiController]
public class UsersController : ControllerBase {
// GET: api/Users
[HttpGet]
public IEnumerable<User> GetUsers() {
//...
}
//GET: api/Users/5
[HttpGet("{id:int}")]
public async Task<IActionResult> GetUser([FromRoute] int id) {
//...
}
//GET: api/Users/GetUserBy
[HttpGet("[action]")]
public async Task<IActionResult> GetUserBy([FromQuery]string username, [FromQuery]string password) {
//...
}
}
Reference Routing to controller actions in ASP.NET Core
I am working on extending the example at: https://docs.asp.net/en/latest/tutorials/first-web-api.html
They have a ToDo apis: /api/todo and /api/todo/{id}.
I want to extend it to ToDoGroups /api/ToDoGroup.
Under ToDoGroup, I want to reach a ToDo by the follwoing:
/api/ToDoGroup/{id}/ToDo/{id}.
How can I make it point to the same controller action? For example the following action below will also have another route like [HttpGet("ToDoGroup/{ToDoGroupid}/ToDo/{ToDoid}", Name = "GetTodo")]
[HttpGet("{id}", Name = "GetTodo")]
public IActionResult GetById(string id)
{
var item = TodoItems.Find(id);
if (item == null)
{
return NotFound();
}
return new ObjectResult(item);
}
first change the controller's route prefix:
[Route("api/todogroup/{groupId:int}")]
public class TodoController : Controller
then change your action's route:
[HttpGet("todo/{id}", Name = "GetTodo")]
public IActionResult GetById(int groupId, string id)
edit:
to get both routes, you can do this:
[Route("api")]
public class TodoController : Controller
[HttpGet("todo/{id}", Name = "GetTodo")]//api/todo/43
public IActionResult GetById(string id)
[HttpGet("todogroup/{groupdId:int}/todo/{id}", Name = "GetGroupTodo")]//api/todogroup/100/todo/43
public IActionResult GetById(int groupId, string id)
Asp.Net Web Api has a way of negating a route prefix (the route specified on the controller), but I cant find an equivalent in Asp.Net Core.
I am stuck with Web API 2 controller, from which I call PUT method and it gives me an error that method isn't allowed. I added lines of code in Web.config that prevent WebDAV to block methods. I tried everything but it is not working. It is probably problem with my PUT method in a controller.
Here is my controller code:
public IHttpActionResult Put(int id, [FromBody]ArticleModel model) {
var article = _articleService.UpdateArticle(model);
return Ok<ArticleModel>(article);
}
This is a code from where I call put :
response = await client.PutAsJsonAsync("api/article/2", articleModel);
before this code I defined client as http and added needed properties, and called other controller methods (GET, POST, DELETE) , they all work. This is from Windows Form app, and I am also calling from Postman but still the same error.
Add [HttpPut] , [RoutePrefix("api/yourcontroller")] and [Route("put")] attribute to your controller method
Example:
[RoutePrefix("api/yourcontroller")]
public class YourController
{
[HttpPut]
[Route("{id}/put")]
public IHttpActionResult Put(int id, [FromBody]ArticleModel model) {
var article = _articleService.UpdateArticle(model);
return Ok<ArticleModel>(article);
}
}
EDIT 1
public class YourController
{
[HttpPut]
[Route("api/article/{id}/put")]
public async Task<HttpResponseMessage> Put(int id, [FromBody]ArticleModel model) {
var article = _articleService.UpdateArticle(model);
return Ok<ArticleModel>(article);
}
}
From your HttpRequest call It seems what is expected is a HttpResponseMessage So changed the return type to async Task<HttpResponseMessage>
Code for making HttpRequest:
response = await client.PutAsJsonAsync("api/article/2/put", articleModel);
Add the [System.Web.Http.HttpPut] attribute to your method.
I have a web Api that has several methods. I have problem with routing. I have 1 method that is returning products by yearId and another method that is returning product by product id. Here are 2 routes I came up with:
/api/records/products?yearId=10
/api/records/products/15
These are my 2 methods:
[HttpGet]
[Route("getbyyearid")]
public async Task<Product> GetByYearid(int yearId)
{
.....
}
[HttpGet]
[Route("getbyid")]
public async Task<IEnumerable<Product>> GetByid(int productId)
{
......
}
what route mapping should I have so I can access my Web API with these 2 routes:
/api/records/products?yearId=10
/api/records/products/15
You could look into using Attribute Routing to customize how you want the routes to be used.
Here is an example of how you can achieve the routes you wanted:
[RoutePrefix("api/records")]
public class RecordsController: ApiController {
// GET api/records/products?yearid=10
[HttpGet]
[Route("products")]
public async Task<Product> GetByYearid(int yearId) {
.....
}
// GET api/records/products/15
[HttpGet]
[Route("products/{productId:int}")]
public async Task<IEnumerable<Product>> GetByid(int productId) {
......
}
}