Quantcast
Channel: Active questions tagged blazor - Stack Overflow
Viewing all articles
Browse latest Browse all 4839

Blazor server's render mode and Mudblazor

$
0
0

I am new to both Blazor and Mudblazor. Now I have a simple web app with a login page.The login.razor code is shown below.

@page "/Login"@using System.ComponentModel.DataAnnotations@using FileGrid.Entities.Dto@using Microsoft.AspNetCore.Authentication@using Microsoft.AspNetCore.Authentication.Cookies@using System.Security.Claims@using Microsoft.AspNetCore.Identity@inject NavigationManager Navigation<MudPaper Class="mx-auto mt-12 pa-4" Elevation="4" Style="max-width:400px;"><MudText Typo="Typo.h5" Align="Align.Center" Class="mb-4">LogIn</MudText><EditForm Model=@Input OnValidSubmit="HandleValidSubmit" FormName="LoginForm"><DataAnnotationsValidator /><MudTextField @bind-value="@Input.UserName" Immediate="true" T="string" Label="User Name"            For="@(() => Input.UserName)" FullWidth="true" Class="mb-4" Required="true" /><MudTextField @bind-value="@Input.Password" Immediate="true" T="string" Label="Password"            For="@(() => Input.Password)" Variant="Variant.Text" InputType="InputType.Password" FullWidth="true"            Class="mb-4" Required="true" /><MudCheckBox T="bool" Label="Remember Me" @bind-checked="@Input.RememberMe" Class="mb-4" /><MudButton ButtonType="ButtonType.Submit" Color="Color.Primary" Variant="Variant.Filled" Class="mt-2"            FullWidth="true">            LogIn</MudButton></EditForm>    @if (!string.IsNullOrEmpty(errorMessage))    {<MudAlert Class="mt-3" Color="Color.Error">@errorMessage</MudAlert>    }</MudPaper>@code {    [CascadingParameter]    private HttpContext HttpContext { get; set; } = default!;    [SupplyParameterFromForm]    private InputModel Input { get; set; } = new InputModel();    private string errorMessage = string.Empty;    private async Task HandleValidSubmit()    {        try        {            var claims = new List<Claim>{new Claim(ClaimTypes.Name, Input.UserName),new Claim(ClaimTypes.Role, "Admin")};            var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);            var principal = new ClaimsPrincipal(identity);            var authProperties = new AuthenticationProperties            {                IsPersistent = Input.RememberMe,                ExpiresUtc = DateTimeOffset.UtcNow.Add(            Input.RememberMe ? TimeSpan.FromDays(30) : TimeSpan.FromMinutes(30)),                AllowRefresh = true            };            await HttpContext.SignInAsync(            CookieAuthenticationDefaults.AuthenticationScheme,            principal,            authProperties);            Navigation.NavigateTo("/", true);        }        catch (Exception ex)        {            errorMessage = "Login failed: " + ex.Message;        }    }    private class InputModel    {        [Required(ErrorMessage = "UserName cannot be empty")]        [StringLength(20, ErrorMessage = "1-20 length")]        public string UserName { get; set; } = string.Empty;        [Required(ErrorMessage = "Password cannot be empty")]        [DataType(DataType.Password)]        [StringLength(20, MinimumLength = 1, ErrorMessage = "1-20 length")]        public string Password { get; set; } = string.Empty;        public bool RememberMe { get; set; } = false;    }}

As you can see, I am using MudTextField to bind a login user model. However, it took me so long to understand that MudTexField's bind-value only functioning under InteractiveServer mode. However, you can see I need HttpContext to set cookies once login, and HttpContext is unavailable under static mode. This is such a dilemma and have no idea to work out. Is there a solution to simultaneously keep Mudblazor style and using HttpContext to set cookies?

BTW, below is my Program.cs, currently it is set to Server mode and per page/compnent:

using MudBlazor.Services;using Microsoft.EntityFrameworkCore;using FileGrid.Components;using Minio;using Microsoft.AspNetCore.Components.Authorization;using Microsoft.AspNetCore.Components.Server;using Microsoft.AspNetCore.Authentication.Cookies;var builder = WebApplication.CreateBuilder(args);// Add db contextbuilder.Services.AddDbContext<FileGrid.Entities.FileGridContext>(options =>    options.UseSqlServer(builder.Configuration.GetConnectionString("FileGrid")));// Add Controllersbuilder.Services.AddControllers();// Add MudBlazor servicesbuilder.Services.AddMudServices();// Add services to the container.builder.Services.AddRazorComponents()    .AddInteractiveServerComponents();// Add HttpClient servicebuilder.Services.AddHttpClient("FileGridHTTPClient",    client => client.BaseAddress = new Uri(builder.Configuration["HTTPClientBaseUri"] ?? "http://localhost:5039/"))    .ConfigurePrimaryHttpMessageHandler(() =>    {        var handler = new HttpClientHandler();        handler.UseCookies = true;        handler.CookieContainer = new System.Net.CookieContainer();        return handler;    });// Add services to Authbuilder.Services.AddCascadingAuthenticationState();builder.Services.AddAuthorization();builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme,                options =>                {                    options.Cookie.HttpOnly = true;                    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;                    options.LoginPath = "/login";                    options.ExpireTimeSpan = TimeSpan.FromDays(7);                    options.SlidingExpiration = true;                });// builder.Services.Configure<CookiePolicyOptions>(options =>//             {//                 options.ConsentCookie.IsEssential = true;//                 // This lambda determines whether user consent for non-essential cookies is needed for a given request.//                 options.CheckConsentNeeded = context => false;//             });// Add Minio client as singleton servicebuilder.Services.AddSingleton(new MinioClient()    .WithEndpoint("localhost:9000")    .WithCredentials("minioadmin", "minioadmin")    .Build());// 添加在其他服务注册之后builder.Services.AddScoped<AuthenticationStateProvider, ServerAuthenticationStateProvider>();var app = builder.Build();// Configure the HTTP request pipeline.if (!app.Environment.IsDevelopment()){    app.UseExceptionHandler("/Error", createScopeForErrors: true);    // 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.UseAuthentication();app.UseAuthorization();app.UseAntiforgery();app.MapStaticAssets();app.MapControllers();app.MapRazorComponents<App>()    .AddInteractiveServerRenderMode();app.Run();

