Search code examples
drop-down-menuasp.net-core-mvc.net-6.0multiple-views

.NET 6 EF - Create a view with information from two classes (using dropdownlist in creation)


.Net 6 Code first DB with EF

I have two MVC-pairs, one to create + display an "Incident/Event" and one to create + display "Transaction/Person" tied to a specific event. What I'm looking to achieve is that when you create Transaction/Person you pick one of the existing already created (isActive) Incident/Event from a dropdownlist during creation.

After creation I want to display the created Transaction/Person object with both it's own properties as well as the chosen incident/event in a view(table). How do you suggest I solve this the best way? I will try to supply some code but let me know if it's insufficient, still very new .NET MVC and a fair amount of it is autogenerated.

If some variable is missing or name doesn't match completely it's me trying to remove a lot of variables and stuff to make it easier to read. the code runs fine just that Incident/Event and Transaction/Person are currently completely seperate and needs to be tied together.

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using CRUD1.Models;
using ClosedXML.Excel;
using System.Data;

namespace CRUD1.Controllers
{
    public class TransactionController : Controller
    {
        private readonly myDbContext _context;

        public TransactionController(myDbContext context)
        {
            _context = context;
        }

        public IActionResult Index()
        {
            List<Transaction> transactions = (from Transaction in _context.Transactions
                                        select Transaction).ToList();
            return View(transactions);
        }


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

            var transaction = await _context.Transactions
                .FirstOrDefaultAsync(m => m.CallerId == id);
            if (transaction == null)
            {
                return NotFound();
            }

            return View(transaction);
        }

        // GET: Transaction/Create
        public IActionResult Create()
        {            
            return View();
        }

        // POST: Transaction/Create

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("CallerId,Date,CallerName")] Transaction transaction)
        {            
            if (ModelState.IsValid)
            {
                _context.Add(transaction);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
            return View(transaction);
        }

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

            var transaction = await _context.Transactions.FindAsync(id);
            if (transaction == null)
            {
                return NotFound();
            }
            return View(transaction);
        }

        // POST: Transaction/Edit/5
       
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, [Bind("CallerId,Date,CallerName")] Transaction transaction)
        {
            if (id != transaction.CallerId)
            {
                return NotFound();
            }

            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(transaction);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!TransactionExists(transaction.CallerId))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                return RedirectToAction(nameof(Index));
            }
            return View(transaction);
        }

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

            var transaction = await _context.Transactions
                .FirstOrDefaultAsync(m => m.CallerId == id);
            if (transaction == null)
            {
                return NotFound();
            }

            return View(transaction);
        }

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

        private bool TransactionExists(int id)
        {
          return (_context.Transactions?.Any(e => e.CallerId == id)).GetValueOrDefault();
        }
    }
}

The Incident-model

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace CRUD1.Models
{
    public class Incident
    {
        [Key]
        public int IncidentId { get; set; }

        public string IncidentName { get; set; }
 
        public bool isActive { get; set; }
    }
}

Transaction model

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace CRUD1.Models
{
    public class Transaction
    {
        [Key]
        public int CallerId { get; set; }
        
        public DateTime Date { get; set; } = DateTime.Now;
  
        public string CallerName { get; set; }    

    }
}

Transaction/Person - Create view (Here is where I'm looking to create a dropdownbox to chose from Incidents)

@model CRUD1.Models.Transaction

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

<h4>New Person/transaction</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="CallerName" class="control-label"></label>
                <input asp-for="CallerName" class="form-control" />
                <span asp-validation-for="CallerName" class="text-danger"></span>
            </div>
   
            <div class="form-group">
                <input type="submit" value="Send" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>


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


Completely autogenerated "Incident/Event" - Controller

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 CRUD1.Models;

namespace CRUD1.Controllers
{
    public class IncidentController : Controller
    {
        private readonly myDbContext _context;

        public IncidentController(myDbContext context)
        {
            _context = context;
        }

        // GET: Incident
        public async Task<IActionResult> Index()
        {
              return View(await _context.Incidents.ToListAsync());
        }

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

            var incident = await _context.Incidents
                .FirstOrDefaultAsync(m => m.IncidentId == id);
            if (incident == null)
            {
                return NotFound();
            }

            return View(incident);
        }

        // GET: Incident/Create
        public IActionResult Create()
        {
            return View();
        }

        // POST: Incident/Create

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("IncidentId,IncidentName,isActive")] Incident incident)
        {
            if (ModelState.IsValid)
            {
                _context.Add(incident);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
            return View(incident);
        }

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

            var incident = await _context.Incidents.FindAsync(id);
            if (incident == null)
            {
                return NotFound();
            }
            return View(incident);
        }

        // POST: Incident/Edit/5

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Edit(int id, [Bind("IncidentId,IncidentName,isActive")] Incident incident)
        {
            if (id != incident.IncidentId)
            {
                return NotFound();
            }

            if (ModelState.IsValid)
            {
                try
                {
                    _context.Update(incident);
                    await _context.SaveChangesAsync();
                }
                catch (DbUpdateConcurrencyException)
                {
                    if (!IncidentExists(incident.IncidentId))
                    {
                        return NotFound();
                    }
                    else
                    {
                        throw;
                    }
                }
                return RedirectToAction(nameof(Index));
            }
            return View(incident);
        }

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

            var incident = await _context.Incidents
                .FirstOrDefaultAsync(m => m.IncidentId == id);
            if (incident == null)
            {
                return NotFound();
            }

            return View(incident);
        }

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

        private bool IncidentExists(int id)
        {
          return _context.Incidents.Any(e => e.IncidentId == id);
        }
    }
}

