I have Two different ASP.net Core 6.0 applications running that have tables linked to other tables by foreign keys. I create a CRUD for both pages. At the first CRUD (PriceList) page, I will enter the data. At the the second CRUD (CombineStage) of the page I will get the data (Stage) from the first page (Pricelist) using multiple select and the search box and its corresponding price in the Index page after using multiple select. I can't find any code commands to make this work. Any help would be appreciated. My foreign key is PricelistId. Below is my code:
CombineStage.cs
using System.ComponentModel.DataAnnotations;
namespace WebApp.Models
{
public class CombineStage
{
[Key]
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")]
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 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);
if (combineStage == null)
{
return NotFound();
}
return View(combineStage);
}
// GET: Admin/CombineStages/Create
public IActionResult Create()
{
ViewData["PricelistId"] = new SelectList(_context.PriceLists, "PricelistId", "Stage");
return View();
}
// POST: Admin/CombineStages/Create
// 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> Create([Bind("StageId,Name,PricelistId,Picture,Price")] CombineStage combineStage)
{
if (ModelState.IsValid)
{
_context.Add(combineStage);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
ViewData["PricelistId"] = new SelectList(_context.PriceLists, "PricelistId", "Stage", combineStage.PricelistId);
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.FindAsync(id);
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
@model WebApp.Models.CombineStage
@{
ViewData["Title"] = "Create";
Layout = "~/Areas/Admin/Views/Shared/_AdminLayout.cshtml";
}
<h1>Create</h1>
<h4>CombineStage</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PricelistId" class="control-label"></label>
<select asp-for="PricelistId" class ="form-control" asp-items="ViewBag.PricelistId" multiple>
</select>
</div>
<div class="form-group">
<label asp-for="Picture" class="control-label"></label>
<input asp-for="Picture" class="form-control" />
<span asp-validation-for="Picture" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
Thank you so much!
Update Pricelist:
Pricelist.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Drawing;
namespace WebApp.Models
{
public partial class PriceList
{
public PriceList()
{
StageDetails = new HashSet<StageDetail>();
CombineStages = new HashSet<CombineStage>();
}
[Key]
public int PricelistId { get; set; }
[Required(ErrorMessage = "Bạn chưa chọn ảnh")]
public string Image { get; set; }
[Required (ErrorMessage = "Bạn chưa chọn máy may")]
public Machine Machine { get; set; }
[Required (ErrorMessage = "Bạn chưa tên nhập công đoạn")]
public string Stage { get; set; }
[Required (ErrorMessage = "Bạn chưa nhập giá tiền")]
public int Price { get; set; }
public virtual ICollection<StageDetail> StageDetails { get; set; }
public virtual ICollection<CombineStage> CombineStages { get; set; }
}
public enum Machine
{
VS,
[Display(Name = "1K")]
OneK
}
}
PriceListsController
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using WebApp.Models;
using WebApp.ViewModel;
namespace WebApp.Areas.Admin.Controllers
{
[Area("Admin")]
public class PriceListsController : Controller
{
private readonly ManageContext _context;
private readonly IWebHostEnvironment _environment;
public PriceListsController(ManageContext context, IWebHostEnvironment environment)
{
_context = context;
_environment = environment;
}
public async Task<IActionResult> Index()
{
return View(await _context.PriceLists.ToListAsync());
}
public async Task<IActionResult> Details(int? id)
{
try
{
if (id == null)
{
return NotFound();
}
var priceList = await _context.PriceLists
.FirstOrDefaultAsync(m => m.PricelistId == id);
var priceListModelView = new PriceListViewModel()
{
Id = priceList.PricelistId,
ExistingImage = priceList.Image,
Machine = priceList.Machine,
Stage = priceList.Stage,
Price = priceList.Price
};
if (priceList == null)
{
return NotFound();
}
return View(priceList);
}
catch (Exception)
{
throw;
}
}
public IActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(PriceListViewModel model)
{
try
{
if (ModelState.IsValid)
{
string uniqueFileName = ProcessUploadedFile(model);
PriceList priceList = new()
{
Image = uniqueFileName,
Machine = model.Machine,
Stage = model.Stage,
Price = model.Price
};
_context.Add(priceList);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
}
catch (Exception)
{
throw;
}
return View(model);
}
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var priceList = await _context.PriceLists.FindAsync(id);
var priceListViewModel = new PriceListViewModel()
{
Id = priceList.PricelistId,
ExistingImage = priceList.Image,
Machine = priceList.Machine,
Stage = priceList.Stage,
Price = priceList.Price
};
if (priceList == null)
{
return NotFound();
}
return View(priceListViewModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(int id, PriceListViewModel model)
{
if (ModelState.IsValid)
{
var priceList = await _context.PriceLists.FindAsync(model.Id);
priceList.Machine = model.Machine;
priceList.Stage = model.Stage;
priceList.Price = model.Price;
if (model.PricelistImage != null)
{
if (model.ExistingImage != null)
{
string filePath = Path.Combine(_environment.WebRootPath, "Images", model.ExistingImage);
System.IO.File.Delete(filePath);
}
priceList.Image = ProcessUploadedFile(model);
}
_context.Update(priceList);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View();
}
public async Task<IActionResult> Delete(int? id)
{
if (id == null)
{
return NotFound();
}
var priceList = await _context.PriceLists
.FirstOrDefaultAsync(m => m.PricelistId == id);
var priceListViewModel = new PriceListViewModel()
{
Id = priceList.PricelistId,
ExistingImage = priceList.Image,
Machine = priceList.Machine,
Stage = priceList.Stage,
Price = priceList.Price
};
if (priceList == null)
{
return NotFound();
}
return View(priceListViewModel);
}
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteConfirmed(int id)
{
var priceList = await _context.PriceLists.FindAsync(id);
//string deleteFileFromFolder = "wwwroot\\Uploads\\";
string deleteFileFromFolder = Path.Combine(_environment.WebRootPath, "Images");
var CurrentImage = Path.Combine(Directory.GetCurrentDirectory(), deleteFileFromFolder, priceList.Image);
_context.PriceLists.Remove(priceList);
if (System.IO.File.Exists(CurrentImage))
{
System.IO.File.Delete(CurrentImage);
}
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
private bool SpeakerExists(int id)
{
return _context.PriceLists.Any(e => e.PricelistId == id);
}
private string ProcessUploadedFile(PriceListViewModel model)
{
string uniqueFileName = null;
string path = Path.Combine(_environment.WebRootPath, "Images");
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
if (model.PricelistImage != null)
{
string uploadsFolder = Path.Combine(_environment.WebRootPath, "Images");
uniqueFileName = Guid.NewGuid().ToString() + "_" + model.PricelistImage.FileName;
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
model.PricelistImage.CopyTo(fileStream);
}
}
return uniqueFileName;
}
}
}
Update Create(HTTPPost) CombineStagesController: (But it still hasn't solved my request. I want when I select multiple then I get the entire corresponding Price value in Index Page)
public IActionResult Create()
{
ViewData["PricelistId"] = new SelectList(_context.PriceLists, "PricelistId", "Stage");
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("StageId,Name,PricelistId,Picture,Price")] CombineStage combineStage, int[] PricelistId)
{
foreach (var id in PricelistId)
{
var stage = _context.PriceLists.Where(m => m.PricelistId == id).Select(x => x.Stage).ToString();
}
if (ModelState.IsValid)
{
_context.Add(combineStage);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(combineStage);
}
Update Things I'm looking forward to
Next I will choose 2 option stages that I created
Next step, I want the total price of the 2 process options I have selected here
Finally, I want to show all the stages and prices of my 2 options that I have selected
That's all my request.
I made a simple test, you can refer to it.
I added a field to CombineStage
to store your options:
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:
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);
}
}
Create.cshtml:
@model _2022092602.Models.CombineStage
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>CombineStage</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PricelistId" class="control-label"></label>
<select asp-for="PricelistId" class ="form-control" asp-items="@ViewBag.PricelistId" multiple>
</select>
</div>
<div class="form-group">
<label asp-for="Picture" class="control-label"></label>
<input asp-for="Picture" class="form-control" />
<span asp-validation-for="Picture" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
Details.cshtml:
@model _2022092602.Models.CombineStage
<div>@Model.Name</div>
<div>@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>