I have a Web API action method like this
[HttpPost]
[Route("{idFlux}/Transfert")]
public IHttpActionResult Post(int idFlux, Transfert parametre)
The controller has a prefix of
[RoutePrefix("api/v1/Flux")]
localhost/api/v1/Flux/59 works, but localhost/api/v1/Flux/59/Transfert is not working, and I think everything is set right.
Just add both acceptable routes to action
[HttpPost]
[Route("{idFlux}/Transfert")]
[Route("{idFlux}")]
public IHttpActionResult Post(int idFlux, Transfert parametre)
Related
When using this button
<a onclick="location.href='#Url.Action("Update", "Book", new { id = #Model.Id })'"
class="btn btn-primary">Edit</a>
The controller indeed hits the get method
[HttpGet]
[Route("{id}")]
public ActionResult Update(int id) {...}
But the Url is not anymore matching the route {controller}/{action}, it just shows the id like this
https://localhost:44345/1
You are overriding the entire route when you use the [Route()] attribute on your endpoint, this is why the controller name portion is removed. I imagine the reason you have done this is due to a conflict with an existing GET action.
You appear to be using a GET request to update your entity. Instead use POST or PUT depending on the scenario (https://www.w3schools.com/tags/ref_httpmethods.asp) and update your HttpGet attribute accodingly.
[HttpPost]
// or
[HttpPut]
However, XHTML 1.x forms only support GET and POST as HTTP request methods. You can either use POST or you can see workaround here if you want to use PUT.
Also, ensure that you have a route attribute on your controller class that looks like this:
[Route("[controller]")]
public class BookController : ControllerBase
This will ensure that the controller portion of the route is included, so the format will be: .../{controllerName}/{id}
NOTE: If you want to stick with GET and have multiple requests of the same HTTP message type then you can route to the correct action by updating the [HttpGet] attribute rather than adding a [Route] attribute :
[HttpGet("update/{id}")]
This will give your url the following format .../{controllerName}/update/{id}
you can use an ancor helper
<a asp-action="Update" asp-controller="Book" asp-route-id="#Model.Id" class="btn btn-primary">Edit</a>
If you use Route attribute, it will override the route template.
So if you use ASP.NET Core MVC, you need use the route template like below:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
Your Controller should be:
public class BookController : Controller
{
[HttpGet]
public ActionResult Update(int id) {
return View();
}
}
Then the Url.Action should work as expected:https://localhost:44345/Book/Update/1
<a onclick="location.href='#Url.Action("Update", "Book", new { id = #Model.Id })'"
class="btn btn-primary">Edit</a>
If you use ASP.NET Core WebApi, controller should be like below:
[Route("[controller]/[action]")]
[ApiController]
public class BookController : ControllerBase
{
[HttpGet]
[Route("{id}")]
public ActionResult Update(int id) => Ok();
}
I having a question should we assign a http attribute for each action?
Like for example Index Page that doesn't have any action just displaying html we still need to assign a http attribute? Why since there is no retrieving data.
And If I remove Http Attribute for ViewDetail and CreateRecord, the page is still working and no bug what the huge difference for adding and not adding http attribute
public ActionResult Index()
{
return View();
}
[HttpGet]
public ActionResult ViewDetail()
{
//.... Get Data Action
return Redirect(Url.Action("Edit","Home"));
}
[HttpPost]
public ActionResult CreateRecord()
{
//.... Create Action
return Redirect(Url.Action("Edit","Home"));
}
There may be some methods in your Controller class that are not HTTP Endpoints.
I have build custom Identity Middle-ware. Inside Invoke method I am checking if request has token etc. After token is checked I want to pass request further to controller. It`s working for GET request - it jump into controller method. It is not working for POST request.
Here is Invoke Method
public async Task Invoke(HttpContext context)
{
//checking
await _next(context);
}
Its working controller:
[Route("api/[controller]")]
public class ValuesController : Controller
{
// GET api/values
[AllowAnonymous]
[HttpGet]
public string Get()
{
return "Allow annymous";
}
}
And not working one
[Route("api/[controller]")]
public class AccountController : Controller
{
[AllowAnonymous]
[HttpPost]
public void Login()
{
//some logic
HttpContext.Response.WriteAsync("Unauthorized");
}
}
Making POST call Postman returns 404 not found.
The route for the action in question would be /api/Account. Make sure that is correct.
If instead you wanted /api/Account/Login:
[Route("api/[controller]/[action]")]
public class AccountController : Controller
{
[AllowAnonymous]
[HttpPost]
public void Login()
{
//some logic
HttpContext.Response.WriteAsync("Unauthorized");
}
}
Try returning something like an IActionResult rather than simply void.
[AllowAnonymous]
[HttpPost]
public IActionResult Login()
{
// some logic
return Unauthorized();
}
Looking at your code I hopping there is only one method inside the AccountController called Login. If not please add attribute [Route("Login")] to Login method (make sure you do not keep it empty like [Route("Login")] otherwise it will have same as what you are doing currently).
Then make the call to the POST http://host:***/api/account/login url and that should work.
FYI: I have tried this thing on my machine and it is working.
I have a client controller that is called "ClientController". The start of the controller is as follows:
[Route("api/[controller]")]
[AllowAnonymous]
public class ClientController : Controller
The first httpget method works like this - naming etc just a "Get":
public IActionResult Get()
{...
..and it does indeed work when I use Postman with a call:
http://localhost:5001/api/Client
However, If I change the name to Index and name it Index like so:
[HttpGet(Name = "Index")]
public IActionResult Index()
{...
return new OkObjectResult(some object)
}
and I use Postman again to call it this time explicitly:
http://localhost:5001/api/Client/Index
I get a 404 status.. - Not found..
I have looked around for some answers on this but its a bit light on for ASPNET Core examples for API and naming conventions..
How do you name an IActionResult API method (via connotations) and call it correctly (eg URL structure)? A little direction on correct convention would be great..
Have you tried this
[HttpGet("Index",Name = "Index")]
public IActionResult Index()
{...
return new OkObjectResult(some object)
}
More detail is given on this link. Please check it out
https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing
I have the following routes set up in a user controller:
[EnableCors("*", "*", "*")]
[RoutePrefix("api/users")]
[Authorize]
public class UserController : ApiController
{
[Route("")]
public IHttpActionResult Get()
{
}
[HttpGet]
[Route("{id:int}")]
public IHttpActionResult Get(int id)
}
[HttpPost]
[Route("validateUser")]
public IHttpActionResult ValidateUser()
{
}
[HttpPost]
[Route("verify/{identityId}/{emailAddress}")]
public void VerifyUserEmailAddress(string identityId, string emailAddress)
{
}
}
The first three routes work just fine. But the fourth fails with a 404. I'm using fiddler to make the call:
http://localhost:39897/api/users/verify/asldkfj/jb#test.com (post is selected)
Does post require data sent in the body? Can anyone see what I'm doing wrong and why the verify route is not being found?
The .com in the email is the issue.
Sure its a valid email, but IIS treats requests with file extensions as actual file requests and tries to find it on disk. When it can't find it then you get the 404 Not Found
If you add a trailing slash / to the request it should work.
ie http://localhost:39897/api/users/verify/asldkfj/jb#test.com/