简体   繁体   中英

404 on “Fetch data” in .net core spa template app when using proxy development server

I created an angular project using the .NET core 2.2 and the spa template.

I changed startup.cs to use a proxy development server when serving angular, so I could start my server and my client code independently.

I am using .net core 2.2 documentation and this blog post as a reference:

https://www.codingflow.net/building-single-page-applications-on-asp-net-core-2-2/

app.UseSpa(spa =>
        {
            // To learn more about options for serving an Angular SPA from ASP.NET Core,
            // see https://go.microsoft.com/fwlink/?linkid=864501

            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                //spa.UseAngularCliServer(npmScript: "start");
                spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");
            }
        });

I then ran the following commands in two terminals

dotnet run

_

cd ./ClientApp\
npm start

When I navigate in my browser (chrome) to localhost:4200, webpack will serve my app. However, when I navigate to the fetch-data page from the template, the api call to

http://localhost:4200/api/SampleData/WeatherForecasts

Made in the fetch-data component, part of the standard template

import { Component, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-fetch-data',
  templateUrl: './fetch-data.component.html'
})
    export class FetchDataComponent {
  public forecasts: WeatherForecast[];

  constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
http.get<WeatherForecast[]>(baseUrl + 'api/SampleData/WeatherForecasts').subscribe(result => {
  this.forecasts = result;
}, error => console.error(error));
  }
}

interface WeatherForecast {
  dateFormatted: string;
  temperatureC: number;
  temperatureF: number;
  summary: string;
}

Returns a 404

GET http://localhost:4200/api/SampleData/WeatherForecasts 404 (Not Found)
HttpErrorResponse {headers: HttpHeaders, status: 404, statusText: "Not Found", url: "http://localhost:4200/api/SampleData/WeatherForecasts", ok: false, …}

Of course, this error is not thrown if I run IIS Express in debug mode from visual studio. This will launch a browser window on a different port (not 4200, 44333 usually) where all of the API requests seem to route fine.

I would like to be able to manage my client code independently of my server code. How can I do this? What is wrong with my current setup?

While spliting the SPA project into Front-End and Back-End, you need to change the baseUrl in the angular.

For dotnet run , it will run the .net core project under https://localhost:5001 and http://localhost:5000 .

For npm start , it will run the angular project under http://localhost:4200 .

For @Inject('BASE_URL') baseUrl: string , it will return the angular url instead of core api url.

So, you need to change the request base url and you could try like:

export class FetchDataComponent {
public forecasts: WeatherForecast[];
private apiUrl: string = "https://localhost:5001/";
constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
    http.get<WeatherForecast[]>(this.apiUrl + 'api/SampleData/WeatherForecasts').subscribe(result => {
    this.forecasts = result;
    }, error => console.error(error));
}
}

Since Angualr and Core project run under different ports, you need to enable Cors in the Core project like

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    //rest code
    app.UseCors(builder =>
    {
        builder.AllowAnyOrigin()
                .AllowAnyHeader()
                .AllowAnyMethod()
                .AllowCredentials();
    });
    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller}/{action=Index}/{id?}");
    });

    app.UseSpa(spa =>
    {
        // To learn more about options for serving an Angular SPA from ASP.NET Core,
        // see https://go.microsoft.com/fwlink/?linkid=864501

        spa.Options.SourcePath = "ClientApp";

        if (env.IsDevelopment())
        {
            //spa.UseAngularCliServer(npmScript: "start");
            spa.UseProxyToSpaDevelopmentServer("http://localhost:4200");
        }
    });
}

Thank you Tao Zhou for your answer. For my project, allowing for request from any origin was not an option, so I had to seek out a different answer.

Angular launches by default on port 4200. I created a proxy.conf.json file, and added it to the same directory as my package.json

{
"/api/*": {
  "target": "https://localhost:5001",
  "secure": false,
  "logLevel": "debug",
  "changeOrigin": true
}

}

I then edit my npm start scrip in package.json to be the following

"scripts": {
    "ng": "ng",
    "start": "npm run ng -- serve --proxy-config proxy.conf.json",

This instructs webpack to proxy all routes beginning with /api to port 5001. This is the convention .NET core for all routes that don't serve a view, and is ideal for my project.

This also allows us to keep stricture controls on header and origin for security reasons.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM