Search code examples
c#razorasp.net-core-mvcasp.net-core-5.0

How to upload an image with ASP.NET Core 5.0 MVC


I want to upload an image in a post method for edit a record,this is the form that send the data to the controller:

<form asp-action="Edit">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <input type="hidden" asp-for="IdEmpresa" />
    <div class="form-group mt-3">
        <label asp-for="CodEmpresa" class="control-label"></label>
        <input required asp-for="CodEmpresa" class="form-control" />
        <span asp-validation-for="CodEmpresa" class="text-danger"></span>
    </div>
    <div class="form-group mt-3">
        <label asp-for="Empresa" class="control-label"></label>
        <input required asp-for="Empresa" class="form-control" />
        <span asp-validation-for="Empresa" class="text-danger"></span>
    </div>
    <div class="form-group mt-3">
        <label asp-for="Contacto" class="control-label"></label>
        <input required asp-for="Contacto" class="form-control" />
        <span asp-validation-for="Contacto" class="text-danger"></span>
    </div>
    <div class="form-group mt-3">
        <label asp-for="Imagen" class="control-label"></label>
        <input asp-for="Imagen" class="form-control" type="file" />
        <span asp-validation-for="Imagen" class="text-danger"></span>
    </div>
    <br />
    <div class="form-group  d-flex justify-content-end">
        <input type="submit" value="Actualizar" class="btn btn-primary bg-primary" />
    </div>
</form>

And here it's the method that update the data but only the strings or the numbers, i don't how to handle the input of type = 'file' to copy the image to a local directory and assign the path to the string of 'Image' attribute in the model

public async Task<IActionResult> Edit(int id, [Bind("IdEmpresa,CodEmpresa,Empresa,Contacto")] MnEmpresa mnEmpresa)
{
    if (id != mnEmpresa.IdEmpresa)
    {
        return NotFound();
    }

    if (ModelState.IsValid)
    {
        try
        {
            MnEmpresa empresa = _context.MnEmpresas.Where(x => x.IdEmpresa == mnEmpresa.IdEmpresa).FirstOrDefault();
            _context.Entry(empresa).State = EntityState.Detached;
            mnEmpresa.Imagen = empresa.Imagen;
            _context.Update(mnEmpresa);
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!MnEmpresaExists(mnEmpresa.IdEmpresa))
            {
                return NotFound();
            }
            else
            {
                throw;
            }
        }

        return RedirectToAction(nameof(Index));
    }

    return View(mnEmpresa);
}

Here is my model:

public MnEmpresa()
{
    MnAplicactivos = new HashSet<MnAplicactivo>();
    MnUsuarios = new HashSet<MnUsuario>();
}

public int IdEmpresa { get; set; }
public int? CodEmpresa { get; set; }
public string Empresa { get; set; }
public string Contacto { get; set; }

public string Imagen { get; set; }

public virtual ICollection<MnAplicactivo> MnAplicactivos { get; set; }
public virtual ICollection<MnUsuario> MnUsuarios { get; set; }

Solution

  • To upload a file use enctype="multipart/form-data" attribute in the form tag. The enctype attribute can be used only if method="post".

    <form asp-action="Edit" method="post" enctype="multipart/form-data">
        ....
        <input type="file" name="postedFile" id="postedFile" multiple />
    
        <div class="form-group  d-flex justify-content-end">
            <input type="submit" value="Actualizar" class="btn btn-primary bg-primary" />
        </div>
    <form>
    

    In the the controller:

    public class YourController : Controller
    {
        private readonly ILogger<HomeController> _logger;
        private readonly IWebHostEnvironment _web;
    
        public YourController(IWebHostEnvironment env, ILogger<HomeController> logger)
        {
            _web = env;
            _logger = logger;
        }
    
        ....
    
        [HttpPost]
        public async Task<IActionResult> Edit(int id, [Bind("IdEmpresa,CodEmpresa,Empresa,Contacto")] MnEmpresa mnEmpresa, IFormFile postedFile)
        { 
            if (id != mnEmpresa.IdEmpresa)
            {
                return NotFound();
            }
        
            if (ModelState.IsValid)
            {         
                string wwwPath = _web.WebRootPath;
                string contentPath = _web.ContentRootPath;
        
                string path = Path.Combine(_web.WebRootPath, "Uploads");
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }          
        
                if (postedFile != null)
                {         
                    var target = Path.Combine(path, fileName);     
                    string fileName = Path.GetFileName(postedFile.FileName);
                    using (FileStream stream = new FileStream(target, fileName), FileMode.Create))
                    {                
                        postedFile.CopyTo(stream);
                    }
        
                    #region Your previous code
                    try
                    {
                        MnEmpresa empresa = _context.MnEmpresas.Where(x => x.IdEmpresa == mnEmpresa.IdEmpresa).FirstOrDefault();
                        _context.Entry(empresa).State = EntityState.Detached;
                        mnEmpresa.Imagen = target;
                        _context.Update(mnEmpresa);
                        await _context.SaveChangesAsync();
                    }
                    catch (DbUpdateConcurrencyException)
                    {
                        if (!MnEmpresaExists(mnEmpresa.IdEmpresa))
                        {
                            return NotFound();
                        }
                        else
                        {
                            throw;
                        }
                    }    
                    return RedirectToAction(nameof(Index));
                    #endregion
                }
                return View();
            }
            return View(mnEmpresa);    
        }
    }