Search code examples
c#asp.net-core.net-corefile-uploadimage-upload

Why I get Null value from view to controller only for one column?


I am practice CRUD operation in ASP.NET Core 6 MVC. I try to upload single image method. The image is upload on create method. But when I try to use edit method without change in image. It give null value on Edit post method.

I make image column as string and save only the random name generated by AJAX url via javascript. On time on Create, Image upload + javascript run and get random name + save in database. But when I try to edit method, without upload new image it save as Null (the image show on edit page.)

Code for controller Edit post method:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, CustomerMaster customerMaster, IFormCollection formData)
{
    if (ModelState.IsValid)
    {
        try
        {
            if (!_context.CustomerMasters.Any(x => x.MobileNo == customerMaster.MobileNo && x.CustomerId != id))
            {
                CustomerMaster customer = await _context.CustomerMasters.FindAsync(id);
                customer.CustomerName = customerMaster.CustomerName;
                customer.MobileNo = customerMaster.MobileNo;
                customer.Email = customerMaster.Email;
                customer.Address = customerMaster.Address;
                customer.Image = customerMaster.Image;
                customer.WhenEntered = DateTime.UtcNow;

                _context.Update(customer);
                await _context.SaveChangesAsync();

                return RedirectToAction(nameof(Index));
            }
            else
            {
                ModelState.AddModelError("", "Name with same mobile no. already exists.");
            }
        }

        return RedirectToAction(nameof(Index));
    }

    return View(customerMaster);
}

Here is my edit.cshtml :

''''

@model Customer_Crud_Demo.Models.CustomerMaster

@using Customer_Crud_Demo.Common

@{
    ViewData["Title"] = "Edit";
    string imagePath = string.IsNullOrEmpty(Model.Image) ? "https://via.placeholder.com/200x200" : Config.customerImagePath + Model.Image.Replace(".", ".");
}

In config

customerImagePath = "/Content/MultiCustomerImg/"

edit.cshtml inside form

<form asp-action="Edit" enctype="multipart/form-data">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <input type="hidden" asp-for="CustomerId" />
        <label asp-for="Image" class="control-label"></label>

        <table>
            <tr>
                <td>
                    <input type="file" asp-for="Image" id="fuCustomerImage" class="fu form-control" accept=".jpg,.jpeg,.png" />
                </td>
                <td>
  <input type="button" value="Upload" id="btnUploadImage" class="btn btn-primary" data-URL="CustomerMaster/UploadFile" data-path="/Content/CustomerImages" />
                </td>
            </tr>
            <tr>
                <td>
                    <span asp-validation-for="Image" class="text-danger"></span>
                </td>
            </tr>
            <tr>
                <td class="error" colspan="2">
                    Please upload image of 200 X 200 and size less than 150KB.
                </td>
            </tr>
        </table>
                        
        <div class="singleImage">
            <img src="@imagePath" alt="Alternate Text" id="ImgUploadedImage" height="200" width="200" />
            @Html.HiddenFor(model => model.Image, new { id = "image" })
        </div>
</form>

What is my mistake? Please correct me.


Solution

  • In your Edit.cshtml, You have two input tag with same Name:

    1.

    <input type="file" asp-for="Image" id="fuCustomerImage" class="fu form-control" accept=".jpg,.jpeg,.png" />
    

    2.

    @Html.HiddenFor(model => model.Image, new { id = "image" })
    

    They will all generate code like <input Name="Image" ..../> in HTML.

    ModelBinding will just bind the value of the first Input, This is why you will get null even you don't change any in Image. You can refer to this code:

    Edit.cshtml

    <input type="file" Name="file" id="fuCustomerImage" class="fu form-control" accept=".jpg,.jpeg,.png" />
    

    Edit Method

    [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, CustomerMaster customerMaster, IFormFile file)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    if (!_context.CustomerMasters.Any(x => x.MobileNo == customerMaster.MobileNo && x.CustomerId != id))
                    {
                        CustomerMaster customer = await _context.CustomerMasters.FindAsync(id);
                            customer.CustomerName = customerMaster.CustomerName;
                            customer.MobileNo = customerMaster.MobileNo;
                            customer.Email = customerMaster.Email;
                            customer.Address = customerMaster.Address;
    
                        if (file != null)
                        {
                            //I don't how you save file as string in database, Here i just save file name as an example
                            customer.Image = file.FileName
                        }
                        else
                        {
                            customer.Image = customerMaster.Image;
                        }
                            
                            customer.WhenEntered = DateTime.UtcNow;
    
                            _context.Update(customer);
                            await _context.SaveChangesAsync();
                        
                    }
                    else
                    {
                        ModelState.AddModelError("", "Name with same mobile no. already exists.");
                    }
                }
    
    
            return RedirectToAction(nameof(Index));
            }
    
            return View(customerMaster);
        }