Search code examples
c#asp.net-corecrud

Select multiple and display corresponding value from another model


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

enter image description here

Next I will choose 2 option stages that I created

enter image description here

Next step, I want the total price of the 2 process options I have selected here

enter image description here

Finally, I want to show all the stages and prices of my 2 options that I have selected

enter image description here

That's all my request.


Solution

  • 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>
    

    Test Result: enter image description here enter image description here