Home > Software engineering >  Image Upload function in CRUD
Image Upload function in CRUD

Time:09-30

I want to complete the Image Upload functionality in CRUD including Create, Details, Edit, Delete, and Index. I don't know how to add Image Upload along with lines of code in CombineStagesController. I hope everyone can help me. Picture is my Image Upload Model

Below is my code.

CombineStage Model

public class CombineStage
{
    [Key]
    [ForeignKey("StageId")]
    public int StageId { get; set; }
    [Required(ErrorMessage = "Bạn chưa nhập tên công đoạn")]
    public string Name { get; set; }
    [Required(ErrorMessage = "Bạn chưa chọn công đoạn")]
    [ForeignKey("PricelistId")]
    public int PricelistId { get; set; }
    [Required(ErrorMessage = "Bạn chưa chọn ảnh")]
    public string Picture { get; set; }
    [Required(ErrorMessage = "Bạn chưa nhập giá tiền")]
    public int Price { get; set; }
    public string PricelistIdList { get; set; }
    public virtual PriceList PriceList { get; set; }
}

CombineStagesController

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using WebApp.Models;

namespace WebApp.Areas.Admin.Controllers
{
[Area("Admin")]
public class CombineStagesController : Controller
{
    private readonly ManageContext _context;

    public CombineStagesController(ManageContext context)
    {
        _context = context;
    }

    // GET: Admin/CombineStages
    public async Task<IActionResult> Index()
    {
        var manageContext = _context.CombineStage.Include(c => c.PriceList);
        return View(await manageContext.ToListAsync());
    }

    // GET: Admin/CombineStages/Details/5
    public async Task<IActionResult> Details(int? id)
    {
        if (id == null || _context.CombineStage == null)
        {
            return NotFound();
        }

        var combineStage = await _context.CombineStage
            .Include(c => c.PriceList)
            .FirstOrDefaultAsync(m => m.StageId == id);
        int[] PriceIdList = combineStage.PricelistIdList.Split(',').Select(n => Convert.ToInt32(n)).ToArray();
        List<PriceList> priceLists = new List<PriceList>();
        foreach (var PriceId in PriceIdList)
        {
            var PriceDetails = _context.PriceLists.Where(c => c.PricelistId == PriceId).FirstOrDefault();
            priceLists.Add(PriceDetails);
        }
        ViewBag.priceLists = priceLists;
        if (combineStage == null)
        {
            return NotFound();
        }

        return View(combineStage);
    }

    // GET: Admin/CombineStages/Create
    public IActionResult Create()
    {
        var priceLists = _context.PriceLists.ToList();
        List<SelectListItem> mylist = new List<SelectListItem>();
        foreach (var price in priceLists)
        {
            mylist.Add(new SelectListItem { Text = price.Stage, Value = price.PricelistId.ToString() });

        }
        ViewBag.PricelistId = mylist;
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("Name,PricelistId,Picture,Price,PriceList")] CombineStage combineStage, int[] PricelistId)
    {
        int price = 0;
        var stage = "";
        PriceList priceList = new PriceList();

        foreach (var id in PricelistId)
        {
            stage = _context.PriceLists.Where(m => m.PricelistId == id).FirstOrDefault().Stage.ToString();
            price  = _context.PriceLists.Where(m => m.PricelistId == id).FirstOrDefault().Price;
            priceList = _context.PriceLists.Where(m => m.PricelistId == id).FirstOrDefault();

        }
        combineStage.Price = price;
        combineStage.PriceList = priceList;
        combineStage.PricelistIdList = string.Join(",", PricelistId);
        ModelState.Clear();
        if (TryValidateModel(combineStage))
        {
            _context.Add(combineStage);
            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
        return View(combineStage);
    }

    // GET: Admin/CombineStages/Edit/5
    public async Task<IActionResult> Edit(int? id)
    {
        if (id == null || _context.CombineStage == null)
        {
            return NotFound();
        }

        var combineStage = await _context.CombineStage
            .Include(c => c.PriceList)
            .FirstOrDefaultAsync(m => m.StageId == id);
        int[] PriceIdList = combineStage.PricelistIdList.Split(',').Select(n => Convert.ToInt32(n)).ToArray();
        List<PriceList> priceLists = new List<PriceList>();
        foreach (var PriceId in PriceIdList)
        {
            var PriceDetails = _context.PriceLists.Where(c => c.PricelistId == PriceId).FirstOrDefault();
            priceLists.Add(PriceDetails);
        }
        ViewBag.priceLists = priceLists;

        if (combineStage == null)
        {
            return NotFound();
        }
        ViewData["PricelistId"] = new SelectList(_context.PriceLists, "PricelistId", "Stage", combineStage.PricelistId);
        return View(combineStage);
    }

    // POST: Admin/CombineStages/Edit/5
    // To protect from overposting attacks, enable the specific properties you want to bind to.
    // For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Edit(int id, [Bind("StageId,Name,PricelistId,Picture,Price")] CombineStage combineStage)
    {
        if (id != combineStage.StageId)
        {
            return NotFound();
        }

        if (ModelState.IsValid)
        {
            try
            {
                _context.Update(combineStage);
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!CombineStageExists(combineStage.StageId))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }
            return RedirectToAction(nameof(Index));
        }
        ViewData["PricelistId"] = new SelectList(_context.PriceLists, "PricelistId", "Stage", combineStage.PricelistId);
        return View(combineStage);
    }

