HttpGet throws 500 error on vuejs but works with postman

Viewed 957

I have a client which consumes my API. I have an endpoint on the API like so:

[Route("api/account")]
[ApiController]
public class AccountController : BaseController
{
    private readonly IIdentityProvider _identityProvider;

    private string UserId 
    { 
        get
        {
           return User?.FindFirst("AspNetUserId")?.Value;
        }
    }

    public AccountController(IIdentityProvider identityProvider)
    {
        _identityProvider = identityProvider;
    }

    [HttpGet]
    public IActionResult GetAccount()
    {
       var user = _identityProvider.GetByAspNetUserId(UserId);
       var account = new Account
       {
          UserName = user.UserName,
          Email = user.Email,
          EmailConfirmed = user.EmailConfirmed,
          PhoneNumber = user.PhoneNumber,
          PhoneNumberConfirmed = user.PhoneNumberConfirmed,
          TwoFactorEnabled = user.TwoFactorEnabled,
          SmsTwoFactorEnabled = user.SmsTwoFactorEnabled
       };

       return Ok(account);
     }
}

My client Vue.js application calls this action like so:

async getAccount(): Promise<Account> {
  const result = await this.axios.get(`${this.apiUrl}/account`);
  return this.jsonConvert.deserializeObject(result.data, Account);
}

Whenever this is called I get a 500 error. I've put a breakpoint on the start line of the action, but it doesn't get called. But when I call this same action through Postman, it works. There is nothing different in the 2 requests.

However if I change the [HttpGet] to [HttpGet("test") and change the vue.js client to await this.axios.get(${this.apiUrl}/account/test); it works and hits the breakpoint.

Can anyone explain what I'm doing wrong here?

EDIT:

The following is what is in the inspector of my browser, as you can see there is no useful information here. It just says 500 internal error with no response:

enter image description here

Here is the configure method of my Startup.cs file:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
   app.UseRouting();
   app.UseCors("AllowAll");
   app.UseAuthentication();
   app.UseAuthorization();
   app.UseEndpoints(endpoints =>
   {
       endpoints.MapControllers();
       endpoints.MapDefaultControllerRoute();
   });
}
4 Answers

It's not failing the GET request but the OPTIONS request. Vue.js does a preflight for requests. So if your endpoint has a GET verb, when called with the OPTIONS one it will throw an error.

You have 2 solutions:

  1. Simple solution, allow OPTIONS verb for your endpoint, check for it, and return a 200.
  2. You can check the answer to this question and make a similar solution: cors issue with vue and dotnet and implement an auto-response for all OPTIONS requests.

For a reference, you can read preflight-requests

This behavior could be caused by routing issue which can be fixed by adding an empty route on your method to allow a get request made to Route("api/account").

    [Route("")]
    [HttpGet]
    public IActionResult GetAccount()
    {
       var user = _identityProvider.GetByAspNetUserId(UserId);
       var account = new Account
       {
          UserName = user.UserName,
          Email = user.Email,
          EmailConfirmed = user.EmailConfirmed,
          PhoneNumber = user.PhoneNumber,
          PhoneNumberConfirmed = user.PhoneNumberConfirmed,
          TwoFactorEnabled = user.TwoFactorEnabled,
          SmsTwoFactorEnabled = user.SmsTwoFactorEnabled
       };

       return Ok(account);
     }

When I debug locally and attempt to get an endpoint without an empty route on a method get a 404 error without the breakpoint for the method ever hitting. Adding the empty route cause the breakpoint to hit.

As far as the 500, your application could very well have something causing a 500 instead of a 404 such as a null reference in a custom error handler, or your base controller class or some kind of error in a filter like an authorization filter.

Your debugger should give you more information about the exact reason for the 500 error. If you are hosting in IIS you can enable request tracing for error codes above 500.

I see that you use DI, did you register the interface IdentityProvider on startup.cs too. for cors issues, you should first add the cors on ConfigureServices like this

services.AddCors(options =>
        {
            options.AddPolicy("CorsPolicy",
                builder => builder
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                    .AllowAnyOrigin());
        });

in configure method add the cors with this policy like this

app.UseRouting();
app.UseCors("CorsPolicy");

I think it's about your controller routing. Your controller route([Route("api/account")]) means when you want to call its actions, you shouldn't specify Action in your URL. AccountController can one action per each HTTP verb(you can't have more than one HttpGet in AccountController). If you have more than one HttpGet in your AccountController change its routing like this:

[Route("api/[Controller]/[Action]")]

and then add action name to URL in front-end part:

const result = await this.axios.get(`${this.apiUrl}/account/getaccount`);
Related