Solution

  • Here is a sample about how to create a Transaction with Incident dropdownlist and display the created Transaction with selected Incident:

    Model

    public class Incident
    {
        [Key]
        public int IncidentId { get; set; }
        public string? IncidentName { get; set; }
        public bool isActive { get; set; }
        public List<Transaction>? Transaction { get; set; }
    }
    public class Transaction
    {
        [Key]
        public int CallerId { get; set; }
        public DateTime Date { get; set; } = DateTime.Now;
        public string? CallerName { get; set; }
        public Incident? Incident { get; set; }
    }
    

    View

    1.Create.cshtml

    @model Transaction
    
    @{
        ViewData["Title"] = "Create";
    }
    
    <h1>Create</h1>
    
    <h4>Transaction</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="Date" class="control-label"></label>
                    <input asp-for="Date" class="form-control" />
                    <span asp-validation-for="Date" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="CallerName" class="control-label"></label>
                    <input asp-for="CallerName" class="form-control" />
                    <span asp-validation-for="CallerName" class="text-danger"></span>
                </div>
                 <div class="form-group">
                    <label asp-for="Incident.IncidentId" class="control-label"></label>
                    <select asp-for="Incident.IncidentId" asp-items="@ViewBag.Incident" class="form-control">
                        <option>select an option</option>
                    </select>
                    <span asp-validation-for="CallerName" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <input type="submit" value="Create" class="btn btn-primary" />
                </div>
            </form>
        </div>
    </div>
    
    <div>
        <a asp-action="Index">Back to List</a>
    </div>
    
    @section Scripts {
        @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    }
    

    2.Index.cshtml

    @model IEnumerable<Transaction>
    
    @{
        ViewData["Title"] = "Index";
    }
    
    <h1>Index</h1>
    
    <p>
        <a asp-action="Create">Create New</a>
    </p>
    <table class="table">
        <thead>
            <tr>
                <th>
                    @Html.DisplayNameFor(model => model.Date)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.CallerName)
                </th>
                <th>
                    @Html.DisplayNameFor(model => model.Incident.IncidentName)
                </th>
                <th></th>
            </tr>
        </thead>
        <tbody>
    @foreach (var item in Model) {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.Date)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.CallerName)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.Incident.IncidentName)
                </td>
                <td>
                    <a asp-action="Edit" asp-route-id="@item.CallerId">Edit</a> |
                    <a asp-action="Details" asp-route-id="@item.CallerId">Details</a> |
                    <a asp-action="Delete" asp-route-id="@item.CallerId">Delete</a>
                </td>
            </tr>
    }
        </tbody>
    </table>
    

    Controller

    public class TransactionsController : Controller
    {
        private readonly MvcProjContext _context;
    
        public TransactionsController(MvcProjContext context)
        {
            _context = context;
        }
    
        // GET: Transactions
        public async Task<IActionResult> Index()
        {
              return View(await _context.Transactions.Include(a=>a.Incident).ToListAsync());
        }
    
        
        // GET: Transactions/Create
        public IActionResult Create()
        {
            //display the dropdownlist
            ViewBag.Incident = new SelectList(_context.Incidents.ToList(), "IncidentId", "IncidentName");
            return View();
        }
    
        // POST: Transactions/Create       
        [HttpPost]
        public async Task<IActionResult> Create([FromForm]Transaction transaction)
        {
            if (ModelState.IsValid)
            {
                transaction.Incident = _context.Incidents.Find(transaction.Incident.IncidentId);
                _context.Add(transaction);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
            ViewBag.Incident = new SelectList(_context.Incidents.ToList(), "IncidentId", "IncidentName");
            return View(transaction);
        }
    }