2

I have a project that I created based on the ASP.NET Core 3 Angular template that works great locally. However, when I deploy the application to an Azure App Service, the site will start, but then immediately fails when the first API calls it makes against the server fails because it's returning the contents of index.html, rather than the expected API results. This particular call SHOULD be returning a simple true/false, but is index.html instead. Here's my Startup.cs:

using System;
using AutoMapper;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SpaServices.AngularCli;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using StaticSphere.Bookings.Converters;
using StaticSphere.Bookings.Data;
using StaticSphere.Bookings.Extensions;
using StaticSphere.Bookings.Middleware;

namespace StaticSphere.Bookings
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton(Configuration);
            services.AddDbContext<BookingsDbContext>(options =>
            {
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
            });

            services.AddConfiguredIdentity(Configuration); // This just wraps up my ASP.NET Identity configuration

            services.Configure<ApiBehaviorOptions>(options =>
            {
                options.SuppressModelStateInvalidFilter = true;
            });

            services.AddAutoMapper(typeof(Startup));
            services.AddControllers()
                .AddJsonOptions(options =>
                {
                    options.JsonSerializerOptions.Converters.Add(new DateTimeConverter());
                })
                .SetCompatibilityVersion(CompatibilityVersion.Version_3_0);

            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/dist";
            });

            services.AddLocalRegistrations(); // This wraps up my custom services
        }

        public static 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();

            if (!env.IsDevelopment())
            {
                app.UseSpaStaticFiles();
            }

            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();

            app.UseWhen(context =>
                context.Request.Path.StartsWithSegments("/api", StringComparison.InvariantCultureIgnoreCase) &&
                !context.Request.Path.StartsWithSegments("/api/auth", StringComparison.InvariantCultureIgnoreCase),
                builder =>
            {
                builder.UseMiddleware<ActivityMiddleware>(); // This just makes a call to log user activity to the database.
            });

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{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.Options.StartupTimeout = TimeSpan.FromSeconds(120);
                }
            });   
        }
    }
}

I've briefly experimented with using rewriting, but didn't have any success with it, as none of the examples that I found online seemed set up to work with the app.UseSpa call, nor does it seem logical that I would need to use it, since the calls work correctly at DEV time, but maybe I missed something obvious?

Thanks in advance for any help here!

5
  • I have the same issue. I started by using the Angular .Net 3 Core template. It works fine within VS but seems to return the static file handler. What's odd is that, if I go back to the default template and deploy it as-is, the api calls work. Startup.CS matches up for me. Commented Jan 2, 2020 at 18:56
  • Interesting. Well, I think I'm going to try creating a raw template, deploy that, then start adding in, one by one, the middleware that I'm using in my actual app until it stops working. Maybe that'll provide a clue. Thanks for following up, and I'll let you know if this gets me anywhere. Commented Jan 4, 2020 at 23:41
  • 2
    I fixed mine. The issue was that it was swallowing the error... in a sense. The error was related to a call to the database (permissions) and the application was trying to handle it in Startup.cs by redirecting to /Error because of this default line: app.UseExceptionHandler("/Error"); Well, I didn't have a controller to handle this route so instead it returned the default page index.html. I resolved this by creating a web api controller named ErrorController and changing the line to app.UseExceptionHandler("/api/Error/Error");. Commented Jan 6, 2020 at 16:12
  • 1
    This error controller handles it using var exceptionHandlerFeature = HttpContext.Features.Get<IExceptionHandlerFeature>();; Using this I grabbed and returned the error message. Commented Jan 6, 2020 at 16:13
  • LOL Dude, I literally just came to the same conclusion. I've been futzing around with things for the last half hour or so and started digging through my logs. The last time I looked there wasn't really anything meaningful in there, but this time, it specifically mentioned that my database wasn't reachable. I had to open up access to my database for the web app. And boom! It's working! Thanks for, uh, taking this journey with me! :) I'll upvote your response for credit! And good luck! Commented Jan 7, 2020 at 5:03

1 Answer 1

4

Thanks to Zach for his insight on this issue! Ultimately I found that the database wasn't accessible, and needed to open access to it to my application. I'm fairly new to Azure, so I'm still picking up its ins and outs.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.