0

I had this problem where reloading a page on production (Azure Linux App Service) were throwing a 404.

I managed to fix this using hashLocationStrategy in my app.routing.module.ts. But it is not SEO safe. I understand that it works because the API ignores what's after the hash, but I was wondering how could I rollback this change on the routing strategy, and handle the redirection in my API.

I looked up for something on the Internet, but I didn't manage to find anything working. I tried using app.MapWhen() or modifying app.MapControllers() to app.UseEndpoints(options => options.MapControllers()). And the more I look up for this, the more I find it very confusing.

Here is my current Program.cs :

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHttpsRedirection(options => options.HttpsPort = 443);

// Add services to the container.
builder.Services.AddCors(options => 
    options.AddPolicy("Default", policyBuilder =>
    {
        policyBuilder
            .AllowAnyOrigin()
            .AllowAnyMethod()
            .AllowAnyHeader();
    })
);

builder.Services.AddControllers();
builder.Services.AddAuthentication(x =>
{
    x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{
    o.SaveToken = true;
    o.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuer = false,
        ValidateAudience = false,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(
            Encoding.UTF8.GetBytes(
                builder.Configuration
                    .GetSection(ApplicationSettings.Section)
                    .GetValue<string>("JWT:Secret")))
    };
});

builder.Services.AddSwaggerGen(config =>
{
    config.SwaggerDoc("Backend", new OpenApiInfo { Title = "Backend", Version = "0.1"});

    config.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
    {
        In = ParameterLocation.Header,
        Description = "Please enter a valid token",
        Name = "Authorization",
        Type = SecuritySchemeType.Http,
        BearerFormat = "JWT",
        Scheme = "Bearer"
    });

    var securityRequirement = new OpenApiSecurityRequirement
    {
        {
            new OpenApiSecurityScheme
            {
                Reference = new OpenApiReference
                {
                    Type = ReferenceType.SecurityScheme,
                    Id = "Bearer"
                }
            },
            Array.Empty<string>()
        }
    };

    config.AddSecurityRequirement(securityRequirement);
});

builder.Services.Configure<ApplicationSettings>(
    builder.Configuration.GetSection(ApplicationSettings.Section));

builder.Services.AddDbContext<InstituteDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("Database")));

// Repositories
builder.Services.AddScoped<ICareCategoryRepository, CareCategoryRepository>();
builder.Services.AddScoped<ICareRepository, CareRepository>();

builder.Services.AddScoped<IUserRepository, UserRepository>();

builder.Services.AddScoped<IReservationInfoRepository, ReservationInfoRepository>();

// Services
builder.Services.AddScoped<ICareService, CareService>();
builder.Services.AddScoped<ICareCategoryService, CareCategoryService>();

builder.Services.AddScoped<IUserService, UserService>();

builder.Services.AddScoped<IReservationService, ReservationService>();

builder.Services.AddScoped<IReservationInfoService, ReservationInfoService>();

var app = builder.Build();

using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;

    var context = services.GetRequiredService<InstituteDbContext>();
    context.Database.Migrate();
}

app.UseMiddleware<ExceptionHandlerMiddleware>();
app.UseMiddleware<JwtMiddleware>();
app.UseMiddleware<AntiXssMiddleware>();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI(options =>
    {
        options.SwaggerEndpoint("/swagger/Backend/swagger.json", "Backend");
    });
}
else
{
    app.UseHttpsRedirection();
}

app.UseRouting();

app.UseCors("Default");

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

app.UseDefaultFiles();
app.UseStaticFiles();

app.MapControllers();

app.Run();

EDIT : Here is the .htaccess file I used (there is more than just url rewriting)

RewriteEngine On

# Redirection to HTTPS:
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

# Redirection of requests to index.html
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^.*$ - [NC,L]
# Redirect all non-file routes to index.html
RewriteRule ^(?!.*\.).*$ index.html [NC,L]
4
  • I'm not sure to understand well your question, the 404 you get is when you are in a page other than the "home page" and you reload the page ? If this is your issue it is related to the fact that the routing inside your angular application is managed by angular not your server, if you did not install NGINX on your Linux server you cannot navigate into your application by the URL. serverlab.ca/tutorials/linux/web-servers-linux/… I hope this help otherwhise explain a little more your problem Commented Jun 20, 2023 at 7:56
  • This isn't a .Net issue, it's an issue related to whichever web server you are running. That server needs to redirect all routing URLs to index.html. This can be done, for example, in your nginx.conf for NGINX, or in your .htaccess for Apache. Commented Jun 20, 2023 at 8:07
  • @ Max I'll take a look to your link :) @ WillAlexander I looked a bit into that, I found out that Linux App Services are running on Apache. I tried adding an .htaccess file to my app (in WebApi/ClientApp/src, and in WebApi). But it did not work. Maybe I did misconfigure my app to take into consideration the .htaccess file. I am quite new to deploying stuff so it is also a possibility How and where would you add the .htaccess file so that the server behaves correctly ? I'll update my question to add .htaccess I used Commented Jun 20, 2023 at 8:18
  • @WillAlexander don't know if you saw my questions. Do you have any idea on this ? I did not have much time to spent on this (it's a side project) so I do not have new infortmation. I looked over Max's answer but it won't work as Linux app services are running on Apache (I'm not sure though, I thinks it's actually running on Kestrel. There is no clear documentation about that). Commented Jun 28, 2023 at 7:38

0

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.