And App.razor:

<!DOCTYPE html><html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><base href="/" /><link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" /><link href=@Assets["_content/MudBlazor/MudBlazor.min.css"] rel="stylesheet" /><ImportMap /><link rel="icon" type="image/ico" href="favicon.ico" /><HeadOutlet /></head><body><Routes /><script src="_framework/blazor.web.js"></script><script src=@Assets["_content/MudBlazor/MudBlazor.min.js"]></script></body></html>

For the code above,

  1. I can't trigger remember me check box, seems it can't bind to login model properly.
  2. When login button is clicked, errors are like:
An unhandled exception occurred while processing the request.InvalidOperationException: EditForm requires either a Model parameter, or an EditContext parameter, please provide one of these.Microsoft.AspNetCore.Components.Forms.EditForm.OnParametersSet()Microsoft.AspNetCore.Components.Forms.EditForm.OnParametersSet()Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync()Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()Microsoft.AspNetCore.Components.RenderTree.Renderer.HandleExceptionViaErrorBoundary(Exception error, ComponentState errorSourceOrNull)Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToPendingTasksWithErrorHandling(Task task, ComponentState owningComponentState)Microsoft.AspNetCore.Components.Rendering.ComponentState.SupplyCombinedParameters(ParameterView directAndCascadingParameters)Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters)Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(ref DiffContext diffContext, int frameIndex)Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(ref DiffContext diffContext, int frameIndex)Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(ref DiffContext diffContext, int newFrameIndex)Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(ref DiffContext diffContext, int oldStartIndex, int oldEndIndexExcl, int newStartIndex, int newEndIndexExcl)Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer renderer, RenderBatchBuilder batchBuilder, int componentId, ArrayRange<RenderTreeFrame> oldTree, ArrayRange<RenderTreeFrame> newTree)Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder batchBuilder, RenderFragment renderFragment, out Exception renderFragmentException)Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry renderQueueEntry)Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessPendingRender()Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToRenderQueue(int componentId, RenderFragment renderFragment)Microsoft.AspNetCore.Components.RenderHandle.Render(RenderFragment renderFragment)Microsoft.AspNetCore.Components.ComponentBase.StateHasChanged()Microsoft.AspNetCore.Components.ComponentBase.CallOnParametersSetAsync()Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync()Microsoft.AspNetCore.Components.RenderTree.Renderer.HandleExceptionViaErrorBoundary(Exception error, ComponentState errorSourceOrNull)Microsoft.AspNetCore.Components.RenderTree.Renderer.AddToPendingTasksWithErrorHandling(Task task, ComponentState owningComponentState)Microsoft.AspNetCore.Components.Rendering.ComponentState.SupplyCombinedParameters(ParameterView directAndCascadingParameters)Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView parameters)Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderRootComponentAsync(int componentId, ParameterView initialParameters)Microsoft.AspNetCore.Components.HtmlRendering.Infrastructure.StaticHtmlRenderer.BeginRenderingComponent(IComponent component, ParameterView initialParameters)Microsoft.AspNetCore.Components.Endpoints.EndpointHtmlRenderer.RenderEndpointComponent(HttpContext httpContext, Type rootComponentType, ParameterView parameters, bool waitForQuiescence)System.Runtime.CompilerServices.ValueTaskAwaiter<TResult>.GetResult()Microsoft.AspNetCore.Components.Endpoints.RazorComponentEndpointInvoker.RenderComponentCore(HttpContext context)Microsoft.AspNetCore.Components.Endpoints.RazorComponentEndpointInvoker.RenderComponentCore(HttpContext context)Microsoft.AspNetCore.Components.Rendering.RendererSynchronizationContext+<>c+<<InvokeAsync>b__10_0>d.MoveNext()Microsoft.AspNetCore.Builder.ServerRazorComponentsEndpointConventionBuilderExtensions+<>c__DisplayClass1_1+<<AddInteractiveServerRenderMode>b__1>d.MoveNext()Microsoft.AspNetCore.Antiforgery.Internal.AntiforgeryMiddleware.InvokeAwaited(HttpContext context)Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

This error is due to MudTextField's binding malfunction.So I add @rendermode @(RenderMode.InteractiveServer) to Login.razor, and now it binding well, however, leads to Null reference to HttpContext.So this is it, anyone can help with my hair?




I finally figured out how to bind login user mode properly, simple add a name attribute to MudTextField. Like this:

<MudTextField @bind-Value="@Input.UserName" name="Input.UserName" />

But another question remains: the checkbox refused to toggle, ie, I can't toggle the value of RememberMe.


Viewing all articles
Browse latest Browse all 4839

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>