Shared resource localization is not working - asp.net-core

I am working on shared resource localization in Asp .Net Core 3.1. For that I created resource directory and created SharedResources.cs file.
Root/Resources/SharedResources.cs
Root/Resources/SharedResources.en.resx
I injected code in controller.
public AccountController(IStringLocalizer<SharedResources> sharedLocalizer)
{
_sharedLocalizer = sharedLocalizer;
}
public IActionResult Login(LoginViewModel model)
{
if(loginSuccess == true)
{
return RedirectToAction("Dashboard", "Dashboard");
}
TempData["Error"] = _sharedLocalizer["Error"];
return View(model);
In SharedResources.en.resx
Key : Error
Value : Invalid User
In SharedResources.cs
namespace RootName
public class SharedResources
{
}
It displays Error and it should display Invalid User. Where am I wrong?

For asp.net core 3.x,you need to create SharedResources.cs in your root folder and create SharedResources.en.resx in root/Resources folder like below:
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddLocalization(o =>
{
// We will put our translations in a folder called Resources
o.ResourcesPath = "Resources";
});
services.Configure<RequestLocalizationOptions>(options =>
{
var supportedCultures = new[]
{
new CultureInfo("en"),
new CultureInfo("de"),
};
options.DefaultRequestCulture = new RequestCulture("en");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
}
// 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("/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.UseRouting();
var localizationOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>().Value;
app.UseRequestLocalization(localizationOptions);
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}

Related

asp.net core web Api integration testing with startup having static file configuration

I was trying to implement integration testing for my api. But, it is saying System.IO.DirectoryNotFoundException : ..WebApi.IntegrationTest\bin\Debug\net6.0\Files\ while I run the test
here is my startup code
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseBlazorFrameworkFiles();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), #"Files")),
RequestPath = new PathString("/Files")
});
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("CorsPolicy");
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.Initialize(Configuration);
}
when I comment out UseStaticFiles it passes the test else it fails with the above. exception
here is my CustomWebApplicationFactory
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseInMemoryDatabase("ApplicationDbContextInMemoryTest");
})
.AddControllers()
.AddApplicationPart(typeof(Startup).Assembly);
var sp = services.BuildServiceProvider();
using (var scope = sp.CreateScope())
{
var scopedService = scope.ServiceProvider;
var context = scopedService.GetRequiredService<ApplicationDbContext>();
var logger = scopedService.GetRequiredService<ILogger<CustomWebApplicationFactory<TStartup>>>();
context.Database.EnsureCreated();
try
{
Utilities.InitializeDbForTests(context);
}
catch (Exception ex)
{
logger.LogError(ex, $"An error occured seeding the database with test messages, Error: {ex.Message}");
}
}
});
}
protected override IHost CreateHost(IHostBuilder builder)
{
builder.UseContentRoot(Directory.GetCurrentDirectory());
return base.CreateHost(builder);
}
public HttpClient GetAnonymousClient()
{
return CreateClient();
}
}
I tried a lot to fix it but I was not able, please help me, thank you!

Where will the default _logger file be stored?

Created a sample webAPI(5.0) in asp.net core. It comes with WeatherForecastController.cs
Now this is the code :
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
_logger.LogInformation("entered");
var rng = new Random();
_logger.LogInformation("exited");
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
})
.ToArray();
}
I entered the _logger.LogInformation("entered");
Now where will I find this information ? will there be any file located? I am in an understanding that a file will be created and all this logging info will be stored.
this is my startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddFluentValidation(s =>
{
s.RegisterValidatorsFromAssemblyContaining<Startup>();
});
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApi", Version = "v1" });
});
services.AddDbContext<ApplicationContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection"),
b => b.MigrationsAssembly(typeof(ApplicationContext).Assembly.FullName)));
#region Repositories
services.AddTransient(typeof(IGenericRepository<>), typeof(GenericRepository<>));
services.AddTransient<IDeveloperRepository, DeveloperRepository>();
services.AddTransient<IProjectRepository, ProjectRepository>();
services.AddTransient<IUnitOfWork, UnitOfWork>();
#endregion
}
// 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", "WebApi v1"));
}
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
By default is it logging to the output console.
You can find more information about ASP.NET Core logging here

Error hosting web API in Blazor server web application

