How do I enable compression for my API on the linux service plan? - asp.net-core

I'm deploying a .net-core web API to the Linux app service plan. I haven't created a DOCKERFILE. Just building production release and deploying. Based on the response headers in production, it appears to be using the Kestrel server. I found in the MS documentation that one can enable compression in the code. This approach seems to work perfectly locally, however I do not see the Content-Encoding header on my web API call while in production.

You can add below code in your startup.cs file. It works for me.
// Configure Compression level
services.Configure<GzipCompressionProviderOptions>(options => options.Level = CompressionLevel.Fastest);
// Add Response compression services
services.AddResponseCompression(options =>
{
options.Providers.Add<GzipCompressionProvider>();
options.EnableForHttps = true;
});
And you also need add app.UseResponseCompression(); in configure function.
Test Result:
My Startup.cs file.
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.ResponseCompression;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.OpenApi.Models;
using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.Linq;
using System.Threading.Tasks;
namespace corewebapp_linux
{
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)
{
// Configure Compression level
services.Configure<GzipCompressionProviderOptions>(options => options.Level = CompressionLevel.Fastest);
// Add Response compression services
services.AddResponseCompression(options =>
{
options.Providers.Add<GzipCompressionProvider>();
options.EnableForHttps = true;
});
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "corewebapp_linux", Version = "v1" });
});
}
// 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.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "corewebapp_linux v1"));
}
app.UseResponseCompression();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}

Related

I cannot access to the login and register view after scaffolding

I am making a web application with ASP.NET Core 5 MVC.
I have created controllers and views and now I am trying to implement the identity views so I made scaffolding in my project. It created a new folder Account with the different views that Identity brings, but when my application is being executed I cannot access to any scaffolded view it shows me blank page and the url link is combined with link of the currently displayed page.
These is my code in the Startup class
using CSFYshop.Data;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CSFYshop
{
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.AddDistributedMemoryCache();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(30);
//options.Cookie.HttpOnly = true;
options.Cookie.IsEssential = true;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDatabaseDeveloperPageExceptionFilter();
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddControllersWithViews();
}
// 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.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Home/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.UseSession();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllerRoute(
name: "area",
pattern: "{area=Customer}/{controller=Home}/{action=Index}/{id?}"
);
});
}
}
}
Scaffolded files
Web page
I tried new scaffold but it didn't work

Why Is SwashBuckle AddSwaggerGen CustomSchemaIds not used in generating the swagger.json and Swagger UI?

I am attempting to try to modify/map some of the schema types in an open api document. When I run this ASPNET Web API, I get the Swagger UI with the schemas at the bottom. But, it does not use the options.CustomSchemaIds(CustomSchemaGenerator.GetCustomSchemaId) configuration. (It does not hit any breakpoint, nor do the returned results affect the output).
Why would it not use this configuration?
using System;
using System.Diagnostics;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.CustomSchemaIds(CustomSchemaGenerator.GetCustomSchemaId);
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
public static class CustomSchemaGenerator
{
public static string GetCustomSchemaId(Type type)
{
if (type.IsGenericTypeDefinition)
{
Debugger.Break();
}
if (type.ToString().Contains("ListResponse"))
{
Debug.Write(type.ToString());
}
return type.ToString();
}
}

Getting 401 error without any message while authorizing dotnet core web api with keycloack

