I've moved the scaffolded Identity Razor Pages from a blazor server app into a separate project(RCL). There are no build/compile or runtime errors. The project runs.
When I browse to /Identity/Account/ForgotPassword I get:
"Sorry there's nothing at this address"
I am calling
services.AddRazorPages() in my main blazor project and also have a reference like so in app.razor:
<Router AppAssembly="#typeof(App).Assembly"
AdditionalAssemblies="new[] {
typeof(DapperIdentity.Controllers.IdentityController).Assembly,
typeof(IdentityUI.Pages.UsersEditPage).Assembly
}">
The razor pages are in the same project as IdentityUI.Pages.UsersEditPage as there are blazor components in there. (Note, the blazor components work.)
Program.cs:
var builder = WebApplication.CreateBuilder(args);
string connectionString;
if (builder.Environment.IsDevelopment())
{
var conStrBuilder = new SqlConnectionStringBuilder(builder.Configuration.GetConnectionString("DefaultConnection"));
conStrBuilder.Password = builder.Configuration["ConnectionStringPasswords:Development"];
//conStrBuilder.CommandTimeout=60;
conStrBuilder.ConnectTimeout=30;
connectionString = conStrBuilder.ConnectionString;
}
else
{
connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
}
builder.Services.AddDbConnectionInstantiatorForRepositories<MySqlConnection>(connectionString);
builder.Services.AddDapperIdentityWithCustomCookies(TimeSpan.FromDays(10), false, true);
builder.Services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<DapperIdentity.Models.CustomIdentityUser>>();
builder.Services.AddMyAppServices(builder.Environment);
StaticWebAssetsLoader.UseStaticWebAssets(builder.Environment, builder.Configuration);
// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddMudServices();
builder.Services.AddHttpClient();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
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.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapBlazorHub();
app.MapControllers();
app.UseEndpoints(endpoints => {
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
endpoints.MapRazorPages(); });
app.Run();
I'm a little stuck on where to go from here in order to get the razor pages working from my blazor server app.
Related
What happened: The default Healthchecks UI page displays a blank page.
What you expected to happen: To properly see the default Healthchecks UI page.
How to reproduce it (as minimally and precisely as possible): In Program.cs, use app.MapHealthChecks() and app.MapHealthChecksUI()
Source code sample: Below is the Program.cs file.
using HealthChecks.UI.Client;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using MonitoringApi.HealthChecks;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddHealthChecks()
.AddCheck<RandomHealthCheck>("Site Health Check")
.AddCheck<RandomHealthCheck>("Database Health Check");
builder.Services.AddHealthChecksUI(opts =>
{
opts.AddHealthCheckEndpoint("api", "/health");
opts.SetEvaluationTimeInSeconds(5);
opts.SetMinimumSecondsBetweenFailureNotifications(10);
}).AddInMemoryStorage();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.MapHealthChecks("/health", new HealthCheckOptions
{
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
app.MapHealthChecksUI();
app.Run();
Anything else we need to know?: Possibly occuring if you have installed Watchdogs before.
Environment:
.NET Core version 6
Healthchecks version 6.0.5
Operative system: Windows 10
The solution was by replacing in Program.cs, the app.MapHealtchChecks() and app.MapHealthChecksUI() with app.UseHealthChecks() and app.UseHealthChecksUI() as seen below.
using HealthChecks.UI.Client;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using MonitoringApi.HealthChecks;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddHealthChecks()
.AddCheck<RandomHealthCheck>("Site Health Check")
.AddCheck<RandomHealthCheck>("Database Health Check");
builder.Services.AddHealthChecksUI(opts =>
{
opts.AddHealthCheckEndpoint("api","/health");
opts.SetEvaluationTimeInSeconds(5);
opts.SetMinimumSecondsBetweenFailureNotifications(10);
}).AddInMemoryStorage();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.UseHealthChecks("/health", new HealthCheckOptions
{
// json response
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
app.UseHealthChecksUI(setup =>
{
setup.UIPath = "/healthchecks-ui"; // ui path
setup.ApiPath = "/health-ui-api"; // this is the internal ui api
});
app.Run();
I am trying to add a web API endpoint to an existing web application. How do I go about doing this?
Here is the GitHub link https://github.com/GrindingLife/BHFunctioning
I have tried adding a scaffold of an API controller in the controller folder. When launched accessing the localhost/api does not work. I do not know what to add to the Program.cs file. All the examples that I've seen are for startup.cs file instead of program.cs
Here is my program.cs file
using BHFunctioning.Controllers;
using BHFunctioning.Data;
using BHFunctioning.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddAuthorization(options =>
{
options.AddPolicy("RequireAdministratorRole",
policy => policy.RequireRole("Administrator"));
});
builder.Services.AddIdentity<IdentityUser, IdentityRole>(options => options.SignIn.RequireConfirmedAccount = false)
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddRoles<IdentityRole>()
.AddDefaultUI()
.AddDefaultTokenProviders();
builder.Services.AddSingleton<IFileProvider>(
new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "wwwroot")));
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
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.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
I have solved it, i just needed to add the following into Program.cs and call it using localhost:2444/api/{controller name}
builder.Services.AddRazorPages();
builder.Services.AddControllers();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
});
I'm currently trying to get a token from the bootstrap context in a test application that I have put together to help understand a separate issue. This is the first time that I have configured a .net 6 web application (generally I work in Angular) authentication pipeline so I'm not sure if I am missing something simple.
The code that I have configured in program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"));
builder.Services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
builder.Services.AddRazorPages()
.AddMicrosoftIdentityUI();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
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();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();
app.Run();
When I access HttpContext.User.Identities.First() - I have access to a valid object and the user is shown as successfully authenticated. However, the BootstrapContext is always null...I did some digging and found that I might need to configure the auth service to save tokens, I tried that using the following alternative code but still no luck:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(x =>
{
var configurationSection = builder.Configuration.GetSection("AzureAd");
x.ClientId = configurationSection["ClientId"];
x.TenantId = configurationSection["TenantId"];
x.ClientSecret = configurationSection["ClientSecret"];
x.Domain = configurationSection["Domain"];
x.CallbackPath = configurationSection["CallbackPath"];
x.Instance = configurationSection["Instance"];
x.SaveTokens = true;
});
Does anyone have any ideas as to how I can get the BootstrapContext populated?
Alternatively, given the fact that I have an authenticated user, is there a way to create a new instance of GraphServiceClient using the HttpContext.User object? - that is ultimately what I'm trying to achieve here.
I've just created a new ASP.NET Core application using Visual Studio, it has the authentication type set to "Individual Accounts":
I've added some code to handle OIDC:
builder.Services.AddAuthentication().AddOpenIdConnect(openIdOptions =>
{
openIdOptions.ClientId = "myClientId";
openIdOptions.Authority = "myAuthority";
openIdOptions.ResponseType = OpenIdConnectResponseType.Code;
openIdOptions.GetClaimsFromUserInfoEndpoint = false;
openIdOptions.CallbackPath = "/signin-oidc";
openIdOptions.SaveTokens = true;
Which is all well and good, I can click to login with OpenIdConnect:
When I log in with the provided credentials it pops up asking me to Associate my OpenIdConnect account:
I don't want to have to do this. Retrieving the access token and id token is sufficient for what I want to do, I don't require a local copy of the user. Being new to ASP.net and having not used Razor before it's not immediately obvious what code I should delete — if that's even the correct approach. I've played around with deleting various bits such as the Db setup as I don't really require it, although I suspect Razor does in some regard.
The Program.cs looks as follows:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options =>
{
})
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddAuthentication().AddGoogle(googleOptions =>
{
googleOptions.ClientId = builder.Configuration["Authentication:Google:ClientId"];
googleOptions.ClientSecret = builder.Configuration["Authentication:Google:ClientSecret"];
});
builder.Services.AddAuthentication().AddOpenIdConnect(openIdOptions =>
{
openIdOptions.ClientId = "clientId";
openIdOptions.Authority = "authority";
openIdOptions.ResponseType = OpenIdConnectResponseType.Code;
openIdOptions.GetClaimsFromUserInfoEndpoint = false;
openIdOptions.CallbackPath = "/signin-oidc";
openIdOptions.SaveTokens = true;
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapRazorPages();
app.UseEndpoints(endpoints => { endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}"); });
app.Run();
I am currently testing out an asp.net core 3 blazor server-side app. I built a middleware extension in f#, and called it from c# within the Configure method of the Startup class. It appears to initially attempt the redirect as the correct url is called, but I get an error page stating that the page isn't redirecting properly. What am I missing here.
F#:
type CheckMaintenanceStatusMiddleWare(next : RequestDelegate) =
let _next = next
member this.InvokeAsync(context : HttpContext) =
let statusCheck = true
if statusCheck
then
Task.Run(fun arg -> context.Response.Redirect("/Maintenance"))
else
_next.Invoke(context)
[<Extension>]
type CheckMaintenanceStatusMiddleWareExtensions() =
[<Extension>]
static member inline UseCheckMaintenanceStatus(builder : IApplicationBuilder) =
builder.UseMiddleware<CheckMaintenanceStatusMiddleWare>()
C#
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseCheckMaintenanceStatus();
var connectionString = Configuration.GetConnectionString("DefaultConnection");
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();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
//app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
Razor Component:
#page "/Maintenance"
<h3>Maintenance</h3>
#code {
}
A redirect-loop might happens as below:
(redirect-loop might happens)
Request Process Starts <---------------------------+
|-----> CheckMaintenanceStatusMiddleWare |
(check status) |
if fail then redirect to '/Maintenance' -------------->|
else
|----> go to inner middlewares by next(context)
To avoid the endless redirect loop, check whether the current path has already been changed to /Maintenance:
if statusCheck && context.Request.Path.Value <> "/Maintenance" then
... redirect
else
... invoke inner middlewares