Unable to call web api via httpclient - c#

I have a controller with the following route:
[HttpGet("/{id}/studentrank")]
public async Task<ActionResult> GetStudentRank(Guid id){
...
}
Note, the decorator over the class is: [Route("api/[controller]")]
so it should be called by: api/student/{guid here}/studentrank
This works fine in swagger. However when I call it as follow, I get an internal server error and does not even break in the controller:
var response = await HttpClient.GetAsync($"/api/student/{id}/studentrank");
Any idea of what could be missing?

The HttpGet does not contain the route parameter. Assuming the method is in the StudentController class you should do it like this:
[HttpGet]
[Route("GetStudentRank/{id}")]
public async Task<ActionResult> GetStudentRank(Guid id){
...
}
var response = await HttpClient.GetAsync($"{BaseUrl}/Student/GetStudentRank/{id}");

I think, cause it is a Guid and not a string the type must be declared in the route and or the route must not start with a slash if it should be combined with the route on the class:
[HttpGet("{id:guid}/studentrank")]
public async Task<ActionResult> GetStudentRank(Guid id){
...
}

Related

Is there any way to get full Url to other controller method from code?

I have Asp.Net Core web application. With following controller
[Produces("application/json")]
[Route("api/[controller]")]
public class TestController
{
[HttpGet]
[Route("firstroute")]
public async Task<IActionResult> FirstMethod()
{
...Some code...
}
[HttpGet]
[Route("secondroute")]
public async Task<IActionResult> SecondMethod()
{
...
SomeMethod(redirectLink)
...
}
}
What I need is to get fully assembled redirectLink to FirstMethod (it will probably be similar to this: "http://localhost/api/test/firstroute").
I need not RedirectToAction, but exact Url as string.
Didn't manage to find any suitable methods in this.Url or Microsoft.AspNetCore.Http.Extensions.
this.Request.GetDisplayUrl() returns result in appropriate format, but only for the called method.
you can use data from HttpContext.Request like bellow
var Url = string.Format("{0}://{1}{2}", HttpContext.Request.Scheme,HttpContext.Request.Host,"/api/firstroute");
and rediret by
return Redirect(Url);

Can't map route to action, ASP.NET Core Web API

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

ASP.NET Core Middleware

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.

Unable to get aspnet core api naming to work

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

Web API 2 - Method now allowed(405) for PUT

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.

Categories

Resources