    // GET: Admin/CombineStages/Delete/5
    public async Task<IActionResult> Delete(int? id)
    {
        if (id == null || _context.CombineStage == null)
        {
            return NotFound();
        }

        var combineStage = await _context.CombineStage
            .Include(c => c.PriceList)
            .FirstOrDefaultAsync(m => m.StageId == id);
        if (combineStage == null)
        {
            return NotFound();
        }

        return View(combineStage);
    }

    // POST: Admin/CombineStages/Delete/5
    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> DeleteConfirmed(int id)
    {
        if (_context.CombineStage == null)
        {
            return Problem("Entity set 'ManageContext.CombineStage'  is null.");
        }
        var combineStage = await _context.CombineStage.FindAsync(id);
        if (combineStage != null)
        {
            _context.CombineStage.Remove(combineStage);
        }
        
        await _context.SaveChangesAsync();
        return RedirectToAction(nameof(Index));
    }

    private bool CombineStageExists(int id)
    {
      return _context.CombineStage.Any(e => e.StageId == id);
    }
}
}

Create.cshtml

@model WebApp.Models.CombineStage

@{
ViewData["Title"] = "Create";
Layout = "~/Areas/Admin/Views/Shared/_AdminLayout.cshtml";
}

<h1>Create</h1>

<h4>CombineStage</h4>
<hr />
<div >
<div >
    <form asp-action="Create">
        <div asp-validation-summary="ModelOnly" ></div>
        <div >
            <label asp-for="Name" ></label>
            <input asp-for="Name"  />
            <span asp-validation-for="Name" ></span>
        </div>
        <div >
            <label asp-for="PricelistId" ></label>
            <select asp-for="PricelistId"  asp-items="ViewBag.PricelistId" multiple id="Subjects_dropdown">
            </select>
        </div>
        <div >
            <label asp-for="Picture" ></label>
            <input asp-for="Picture"  />
            <span asp-validation-for="Picture" ></span>
        </div>
        <div >
            <input type="submit" value="Create"  />
        </div>
    </form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>

</div>

@section Scripts {

@{
    await Html.RenderPartialAsync("_ValidationScriptsPartial");
}


<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.13/js/bootstrap-multiselect.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-multiselect/0.9.13/css/bootstrap-multiselect.css">
<script>

    $(document).ready(function () {

        $('#Subjects_dropdown').multiselect();
    });
</script>
}

Update my expectations

I want to use multiple select and image upload here.

enter image description here

enter image description here

enter image description here

Update2

I want to display it on Details Page like this

enter image description here

Edit Update3

enter image description here

CodePudding user response:

Change the type of Picture in Model from String to byte[]:

public byte[] Picture { get; set; }

Change the Create method and View:

Controller:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Name,PricelistId,Picture,Price,PriceList")] CombineStage combineStage, int[] PricelistId, IFormFile ImageFile)
{
    using (var ms = new MemoryStream())
    {
        ImageFile.CopyTo(ms);
        combineStage.Picture = ms.ToArray();
    }
    //...
    //Your other code
}

