This is my code:
From what I can see, I am creating a new instance of the class, binding each attribute to the class in the form, then converting to JSON and printing. What am I missing?
@inject IIdentityService IdentityService;
@inject ErrorService ErrorService;
<div class=" w-full flex justify-center text-main ">
<div class="flex w-full">
<div class="w-1/2 flex">
<div class="w-full h-[100vh] bg-cover bg-center"
style="background-image: url('./images/identity/login.jpg')">
</div>
</div>
<div class="bg-white p-8 w-1/2 rounded-lg pt-[10%] px-[5%]">
<EditForm Model="RegisterModel" OnValidSubmit="HandleValidSubmit" FormName="RegisterForm">
<DataAnnotationsValidator/>
<ValidationSummary/>
<!-- First Name and Last Name -->
<div class="mb-4 flex justify-between">
<InputText
@bind-Value="FirstName"
placeholder="First Name"
class="form-control mt-1 block w-[48%] px-6 py-4 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
required/>
<ValidationMessage For="@(() => FirstName)"/>
<InputText
@bind-Value="LastName"
placeholder="Last Name"
class="form-control mt-1 block w-[48%] px-6 py-4 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
required/>
<ValidationMessage For="@(() => LastName)"/>
</div>
<!-- Phone Number -->
<div class="mb-4">
<InputText
@bind-Value="RegisterModel.PhoneNumber"
placeholder="Phone Number"
class="form-control mt-1 block w-full px-6 py-4 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
required/>
<ValidationMessage For="@(() => RegisterModel.PhoneNumber)"/>
</div>
<!-- Email -->
<div class="mb-4">
<InputText
@bind-Value="RegisterModel.Email"
type="email"
placeholder="Email"
class="form-control mt-1 block w-full px-6 py-4 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
required/>
<ValidationMessage For="@(() => RegisterModel.Email)"/>
</div>
<!-- Password -->
<div class="mb-4">
<InputText
@bind-Value="RegisterModel.Password"
type="password"
placeholder="Password"
class="form-control mt-1 block w-full px-6 py-4 border border-gray-300 rounded-md shadow-sm focus:ring-blue-500 focus:border-blue-500 sm:text-sm"
required/>
<ValidationMessage For="@(() => RegisterModel.Password)"/>
</div>
<!-- Register Button -->
<div>
<button type="submit"
class="w-full inline-flex justify-center py-2 px-4 border border-transparent shadow-sm font-medium rounded-sm text-white bg-[#00205c] focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 text-xl transition-all ease-out">
Register
</button>
</div>
</EditForm>
<div class="w-full flex justify-between mt-3 ">
<button class="hover:underline" type="button">
<NavLink href="/login">
Already Have An Account?
</NavLink>
</button>
<button class="hover:underline " type="submit">
<a href="">
Forgot Password?
</a>
</button>
</div>
</div>
</div>
</div>
@code {
[SupplyParameterFromForm(FormName = "RegisterForm")]
private RegisterFormModel RegisterModel { get; set; } = RegisterFormModel.Empty;
private string FirstName { get; set; } = string.Empty;
private string LastName { get; set; } = string.Empty;
private async Task HandleValidSubmit()
{
RegisterModel.Username = $"{FirstName} {LastName}";
var result = await IdentityService.Register(RegisterModel);
if (result.IsFailure)
{
ErrorService.SetErrorMessage(result.ErrorTypes);
}
}
The Problem is when i bind the form value to the p tag, it still display my input value, but when i send the submit, it become null or i should say default value.
I also check it in the server and try to change the default value of the DTOs in the backend, so i can know when i send, the bind value in my blazor form is empty or null.
What can i do? the @rendermode dont work in blazor wasm or i just missing something
Edit: my problem also happen with all of property not only firstname/lastname
Edit2: My service
public class IdentityService(
IHttpClientFactory factory,
string baseUrl = nameof(IdentityService),
string endpoint = "api/User"
) : BaseApiService(factory, baseUrl, endpoint), IIdentityService
{
public async Task<Result> Register(RegisterFormModel registerModel)
{
var content = SerializeItem(registerModel);
var result = await Client.PostAsJsonAsync($"{Endpoint}/Register", content);
return await HandleResponse(result);
}
public async Task<Result<LoginResponse>> Login(LoginFormModel loginModel)
{
var content = SerializeItem(loginModel);
var result = await Client.PostAsJsonAsync($"{Endpoint}/Login", content);
return await HandleResponse<LoginResponse>(result);
}
}
protected static StringContent SerializeItem<TItem>(TItem item)
where TItem : class
{
return new StringContent(JsonSerializer.Serialize(item), Encoding.UTF8, "application/json");
}
My model:
public class RegisterFormModel
{
public string? Email { get; set; }
public string? Username { get; set; }
public string? Password { get; set; }
public string? PhoneNumber { get; set; }
public static RegisterFormModel Empty =>
new()
{
Email = default,
Username = default,
Password = default,
PhoneNumber = default,
};
}
This issue is more likely happened in SSR. In SSR the input field has to be in the editform model.
public class RegisterFormModel
{
public string? FirstName { get; set; }
public string? LastName { get; set; }
...
var content = SerializeItem(registerModel);
var result = await Client.PostAsync($"{Endpoint}/Register", content);
<InputText @bind-Value="RegisterModel.FirstName" ...
...
<InputText @bind-Value="RegisterModel.LastName" ...
And need use following pattern to initilize the model
[SupplyParameterFromForm(FormName = "RegisterForm")]
private RegisterFormModel RegisterModel { get; set; }
protected override void OnInitialized() => RegisterModel ??= new RegisterFormModel();
-------------------update--------------------
Inside this page, add a testValue to check if the Value dispaly changed correctly.
@testValue
@code {
private string testValue { get; set; } = "test";
...
private async Task HandleValidSubmit()
{
testValue = FirstName + RegisterModel.PhoneNumber;
------------------------update2----------------------
The PostAsJsonAsync method doesn't match the [FromForm]
attribute which accept MultipartFormDataContent
. There are 2 ways to do this post.
[FromForm]
public async Task<IActionResult> Register(Register.Commond commond)
then use PostAsync
instead.
var content = SerializeItem(registerModel);
var result = await Client.PostAsync($"{Endpoint}/Register", content);
FromForm
(in case you cannot change the api) var content = new MultipartFormDataContent();
var stringContent = new StringContent(registerModel.Username, Encoding.UTF8);
content.Add(stringContent, "UserName");
stringContent = new StringContent(registerModel.Email, Encoding.UTF8);
content.Add(stringContent, "Email");
stringContent = new StringContent(registerModel.PhoneNumber, Encoding.UTF8);
content.Add(stringContent, "PhoneNumber");
stringContent = new StringContent(registerModel.Password, Encoding.UTF8);
content.Add(stringContent, "Password");
var result = await client.PostAsync($"{Endpoint}/Register", content);