proxy.conf.js not working in ASP.NET Core app with Angular
Asked Answered
S

5

7

I am trying to setup an ASP.NET Core app with Angular frontend by following this tutorial. I was already able to successfully create the projects and I am also able to run and debug them flawlessly. The problem is that for some reason I cannot get proxying the backend calls to the ASP.NET Core backend to work. When I try to call an action inside a controller from the angular app, I get a 404 error.

Here is my proxy.conf.js file:

const PROXY_CONFIG = [
  {
    context: [
      "/api/*",
    ],
    target: "https://localhost:7139",
    secure: false
  }
]

module.exports = PROXY_CONFIG;

This is my TestController which I created for testing purposes:

[Authorize]
[ApiController]
[Route("api/[controller]")]
public class TestController : ControllerBase
{
    private readonly ILogger<TestController> _logger;

    public TestController(ILogger<TestController> logger)
    {
        _logger = logger;
    }

    [HttpGet("{id}")]
    public string Get(int id)
    {
        return "Test response";
    }
}

Here is how I am trying to call it from within the Angular app:

this.http.get<string>(`api/test/1`).subscribe((value) => {
  alert(value);
},
(error) => {
  alert(`Error: ${error.error}`);
});

This is how the proxy.conf.js is added in the serve section of my angular.json:

"serve": {
  "builder": "@angular-devkit/build-angular:dev-server",
  "configurations": {
    "production": {
      "browserTarget": "angularproject1.Client:build:production"
    },
    "development": {
      "browserTarget": "angularproject1.Client:build:development"
    }
  },
  "defaultConfiguration": "development",
  "options": {
    "proxyConfig": "src/proxy.conf.js"
  }
},

I already checked the port and in the proxy.conf.json and it does indeed match the port specified in the applicationUrl entry of the launchSettings.json file in the ASP.NET Core project. Here is the content of the launchSettings.json file:

{
  "$schema": "https://json.schemastore.org/launchsettings.json",
  "iisSettings": {
    "windowsAuthentication": true,
    "anonymousAuthentication": false,
    "iisExpress": {
      "applicationUrl": "http://localhost:30959",
      "sslPort": 44345
    }
  },
  "profiles": {
    "WebApplication1": {
      "commandName": "Project",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "https://localhost:7139;http://localhost:5139",
      "dotnetRunMessages": true
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

What could be the reason why this is still not working? Could it be related to the fact that I am trying to get this to work with Windows Authentication, or what am I doing wrong here?

Stanwood answered 11/4, 2022 at 15:0 Comment(10)
If you use postman or curl to talk to your api, does it work? If so, can you take a look at the exact url your frontend is requesting to see if that matches the api call? Then you can figure out if it's an API issue or proxy issue. I would also recommend generating a new empty project with dotnet new webapp so you can easily compare the differences until you find the issue. Another thing, in these cases it's useful to disable auth using things like [AllowAnonymous] but I doubt that's the issue because that should return 401/403Holmberg
In these cases it would also be useful to create a minimal reproducable example so we could run the code ourselvesHolmberg
@S.tenBrinke Yes, if I talk directly to the API via the backend port it works fine. If, however, the call is routed through the Angular Development Server, it never reaches the backend. Therefore I assume that the problem is related to the proxy. Additionally, this is quite literally a brand new project without anything else than the example TestController in it. I have not even started working on anything else yet as I am still trying to setup this project.Stanwood
@S.tenBrinke How/Where can I provide an example? Afaik, I need to provide the entire solution with both projects as otherwise the problem might not be possible to reproduce?Stanwood
@S.tenBrinke I just created a whole new solution from scratch just to figure this out and it seems like the problem might be related to the additional ID argument which I pass to the controller. If I remove the ID argument and just call /api/test, I get a valid response. Why does this happen and how do I allow it to also pass requests with additional arguments to the backend?Stanwood
@S.tenBrinke Just another update: Apparently what I just said previously is not the only problem here. In my new solution which I just created from scratch, I can at least get the API call without the ID working. In my actual project however, it does not even work without the ID. Instead, I get a 400 Bad Request error without any further information about what exactly is wrong about the request whatsoever. I am starting to really get out of ideas on what is going on here. This really does not make any sense to me that I get so much trouble with just a simple GET request that returns a string.Stanwood
@Stanwood I am in the exact same situation, same tutorial,etc... The default /weatherforecast call from the tutorial works but when I try my API calls based on /api/*, I got a 404 error. I have the exactly same configuration as yours. When I try on the backend, it works fine. Did you find a solution?Techy
@SylvainC. Yes, I got it to work just fine. Are you also using windows authentication? I don't remember exactly what was the cause of the problem, but looking at my current proxy.conf.js file it has "/api" listed as context instead of "/api/*". Could that maybe be your problem?Stanwood
@Stanwood Thank you for your feedback. I had already tried the "/api/*" in the proxy.conf.js but with no success for the time being. Will continue to explore.Techy
@SylvainC. I meant to try /api, not /api/*, or did you also try that?Stanwood
A
11

I ran into the same problem. After an hour I remembered that Angular uses ** as a catch all and not *.

const PROXY_CONFIG = [
  {
    context: [
      "/api/**",
    ],
    target: "https://localhost:7139",
    secure: false
  }
]

module.exports = PROXY_CONFIG;

I think that you can use a single * if the proxy.conf.js file is formatted the same as a json file. Like so:

{
  "/api/*": {
    "target": "https://localhost:7139",
    "secure": false
  }
}
Abrogate answered 3/10, 2022 at 14:46 Comment(0)
S
1

I had the same problem using VS Code on Ubuntu. All I needed to do was update my PROXY_CONFIG's context entry to ["/api/**"] then I could change all my controllers to route with the /api/ prefix.

The reason for the proxy is that your dotnet application runs on one port while your angular app on another. When you press F5 VS Code will start both apps, and load the UI through the angular port.

If you look at the fetch-data-component from the default project you'll see it injects a BASE_URL. This base url uses the port the angular app listens on. It is suggested to use this BASE_URL in your service and allow the proxy to do its job.

So for example a request such [angular app]+/api/customers needs to be resolved to the dotnet app, this is the purpose of proxy.conf.js.

To differentiate between an agular route and a dotnet api route the context value in PROXY_CONFIG is used to trigger the redirect to the dotnet app. This is where /api/** comes in as angular uses the **-wildcard to catch all incoming urls starting with the api-prefix, then redirects them to whatever the target value is.

Swithbart answered 4/11, 2022 at 19:5 Comment(1)
btw, you would be able to call your controller methods through noth the dotnet application directly and the angular app since the angular app will reverse-proxy your traffic to the dotnet app.Swithbart
P
0

Try adding your [Controller][Action] explicitly into proxy.config.js

Like this:

const PROXY_CONFIG = [
{
   context: [
   "/api/Test/Get", 
  ],
  target: "https://localhost:7139",
  secure: false
 }
 ]

 module.exports = PROXY_CONFIG;
Proline answered 24/5, 2022 at 3:55 Comment(0)
T
0

I had the same problem (ASP.NET Core 6 / Angular), I fixed it simply using "/api/".

const PROXY_CONFIG = [
  {
    context: [
      "/api/" // <---
    ],
    target: target,
    secure: false
  }
]

Don't forget to change your Controller's routes accordingly.

Triplex answered 25/1, 2023 at 21:23 Comment(0)
C
0

in my case, I had to restart dotnet watch run to restart the proxy

Cicerone answered 20/8, 2023 at 22:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.