Create.cshtml (Change the Picture part to file upload):

@model _2022092602.Models.CombineStage

@{
ViewData["Title"] = "Create";
}

<h1>Create</h1>

<h4>CombineStage</h4>
<hr />
<div >
<div >
     <form asp-action="Create" enctype="multipart/form-data">
        <div asp-validation-summary="ModelOnly" ></div>
        <div >
            <label asp-for="Name" ></label>
            <input asp-for="Name"  />
            <span asp-validation-for="Name" ></span>
        </div>
        <div >
            <label asp-for="PricelistId" ></label>
            <select asp-for="PricelistId" class ="form-control" asp-items="@ViewBag.PricelistId" multiple>
                
            </select>
        </div>
        <div >
            <input type="file" name="ImageFile"  />
        </div>
        <div >
            <input type="submit" value="Create"  />
        </div>
    </form>
</div>

In this way, when you upload an image when you create it, your image will be saved in the database in the form of base64String, which is convenient for you to use on other pages.

If you want to display this image on the Index page, use this way:

<td>
      <img style="width:30px;"  src="data:image/jpg;base64,@Convert.ToBase64String(item.Picture)" />
</td>

Hope this can help you.

Edit:

Data Type in Database:

enter image description here

Update:

Controller:

public class CombineStagesController : Controller
    {
        private readonly ManageContext _context;

        public CombineStagesController(ManageContext context)
        {
            _context = context;
        }
        // GET: Admin/CombineStages/Details/5
        public async Task<IActionResult> Details(int? id)
        {
            if (id == null || _context.CombineStage == null)
            {
                return NotFound();
            }

            var combineStage = await _context.CombineStage
                .Include(c => c.PriceList)
                .FirstOrDefaultAsync(m => m.StageId == id);
            int[] PriceIdList = combineStage.PricelistIdList.Split(',').Select(n => Convert.ToInt32(n)).ToArray();
            List<PriceList> priceLists = new List<PriceList>();
            foreach(var PriceId in PriceIdList)
            {
                var PriceDetails = _context.PriceLists.Where(c => c.PricelistId == PriceId).FirstOrDefault();
                priceLists.Add(PriceDetails);
            }
            ViewBag.priceLists = priceLists;
            if (combineStage == null)
            {
                return NotFound();
            }

            return View(combineStage);
        }
        // GET: Admin/CombineStages/Edit/5
        public async Task<IActionResult> Edit(int? id)
        {
            var priceLists = _context.PriceLists.ToList();
            List<SelectListItem> mylist = new List<SelectListItem>();
            foreach (var price in priceLists)
            {
                mylist.Add(new SelectListItem { Text = price.Stage, Value = price.PricelistId.ToString() });

            }
            ViewBag.PricelistId = mylist;

            var combineStage = await _context.CombineStage
                .Include(c => c.PriceList)
                .FirstOrDefaultAsync(m => m.StageId == id);
            int[] PriceIdList = combineStage.PricelistIdList.Split(',').Select(n => Convert.ToInt32(n)).ToArray();

            List<PriceList> priceList = new List<PriceList>();
            foreach (var PriceId in PriceIdList)
            {
                var PriceDetails = _context.PriceLists.Where(c => c.PricelistId == PriceId).FirstOrDefault();
                priceLists.Add(PriceDetails);
            }
            ViewBag.priceLists = priceList;



            if (id == null || _context.CombineStage == null)
            {
                return NotFound();
            }

            
            if (combineStage == null)
            {
                return NotFound();
            }
            
            return View(combineStage);
        }

        // POST: Admin/CombineStages/Edit/5
        // To protect from overposting attacks, enable the specific properties you want to bind to.
        // For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, [Bind("StageId,Name,PricelistId,Picture,Price")] CombineStage combineStage, int[] PricelistId, IFormFile ImageFile)
        {
            using (var ms = new MemoryStream())
            {
                ImageFile.CopyTo(ms);
                combineStage.Picture = ms.ToArray();
            }
            int price = 0;
            var stage = "";
            PriceList priceList = new PriceList();

            foreach (var PriceId in PricelistId)
            {
                stage = _context.PriceLists.Where(m => m.PricelistId == PriceId).FirstOrDefault().Stage.ToString();
                price  = _context.PriceLists.Where(m => m.PricelistId == PriceId).FirstOrDefault().Price;
                priceList = _context.PriceLists.Where(m => m.PricelistId == PriceId).FirstOrDefault();

            }
            combineStage.Price = price;
            combineStage.PriceList = priceList;
            combineStage.PricelistIdList = string.Join(",", PricelistId);
            ModelState.Clear();
            if (TryValidateModel(combineStage))
            {
                _context.Update(combineStage);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
            return View(combineStage);
        }
        // GET: Admin/CombineStages/Delete/5
        public async Task<IActionResult> Delete(int? id)
        {
            if (id == null || _context.CombineStage == null)
            {
                return NotFound();
            }

            var combineStage = await _context.CombineStage
                .Include(c => c.PriceList)
                .FirstOrDefaultAsync(m => m.StageId == id);
            if (combineStage == null)
            {
                return NotFound();
            }

            return View(combineStage);
        }

        // POST: Admin/CombineStages/Delete/5
        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DeleteConfirmed(int id)
        {
            if (_context.CombineStage == null)
            {
                return Problem("Entity set 'ManageContext.CombineStage'  is null.");
            }
            var combineStage = await _context.CombineStage.Where(c => c.StageId == id).FirstOrDefaultAsync();
            if (combineStage != null)
            {
                _context.CombineStage.Remove(combineStage);
            }

            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }
    }

Details.cshtml:

@model _2022092602.Models.CombineStage

<div>@Model.Name</div>
<div><img style="width:30px;"  src="data:image/jpg;base64,@Convert.ToBase64String(Model.Picture)" /></div>
<div>@Model.Price</div>

<div>
    @foreach (var price in ViewBag.priceLists)
    {
        <div>
            <span>@price.PricelistId</span>
            <span>@price.Price</span>
            <span>@price.Stage</span>
        </div>

    }
</div>

Delete.cshtml:

@model _2022092602.Models.CombineStage

<h1>Delete</h1>

<h3>Are you sure to delete this?</h3>

<div>
    <dl >
        <dt >
            @Html.DisplayNameFor(model => model.Name)
        </dt>
        <dt >
            @Html.DisplayFor(model => model.Name)
        </dt>
        <dt >
            @Html.DisplayNameFor(model => model.Picture)
        </dt>
        <dt >
            <img style="width:30px;"  src="data:image/jpg;base64,@Convert.ToBase64String(Model.Picture)" />
        </dt>
        <dt >
            @Html.DisplayNameFor(model => model.Price)
        </dt>
        <dt >
            @Html.DisplayFor(model => model.Price)
        </dt>
    </dl>

    <form asp-action="Delete">
        <input type="hidden" asp-for="StageId" />
        <input type="submit" value="Delete"  /> |
        <a asp-action="Index">Back to List</a>
    </form>
</div>

Edit.cshtml:

@model _2022092602.Models.CombineStage

<h1>Edit</h1>

<div >
    <div >
        <form asp-action="Edit" enctype="multipart/form-data">
            <div asp-validation-summary="ModelOnly" ></div>
            <input type="hidden" asp-for="StageId" />
            <div >
                <label asp-for="Name" ></label>
                <input asp-for="Name"  />
            </div>
            <div >
                <label asp-for="PricelistId" ></label>
                <select asp-for="PricelistId" class ="form-control" asp-items="@ViewBag.PricelistId" multiple>
                </select>
            </div>
            <div >
                <label asp-for="Picture" ></label>
                <span><img id="Picture" style="width:100px;"  src="data:image/jpg;base64,@Convert.ToBase64String(Model.Picture)" /></span>
                <input type="file"  name="ImageFile"  onchange="readURL(this);" />
            </div>
            <div >
                <input type="submit" value="Save"  />
            </div>
        </form>
    </div>
</div>

<div>
    <a asp-action="Index">Back to List</a>
</div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script>
    function readURL(input) {
      if (input.files && input.files[0]) {
        var reader = new FileReader();

        reader.onload = function (e) {
          $('#Picture').attr('src', e.target.result).width(100);
        };

        reader.readAsDataURL(input.files[0]);
      }
    }

</script>
  • Related