I was setting authentication and authorization for my dotnet core application (3.1 version). I set up a keycloak server as my identity provider. I got a JWT token from keycloak and i used it while calling my api method. I am always getting 401 error. I have checked almost all the Keycloak configurations and i am not able to find the issue.
My JWT token is
eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJza0dldkJuZnhieWlCSF9sOC1ZSEpxVnk2bm8yV3c0eG14a0xjeVlvMXRzIn0.eyJqdGkiOiJlNjI3NTA3MC05MTA0LTRhMGQtOGYxNC1mNzdkY2FjMjYzMDUiLCJleHAiOjE1ODg1MjMxMTcsIm5iZiI6MCwiaWF0IjoxNTg4NTE5NTE3LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvZ2FkZ2VvbiIsImF1ZCI6WyJmdHMtcG9ydGFsIiwiYWNjb3VudCJdLCJzdWIiOiJiMzIxYTA0Ny0zNzBkLTRlOTMtOWQ0MS1jZmRjYWMyN2I1ZjYiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJmdHMtcG9ydGFsIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiYmEzNmRiYjctMGYyOC00MDY4LWIwYmQtMDUxMmQxN2Q1MzEyIiwiYWNyIjoiMSIsInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIl19LCJyZXNvdXJjZV9hY2Nlc3MiOnsiZnRzLXBvcnRhbCI6eyJyb2xlcyI6WyJmdHNfYWRtaW4iXX0sImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJBZG1pbmlzdHJhdG9ycyIsIm1hbmFnZS1hY2NvdW50LWxpbmtzIiwidmlldy1wcm9maWxlIl19fSwic2NvcGUiOiJmdHNfcG9ydGFsIGVtYWlsIHByb2ZpbGUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJQcml5ZXNoIEsiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJwa2FyYXRoYSIsImdpdmVuX25hbWUiOiJQcml5ZXNoIiwiZmFtaWx5X25hbWUiOiJLIiwiZW1haWwiOiJwcml5ZXNoa2FyYXRoYUBnbWFpbC5jb20iLCJmdHMtcnVsZXMiOlsiZnRzX2FkbWluIl19.gFjqPSmyXvk78OhbPJ853upCHIHZdsAsjT1Psc7pzBqv30unH0EyCk3chTK0_87J-5bH2QAEyShKc0QVENMEL2PEhIKvgI7hdqT7oBKiTu3Ux2U5c2KbL9Dbism7nhr9FidrrkxtOsJUyR9hbZCGLnrmoHJEkNMvp3usS4HO1AxwaCSKUVXyNy3FmQJnY_R33IdSaiKsaLCJg57SIak1SexPnlUyFT6_yvbyKLjgpuL3Uk5TasQ3A8GVM2RRGVZa-s9L75rsFflkmRtAvCQca3QCRq8vHl929q6yy2TSrNlVLCeQxdK3Yapk-k_KSFS0dkoCgSQ3F5oGOECxPw-pBg
My Startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Fts.App.Definitions;
using Fts.App.Services;
using Fts.Data.Defnitions;
using Fts.Data.Repository;
using Lbs.FtsClient;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Fts.Api
{
public class Startup
{
public Startup()
{
Configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
}
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.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer("Bearer",o =>
{
o.Authority = Configuration["Jwt:Authority"];
o.Audience = Configuration["Jwt:Audience"];
o.RequireHttpsMetadata = false;
o.Events = new JwtBearerEvents()
{
OnAuthenticationFailed = c =>
{
c.NoResult();
c.Response.StatusCode = 500;
c.Response.ContentType = "text/plain";
return c.Response.WriteAsync(c.Exception.ToString());
}
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("apiadmin", policy => policy.RequireClaim("fts-rules", "[fts_admin]"));
});
services.AddTransient<IUserRepository, UserRepositiry>();
services.AddTransient<IDbAccess, DbAccess>();
services.AddTransient<ISiteRepository, SiteRepository>();
services.AddTransient<IAssetRepository, AssetRepository>();
services.AddTransient<IAssetService, AssetService>();
services.AddTransient<IFtsWebService, FtsWebService>();
services.AddControllers();
}
// 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.UseCors(builder =>
builder.WithOrigins("http://localhost:4200").AllowAnyMethod().AllowAnyHeader());
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
I added following in my controller.
[Authorize(Roles = "apiadmin")]
[ApiController]
[Route("[controller]")]
Please help on this issue.
Thanks
You should add authentication middleware to your web api application , otherwise JWT bearer authentication won't work :
app.UseRouting();
app.UseAuthentication(); <-- add this line
app.UseAuthorization();

.Net Core 3 Identity register or login links not functional [duplicate]

After having a hard time getting my area to show with endpoint routing i managed to fix it in this self answered thread (albeit not in a very satisfactory way) : Issue after migrating from 2.2 to 3.0, default works but can't access area, is there anyway to debug the endpoint resolution?
However Identity UI doesn't show at all for me, i get redirected on challenge to the proper url but the page is blank. I have the identity UI nugget package added and, changing from mvc routing to endpoint routing, i didn't change anything that should break it.
I also don't seem to do much different than what the default project does and identity works there even if i add a route as i did in my hack.
As often the issue hides around the line and not on it i'm posting my whole startup file.
Regular (default) controllers work.
Admin area works (one of the page doesn't have authentication and i can access it)
Any other Admin area page redirect me to /Identity/Account/Login?ReturnUrl=%2Fback (expected behavior) but that page as well as any other /Identity page i tested is blank with no error while running in debug and with a debugger attached.
Any help is most appreciated, full startup bellow:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using FranceMontgolfieres.Models;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
namespace FranceMontgolfieres
{
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.AddSingleton<IConfiguration>(Configuration);
services
.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services
.AddDbContext<FMContext>(options => options
.UseLazyLoadingProxies(true)
.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services
.AddDefaultIdentity<IdentityUser>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<FMContext>();
services
.AddMemoryCache();
services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = Configuration.GetConnectionString("SessionConnection");
options.SchemaName = "dbo";
options.TableName = "SessionCache";
});
services.AddHttpContextAccessor();
services
.AddSession(options => options.IdleTimeout = TimeSpan.FromMinutes(30));
services.AddControllersWithViews();
services.AddRazorPages();
}
// 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.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/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.UseRouting();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseAuthorization();
app.UseSession();
app.UseEndpoints(endpoints =>
{
endpoints.MapAreaControllerRoute("Back", "Back", "back/{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute("default","{controller=Home}/{action=Index}/{id?}");
});
}
private async Task CreateRoles(IServiceProvider serviceProvider)
{
//initializing custom roles
var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
string[] roleNames = { "Admin", "Manager", "Member" };
IdentityResult roleResult;
foreach (var roleName in roleNames)
{
roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
}
}
}
}
The Identity UI is implemented using Razor Pages. For endpoint-routing to map these, add a call to MapRazorPages in your UseEndpoints callback:
app.UseEndpoints(endpoints =>
{
// ...
endpoints.MapRazorPages();
});

Setting RedirectStatusCode for AddHttpsRedirection is not having any effect

Why is the following line not having any effect? It still gives me a 307!
services.AddHttpsRedirection(options => options.RedirectStatusCode = StatusCodes.Status301MovedPermanently);
Startup.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Rewrite;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace blog
{
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.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddHttpsRedirection(options => options.RedirectStatusCode = StatusCodes.Status301MovedPermanently);
services.Configure<RouteOptions>(options =>
{
options.LowercaseUrls = true;
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.Use((context, next) =>
{
context.Request.PathBase = new PathString("/blog");
return next();
});
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc();
}
}
}
As I read your startup config, I see that while not in development mode, you are also using HSTS. If you are testing with Chrome, analyze the network traffic response headers and see if it contains Non-Authoritative-Reason: HSTS. If this is the case, then HSTS is managing the redirect which is expected. The UseHttpsRedirection middleware is more of a fallback in this case for when the client does not support HSTS.
To test using a client that does not support HSTS and ensure the 301 is actually being returned during HTTPS redirection, use an API client such as Postman or Insomnia and view the timeline of the request.