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.
Update2
I want to display it on Details Page like this
Edit Update3
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:
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>