I have a Blazor Webassembly Project that works fine on iisexpress (visual studio 2019). But when I deploy it on IIS, I can't see the login page due to this errors:
crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: The provided expression contains a PropertyExpression which is not supported. FieldIdentifier only supports simple member accessors (fields, properties) of an object. System.ArgumentException: The provided expression contains a PropertyExpression which is not supported. FieldIdentifier only supports simple member accessors (fields, properties) of an object. at Microsoft.AspNetCore.Components.Forms.FieldIdentifier.ParseAccessor[String](Expression
1 , Object& , String& ) at Microsoft.AspNetCore.Components.Forms.FieldIdentifier.Create[String](Expression
1 ) at Microsoft.AspNetCore.Components.Forms.InputBase1[[System.String, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].SetParametersAsync(ParameterView ) at Microsoft.AspNetCore.Components.Rendering.ComponentState.SetDirectParameters(ParameterView ) at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewComponentFrame(DiffContext& , Int32 ) at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InitializeNewSubtree(DiffContext& , Int32 ) at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& , Int32 ) at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.InsertNewFrame(DiffContext& , Int32 ) at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.AppendDiffEntriesForRange(DiffContext& , Int32 , Int32 , Int32 , Int32 ) at Microsoft.AspNetCore.Components.RenderTree.RenderTreeDiffBuilder.ComputeDiff(Renderer , RenderBatchBuilder , Int32 , ArrayRange
1 , ArrayRange`1 ) at Microsoft.AspNetCore.Components.Rendering.ComponentState.RenderIntoBatch(RenderBatchBuilder , RenderFragment ) at Microsoft.AspNetCore.Components.RenderTree.Renderer.RenderInExistingBatch(RenderQueueEntry ) at Microsoft.AspNetCore.Components.RenderTree.Renderer.ProcessRenderQueue()crit: Microsoft.AspNetCore.Components.WebAssembly.Rendering.WebAssemblyRenderer[100] Unhandled exception rendering component: No element is currently associated with component 13 Error: No element is currently associated with component 13 at e.updateComponent (https://localhost/_framework/blazor.webassembly.js:1:31703) at t.renderBatch (https://localhost/_framework/blazor.webassembly.js:1:12134) at window.Blazor._internal.renderBatch (https://localhost/_framework/blazor.webassembly.js:1:61913) at Object.w [as invokeJSFromDotNet] (https://localhost/_framework/blazor.webassembly.js:1:64435) at _mono_wasm_invoke_js_blazor (https://localhost/_framework/dotnet.5.0.12.js:1:190800) at wasm_invoke_iiiiii (wasm://wasm/00aba242:wasm-function[5611]:0xdda7f) at ves_pinvoke_method (wasm://wasm/00aba242:wasm-function[5708]:0xdfb62) at interp_exec_method (wasm://wasm/00aba242:wasm-function[2155]:0x44c08) at interp_runtime_invoke (wasm://wasm/00aba242:wasm-function[7862]:0x12efff) at mono_jit_runtime_invoke (wasm://wasm/00aba242:wasm-function[7347]:0x118e5f)
. when I replace the EditForm with pure HTML inputs, everything is OK! here is my EditForm:
<EditForm Model="request" OnValidSubmit="OnValid" style="max-width:500px;">
<DataAnnotationsValidator />
<ValidationSummary />
<div >
<InputText @bind-Value="request.Username" placeholder="نام کاربری"></InputText>
<div >
<span ></span>
</div>
</div>
<div >
<InputText type="password" @bind-Value="request.Password" placeholder="رمز عبور"></InputText>
<div >
<span ></span>
</div>
</div>
<div >
<!-- /.col -->
<div >
<button disabled="@isDisabled">ورود</button>
</div>
<div >
<img src="dist/img/allin-logo.png" width="140" height="100" />
</div>
<!-- /.col -->
</div>
</EditForm>
and here is the code behind:
[Inject]
public IAccountService accountService { get; set; }
[Inject]
public NavigationManager navigationManager { get; set; }
public AuthenticationRequest request { get; set; }
private string message { get; set; }
private bool isDisabled { get; set; }
public Login()
{
request = new AuthenticationRequest();
message = string.Empty;
isDisabled = false;
}
private async void OnValid()
{
isDisabled = true;
var result = await accountService.LoginAsync(request);
if (result)
{
navigationManager.NavigateTo("/");
}
else
{
isDisabled = false;
message = "نام کاربری یا رمز عبور اشتباه است";
}
}
what should I do?!
Update: changing void OnValid() to Task OnValid() didn't solve the problem.
CodePudding user response:
Blazor Webassembly runs completely on the browser. The server version or edition plays no role at all. There's nothing wrong with either IIS or IIS Express.
The bug is using async void
instead of async Task
. Methods with the async void
signature can't be awaited.
To fix it, change async void OnValid
to async Task OnValid
or even better, async Task OnValidAsync
:
<EditForm Model="request" OnValidSubmit="OnValid" style="max-width:500px;">
</EditForm>
@code {
private async Task OnValidAsync()
{
isDisabled = true;
var result = await accountService.LoginAsync(request);
...
}
}
The async void
signature is only meant for asynchronous event handlers in desktop applications (WinForms, WPF). These frameworks were created before Task
was introduced and don't know how to await asynchronous methods.
Asynchronous methods that return no results should use the async Task
signature. Methods that return a value use async Task<T>
.
Blazor on the other hand was built with asynchronous operations baked in. All Blazor examples use async Task
instead. For example :
@page "/set-params-async/{Param?}"
<p>@message</p>
@code {
private string message = "Not set";
[Parameter]
public string? Param { get; set; }
public override async Task SetParametersAsync(ParameterView parameters)
{
if (parameters.TryGetValue<string>(nameof(Param), out var value))
{
if (value is null)
{
message = "The value of 'Param' is null.";
}
else
{
message = $"The value of 'Param' is {value}.";
}
}
await base.SetParametersAsync(parameters);
}
}
CodePudding user response:
There was a mismatch between sdk versions. project was built with .net 5.0 but .net runtime was .net 6.0.1 . By uninstalling .net 6, everything works fine! Thank you for your helps!
CodePudding user response:
Change this:
<div >
<button
disabled="@isDisabled">ورود</button>
</div>
To:
<div >
<button type="submit"
disabled="@isDisabled">ورود</button>
</div>
You can't control the value of the isDisabled
field from the OnValid
method as the "Submit" button is disabled. In other words, clicking on the "Submit" button does not trigger the call back OnValid
Here's how you can do that:
<EditForm EditContext="@EditContext" OnValidSubmit="OnValid" style="max-width:500px;">
</EditForm>
@code
{
private EditContext EditContext;
private AuthenticationRequest request = new AuthenticationRequest();
protected string Disabled { get; set; } = "disabled";
protected override void OnInitialized()
{
EditContext = new EditContext(request);
EditContext.OnFieldChanged = EditContext_OnFieldChanged;
}
// Note: The OnFieldChanged event is raised for each field in the model
private void EditContext_OnFieldChanged(object sender,
FieldChangedEventArgs e)
{
SetSaveDisabledStatus(e);
}
private void SetSaveDisabledStatus(FieldChangedEventArgs e)
{
// Each time a field changes this code is executed.
// EditContext.Validate() returns true if
// validation succeeded; that is, both fields pass validation, in
// which case we assign the value null
// to the property Disabled, and thus enabling the Submit button.
if (EditContext.Validate())
{
Disabled = null;
}
else
{
Disabled = "disabled";
}
}
private async TaskOnValid()
{
var result = await accountService.LoginAsync(request);
if (result)
{
navigationManager.NavigateTo("/");
}
else
{
Disabled = "disabled";
message = "نام کاربری یا رمز عبور اشتباه است";
}
}
}
Pay attention to Disabled (instead of the boolean isDisabled you're using)