I am working on a project where I have to update a record in which a user can also upload a picture using IFormFile everything is working fine except the IFormFile propery which always give me null on submitting the form I am sharing the code of the whole page please help me to find the issue.
@page "/Admin/UpdatePage/{Id:int}"
@using JobListingSite.Data
@using JobListingSite.Models
@inject AppDbContext db
@inject IWebHostEnvironment env
@layout AdminLayout
<div class="row justify-content-center">
<div class="col-8">
<h3>Create Job</h3>
</div>
<div class="col-8 d-flex justify-content-center">
<EditForm class="row g-3" method="Post" enctype="multipart/form-data" Enhance="true" Model="Job" FormName="UpdateJobForm" OnValidSubmit="Update">
<DataAnnotationsValidator/>
<div class="col-6">
<label class="form-label">Job Title:</label>
<InputText class="form-control" @bind-Value="Job.Name"></InputText>
<InputNumber hidden class="form-control" @bind-Value="Job.Id"></InputNumber>
<ValidationMessage For="@(()=>Job.Name)" class="text-danger"/>
</div>
<div class="col-6">
<label class="form-label">Category:</label>
<InputSelect class="form-select" @bind-Value="Job.Nature">
<option value="">Select job Category</option>
@foreach (var item in Category)
{
<option value="@item.Name">@item.Name</option>
}
</InputSelect>
</div>
<div class="col-6">
<label class="form-label">Salary:</label>
<InputText class="form-control" @bind-Value="Job.salary"></InputText>
<ValidationMessage For="@(()=>Job.salary)" class="text-danger"/>
</div>
<div class="col-6">
<label class="form-label">Last Date to Apply:</label>
<InputText class="form-control" @bind-Value="Job.LastDateToApply"></InputText>
<ValidationMessage For="@(()=>Job.LastDateToApply)" class="text-danger"/>
</div>
<div class="col-12">
<label class="form-label">Upload Photo:</label>
<InputFile class="form-control" name="Job.Photo"/>
</div>
<div class="col-12">
<button class="btn btn-success mt-3" type="submit">Update Job</button>
</div>
</EditForm>
</div>
</div>
@code {
[SupplyParameterFromForm] public Job Job { get; set; } = new();
[Parameter]
public int Id { get; set; }
public IEnumerable<Category> Category { get; set; }
protected override void OnInitialized()
{
Job = db.tbl_Job.Find(Id);
Category = db.tbl_Category;
base.OnInitialized();
}
private void Update()
{
if (Job.Photo == null)
{
db.tbl_Job.Update(Job);
db.SaveChanges();
}
else
{
string ImageName = Job.Photo.FileName;
string OldPhotoName = Job.Image;
var FolderPath = Path.Combine(env.WebRootPath, "images");
var ImagePath = Path.Combine(FolderPath, ImageName);
var myFileStream = new FileStream(ImagePath, FileMode.Create);
Job.Photo.CopyTo(myFileStream);
Job.Image = ImageName;
db.tbl_Job.Update(Job);
db.SaveChanges();
}
}
}
Tried different rendering modes and different available solutions on Stack Overflow but nothing is fixing the issue.
I am working on a project where I have to update a record in which a user can also upload a picture using IFormFile everything is working fine except the IFormFile propery which always give me null on submitting the form
I think you can receive the other properties value but you also can not get the updated value of these properties if you keep the default render mode.
That is because .NET 8 blazor razor component is Static server-side rendering (static SSR) by default which cannot send the changed value if they are set with initialized value.
For the input file value, you could add a OnChange
event to set the value. To handle file uploads correctly in Blazor, you need to work with the IBrowserFile
type directly, rather than trying to convert it to an IFormFile
.
Here is a whole working demo:
@page "/Admin/UpdatePage/{Id:int}"
@using JobListingSite.Data
@using JobListingSite.Models
@inject AppDbContext db
@inject IWebHostEnvironment env
@layout AdminLayout
@rendermode InteractiveServer //add this rendermode....
<div class="row justify-content-center">
<div class="col-8">
<h3>Create Job</h3>
</div>
<div class="col-8 d-flex justify-content-center">
<EditForm class="row g-3" method="Post" enctype="multipart/form-data" Model="Job" FormName="UpdateJobForm" OnValidSubmit="Update">
<div class="col-6">
<label class="form-label">Job Title:</label>
<InputText class="form-control" @bind-Value="Job.Name"></InputText>
<InputNumber hidden class="form-control" @bind-Value="Job.Id"></InputNumber>
<ValidationMessage For="@(()=>Job.Name)" class="text-danger" />
</div>
<!--other properties-->
<div class="col-12">
<label class="form-label">Upload Photo:</label>
<InputFile class="form-control" OnChange="HandleFileSelected" />
</div>
<div class="col-12">
<button class="btn btn-success mt-3" type="submit">Update Job</button>
</div>
</EditForm>
</div>
</div>
@code {
// [SupplyParameterFromForm]
public Job Job { get; set; } = new();
[Parameter]
public int Id { get; set; }
public IEnumerable<Category> Category { get; set; }
protected override void OnInitialized()
{
Job = db.tbl_Job.Find(Id);
Category = db.tbl_Category;
base.OnInitialized();
}
private void HandleFileSelected(InputFileChangeEventArgs e)
{
var file = e.File;
if (file != null)
{
// Store the file in Job.Photo
Job.Photo = file;
}
}
private async Task Update()
{
if (Job.Photo == null)
{
db.tbl_Job.Update(Job);
db.SaveChanges();
}
else
{
string imageName = Job.Photo.Name;
var folderPath = Path.Combine(env.WebRootPath, "images");
var imagePath = Path.Combine(folderPath, imageName);
using (var fileStream = new FileStream(imagePath, FileMode.Create))
{
await Job.Photo.OpenReadStream().CopyToAsync(fileStream);
}
Job.Image = imageName;
db.tbl_Job.Update(Job);
db.SaveChanges();
}
}
}
Model
public class Job
{
public int Id { get; set; }
public string Name { get; set; }
public string Image { get; set; }
//other properties...
public IBrowserFile Photo { get; set; }
}