We have an existing .NET 5.0 Blazor web application. I have added an ASP.NET Core Web API to the same project because I want to provide a REST interface to external consumers. When I request http://localhost:5000/stripe/customerwebhook, I get a 404 not found error. What could I be missing?
My CustomerWebhookController API class looks like the following:
[Route("stripe/[controller]")]
[ApiController]
public class CustomerWebhookController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> Index()
{
return Ok();
}
}
Startup.cs:
using Microsoft.AspNetCore.Mvc;
public partial class Startup
{
public void ConfigureServices(IServiceCollection services)
{
OnConfiguringServices(services);
services.AddHttpContextAccessor();
services.AddScoped<HttpClient>(serviceProvider =>
{
var uriHelper = serviceProvider.GetRequiredService<NavigationManager>();
return new HttpClient
{
BaseAddress = new Uri(uriHelper.BaseUri)
};
});
services.AddHttpClient();
services.AddAuthentication();
services.AddAuthorization();
services.AddControllersWithViews();
services.AddMvc(options => options.EnableEndpointRouting = false)
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
services.AddRazorPages();
services.AddServerSideBlazor().AddHubOptions(o =>
{
o.MaximumReceiveMessageSize = 10 * 1024 * 1024;
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ApplicationIdentityDbContext identityDbContext)
{
OnConfiguring(app, env);
if (env.IsDevelopment())
{
Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
app.UseDeveloperExceptionPage();
}
else
{
app.Use((ctx, next) =>
{
return next();
});
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseMvcWithDefaultRoute();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
}

Enabling basic authentication on ASP NET Core - 404

I am using this middleware as the concepts are new to me
https://github.com/blowdart/idunno.Authentication/tree/master/src/idunno.Authentication.Basic
I've implemented startup exactly as it says
However, every time I post to the WeatherForecast end point I get a 404 if the [Authorize] identifier is there. I did some reading and hence added the AuthenticationSchemes but same result
It cannot be a missing redirect, which is the other problem, as the controller is just returning content in that page?
Please can someone point me in the right direction?
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddMvc();
services.AddRazorPages();
services.AddControllersWithViews();
services.AddAuthentication(BasicAuthenticationDefaults.AuthenticationScheme)
.AddBasic(options =>
{
//options.Realm = "idunno";
options.Events = new BasicAuthenticationEvents
{
OnValidateCredentials = context =>
{
if (context.Username == context.Password)
{
var claims = new[]
{
new Claim(
ClaimTypes.NameIdentifier,
context.Username,
ClaimValueTypes.String,
context.Options.ClaimsIssuer),
new Claim(
ClaimTypes.Name,
context.Username,
ClaimValueTypes.String,
context.Options.ClaimsIssuer)
};
context.Principal = new ClaimsPrincipal(
new ClaimsIdentity(claims, context.Scheme.Name));
context.Success();
}
return Task.CompletedTask;
}
};
});
}
Then this
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
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.UseAuthentication();
app.UseAuthorization();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
Controller looks like this:
[Route("[controller]")]
[Authorize(AuthenticationSchemes = idunno.Authentication.Basic.BasicAuthenticationDefaults.AuthenticationScheme)]
public class WeatherForecastController : ControllerBase
{
[HttpGet]
public ActionController<WeatherForecast> Get()
{
return Content("Authorised");
}
}
As per comment, some of the commands were in the wrong order

How to configure dotnetcore 3 site to return 401 with custom authorization filter rather than redirecting to AccessDenied page

I've got a site using the new dotnetcore3 angular template. I've created a custom authorization filter that's currently extremely simple
public class ClaimRequirementFilter : IAuthorizationFilter
{
readonly string _claim;
public ClaimRequirementFilter(string claim)
{
_claim = claim;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
if (_claim != "test")
{
context.Result = new ForbidResult();
}
}
}
public class ClaimRequirementAttribute : TypeFilterAttribute
{
public ClaimRequirementAttribute(string claimType) : base(typeof(ClaimRequirementFilter))
{
Arguments = new object[] {claimType };
}
}
[Route("{jobId}")]
[ClaimRequirement("testfail")]
[HttpGet]
public async Task<IActionResult> GetJob([FromRoute] Guid jobId)
{
//stuff
{
However, whenever a request fails (which will be all of them right now), it 302s me to the AccessDenied page with a returnUrl of the URL I was trying to hit.
However, since this request is being made from my angular client, I would rather it just return a 401 (or 403 since in this case it's because the loggedin user doesn't have permission to do what they're trying to do), and I'm not sure how to configure it.
Per Ruard's request, here is my Startup configuration
public class Startup
{
public Startup(IWebHostEnvironment env, IConfiguration configuration)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.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.AddApplicationInsightsTelemetry();
services.AddDbContext<ApplicationDbContext>(
options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
);
services.AddTransient<EmailSender, EmailSender>();
services.AddScoped<IRazorViewToStringRenderer, RazorViewToStringRenderer>();
services.Configure<EmailServiceConfiguration>(Configuration.GetSection("EmailServiceConfiguration"));
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddDefaultTokenProviders()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer(options =>
{
options.UserInteraction.LoginUrl = "/auth/login";
options.UserInteraction.LogoutUrl = "/auth/logout";
})
//.AddDeveloperSigningCredential()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
services.AddAuthentication()
// .AddGoogle(options =>
// {
// IConfigurationSection googleAuthNSection = Configuration.GetSection("Authentication:Google");
// options.ClientId = googleAuthNSection["ClientId"];
// options.ClientSecret = googleAuthNSection["ClientSecret"];
// })
.AddIdentityServerJwt();
services.AddControllersWithViews().AddRazorRuntimeCompilation();
services.AddRazorPages(options =>
{
options.Conventions.AddAreaPageRoute("Identity", "/Identity/Account/Login", "/auth/login");
});
services.AddAuthorization(options =>
{
// options.AddPolicy("RequireAdmin", policy =>
// {
// policy.RequireRole("Admin");
// });
// options.AddPolicy("CreateInternalUsers", policy =>
// {
// // policy.RequireRole("Admin");
// policy.RequireClaim("CreatePPGUser");
// });
});
// In production, the Angular files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.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, ApplicationDbContext context, IServiceProvider services)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
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();
}
context.Database.Migrate();
app.UseHttpsRedirection();
app.UseStaticFiles();
if (!env.IsDevelopment())
{
app.UseSpaStaticFiles();
}
app.UseRouting();
app.UseAuthentication();
app.UseIdentityServer();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}"
);
endpoints.MapRazorPages();
});
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");
}
});
CreateUserRoles(services).Wait();
}
}
You should add a controller that serves as api. From the documentation:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
Methods from this controller will return the StatusCode instead of redirecting the user to a view.
Update
Based on your startup, it seems that you are not setting the CompatibilityVersion:
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
As documented, this is required in combination with ApiController:
The preceding change:
Is required to use the [ApiController] attribute at the controller level.
Opts in to potentially breaking behaviors introduced in ASP.NET Core 2.2.
In your case, assuming version 3.0:
services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
})
.SetCompatibilityVersion(CompatibilityVersion.Version_3_0);