.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);
}
}
}
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);
}
}