Frank-Medium
Frank-Medium

Reputation: 223

React asp.net SPA calling API on same app service

I have one solution that includes two projects:

I have deployed both of these projects to one Azure app service using virtual directories. Virtual Directory Setup

When the Foo app makes a call to https://azureFooapp.com/api/getData all that is returned is the index.html file from the Foo project. Instead of actually calling the endpoint located in the Bar API project.

If I remove the Foo project project from the App Service I am able to hit the endpoint https://azureFooapp.com/api/getData successfully.

Foo Startup.cs

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }
    
    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();

        // In production, the React files will be served from this directory
        services.AddSpaStaticFiles(configuration =>
        {
            configuration.RootPath = "ClientApp/build";
        });

        services.AddControllers()
        .AddNewtonsoftJson();

        services.AddMvc().AddNewtonsoftJson(o =>
        {
            o.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }

        app.UseHttpsRedirection();
        app.UseStaticFiles();
        app.UseSpaStaticFiles();

        app.UseRouting();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller}/{action=Index}/{id?}");
        });

        app.UseSpa(spa =>
        {
            spa.Options.SourcePath = "ClientApp";

            if (env.IsDevelopment())
            {
                spa.UseReactDevelopmentServer(npmScript: "start");
            }
        });
    }
}

Bar Startup.cs

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.Configure<ConnectionStrings>(Configuration.GetSection("ConnectionStrings"));

    services.AddControllers();
    services.AddControllersWithViews();

    
    services.AddControllers()
    .AddNewtonsoftJson();

    services.AddMvc().AddNewtonsoftJson(o =>
    {
        o.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    });

    services.AddCors(options => 
    { 
        options.AddPolicy("AllowSpecificOrigin", builder =>
        { 
            builder.WithOrigins("https://localhost").AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod(); 
        }); 
    });
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseCors("AllowSpecificOrigin");

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

Can anyone please help get this working? If anymore information is needed please let me know

Upvotes: 1

Views: 1073

Answers (2)

Frank-Medium
Frank-Medium

Reputation: 223

I have now managed to resolve this issue by modifying the code in Foo Startup.cs with the below

 app.MapWhen(x => !x.Request.Path.Value.ToLower().StartsWith("/api"), builder =>
        {
            builder.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseReactDevelopmentServer(npmScript: "start");
                }
            });
        });

After this I restarted the App Service

Upvotes: 1

Jason Pan
Jason Pan

Reputation: 22067

I suggest you put the api project under wwwroot and the react project in the virtual directory.

Like :

Virtual path     Physical Path                     Type   
/                site\wwwroot                    Application
/pages           site\wwwroot\react_folder       Application

Suggestions

  1. Why is it not recommended to put nodejs projects, such as react, angular, and vue projects into the main application?

    After a lot of testing, I found that when the main application is put into these three items, the virtual application will not take effect, and it can work normally if they are put into the virtual application.

  2. (Not recommended) After the react project is compiled, if the content of the dist folder is released, the routing access of virtual applications is supported in iis, and this is not recommended.

Upvotes: 1

Related Questions