I am trying to create a Job record using EF Core and then displaying after hitting the create button I want to display a table list of unassignedUsers that don't contain matching ID of the newly created record.
But I cannot even display the page and will be shown the error page instead. This occurs in the 'var id=@model.ID' for the unassignedUsersTable which I am instantiating in DataTables. Because I haven't created a Job object with ID so ASP.NET MVC 5 cannot check database to see if there are any users with matching job id. This is where I'm stuck. I do not know how to delay ASP.NET from checking for if newly created record ID exists after user hits the submit button.
Here is the code I'm stuck on:
Models/Users.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Pitcher.Models;
namespace Pitcher.Models
{
public class User
{
public int ID { get; set; }
[Required]
[StringLength(20, MinimumLength = 2, ErrorMessage = "* First Name be bettween 2 to 20 characters.")]
[DataType(DataType.Text)]
[Display(Name = "First Name")]
[Column("UserFirstName")]
public string UserFirstName { get; set; }
[Required]
[StringLength(30, MinimumLength = 2, ErrorMessage = "* Last Name be bettween 2 to 30 characters.")]
[DataType(DataType.Text)]
[Display(Name = "Last Name")]
[Column("UserLastName")]
public string UserLastName { get; set; }
[Required]
[StringLength(30, MinimumLength = 3, ErrorMessage = "Email address must be bettween 3 to 30 characters.")]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email")]
[Column("UserContactEmail")]
public string UserContactEmail{get;set;}
[Display(Name = "Phone Number")]
[Phone()]
[Column("UserPhoneNumber")]
public string UserPhoneNumber{get;set;}
[StringLength(37,ErrorMessage = "Address cannot be longer than 37 characters.")]
[DataType(DataType.Text)]
[Display(Name = "Address")]
[Column("UserAddress")]
public string UserAddress{get;set;}
[Display(Name = "Post Code")]
[Column("UserPostCode")][DataType(DataType.PostalCode)]
public string UserPostCode { get; set; }
[StringLength(15,ErrorMessage = "Country cannot be longer than 15 characters.")]
[DataType(DataType.Text)]
[Display(Name = "Country")]
[Column("UserCountry")]
public string UserCountry {get;set;}
[Phone()]
[Display(Name = "Mobile Number")]
[Column("UserMobileNumber")]
public string UserMobileNumber {get;set;}
[StringLength(3,ErrorMessage = "State cannot be longer than 3 characters.")]
[DataType(DataType.Text)]
[Display(Name = "State")]
[Column("UserState")]
public string UserState {get;set;}
public string UserFullname => string.Format("{0} {1}", UserFirstName, UserLastName);
public ICollection Registrations {get;set;}
}
}
Models/Jobs.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
namespace Pitcher.Models
{
public class Job
{
public int ID { get; set; }
[Required]
[StringLength(20, MinimumLength = 3, ErrorMessage = "Job Title must be bettween 3 to 20 characters.")]
[DataType(DataType.Text)]
[Display(Name = "Job Title")]
[Column("JobTitle")]
public string JobTitle { get; set; }
[StringLength(200, MinimumLength = 3, ErrorMessage = "Job Description must be bettween 200 to 3 characters.")]
[DataType(DataType.Text)]
[Display(Name = "Description")]
[Column("JobDescription")]
public string JobDescription { get; set; }
[Required]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = " Start Date")]
[Column("JobStartDate")]
public DateTime JobStartDate {get;set;}
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
[Display(Name = "Deadline Date")]
[Column("JobDeadlineDate")]
public DateTime JobDeadline {get;set;}
[Display(Name = "Job Is Complete?")]
[Column("JobIsComplete")]
public bool JobIsComplete{get;set;}
public ICollection Registrations {get;set;}
public ICollection Results {get;set;}
}
}
Views/Jobs/Create.cshtml
<pre>@model Pitcher.Models.Job
@{
var user = new User();
}
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>Job</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="JobTitle" class="control-label"></label>
<input asp-for="JobTitle" class="form-control" />
<span asp-validation-for="JobTitle" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="JobDescription" class="control-label"></label>
<textarea asp-for="JobDescription" class="form-control" rows="10" cols="50"></textarea>
<span asp-validation-for="JobDescription" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="JobStartDate" class="control-label"></label>
<input asp-for="JobStartDate" class="form-control" />
<span asp-validation-for="JobStartDate" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="JobDeadline" class="control-label"></label>
<input asp-for="JobDeadline" class="form-control" />
<span asp-validation-for="JobDeadline" class="text-danger"></span>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="JobIsComplete" /> @Html.DisplayNameFor(model => model.JobIsComplete)
</label>
</div>
<div class="form-group">
<input type="submit"
value="Create" class="btn btn-primary" onclick='buttonClick()'/>
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@* <table id="registeredUsersTable" class="table" style="display: none">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => user.UserFirstName)
</th>
<th>
@Html.DisplayNameFor(model => user.UserLastName)
</th>
<th>
@Html.DisplayNameFor(model => user.UserContactEmail)
</th>
<th>
</th>
</tr>
</thead>
<tbody></tbody>
</table> *@
@* Hide table before submission of record to DB *@
<table id="unassignedUsersTable" style='display:none;'>
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => user.UserFirstName)
</th>
<th>
@Html.DisplayNameFor(model => user.UserLastName)
</th>
<th>
@Html.DisplayNameFor(model => user.UserContactEmail)
</th>
<th>
</th>
</tr>
</thead>
<tbody></tbody>
</table>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
$.fn.dataTable.ext.errMode = 'throw';
@* function buttonClick(){
document.getElementById('registeredUsersTable').style.display = 'block';
var id=@Model.ID = $('#registeredUsersTable').DataTable({
"ajax": {
'type': 'get',
'data': { ID: id},
'dataType': "json",
"url": "@Url.Action("GetAllUsersByJobId")",
"dataSrc": function (result) {
return result;
}
},
"columns": [
{ "data": "userFirstName"},
{ "data": "userLastName"},
{ "data": "userContactEmail"}
]
});
} *@
function buttonClick(){
document.getElementById('unassignedUsersTable').style.display = 'block';
var id=@Model.ID
$('#unassignedUsersTable').DataTable({
"ajax": {
type: 'get',
'dataType': "json",
"url": "@Url.Action("GetUnassignedUsersJobId")",
"dataSrc": function (result) {
return result;
}
},
"columns": [
{ "data": "userFirstName"},
{ "data": "userLastName"},
{ "data": "userContactEmail"},
{
"data": null,
"render": function (value) {
return '<a href="/Users/Details/' + value.id + '"button type="button" class="btn btn-primary btn-block">Details</a> <br> '
+ '<a href="/Users/Edit/' + value.id + '"button type="button" class="btn btn-info btn-block">Edit </a> <br> '
+ '<a href="/Users/Delete/' + value.id + '"button type="button" class="btn btn-primary btn-block">Delete</a>';
}
}
]
})
};
</script>
}
JobsController.cs
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 Pitcher.Data;
using Pitcher.Models;
using Pitcher.Models.TeamViewModels;
namespace Pitcher.Controllers
{
public class JobsController : Controller
{
private readonly TeamContext _context;
public JobsController(TeamContext context)
{
_context = context;
}
public IActionResult Create()
{
return View();
}
public IActionResult GetUnassignedUsersJobId(int? ID)
{
if (ID == null)
{
return NotFound();
}
_context.Jobs.OrderByDescending(j => j.ID).FirstOrDefault();
var userlist = _context.Registrations.Where(r => r.JobID != ID).Select(r => r.User).ToList();
return Json(userlist);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("JobTitle,JobDescription,JobStartDate,JobDeadline,JobIsComplete")] Job job)
{
try
{
if (ModelState.IsValid)
{
_context.Add(job);
await _context.SaveChangesAsync();
}
ViewData["Jobs"] = _context.Jobs.ToList();
}
catch(DbUpdateException )
{
ModelState.AddModelError("", "Unable to save changes. " +
"Try again, and if the problem persists " +
"See your system administrator.");
}
return View(job);
}
}
}
TeamContext.cs
using Pitcher.Models;
using Microsoft.EntityFrameworkCore;
using Pitcher.Models.TeamViewModels;
namespace Pitcher.Data
{
public class TeamContext : DbContext
{
public TeamContext(DbContextOptions<TeamContext> options) : base(options)
{
}
public DbSet<User> Users { get; set; }
public DbSet<Registration> Registrations {get;set;}
public DbSet<Job> Jobs {get;set;}
public DbSet<Problem> Problems { get; set; }
public DbSet<Result> Results {get;set;}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().ToTable("tblUser");
modelBuilder.Entity<Registration>().ToTable("tblRegistration");
modelBuilder.Entity<Job>().ToTable("tblJob");
modelBuilder.Entity<Problem>().ToTable("tblProblem");
modelBuilder.Entity<Chat>().ToTable("tblChat");
modelBuilder.Entity<Result>().ToTable("tblResult");
}
}
}
What I have tried:
I'll elaborate further. My objective (if you or someone else can help me please) is to delay that null object from being instantiated until I...
1. Click 'submit'.
2. ASP generates an ID for the record (which it is successfully doing).
3. ASP Saves record to database (which it is successfully doing).
4. ASP then gets the most newly created record by ID. I don't know how to do that.
5. That ID will be stationed in memory so we can render it to the unassignedUsersTable.
6. The object 'var id=@model.ID' then gets instantiated in memory instead of returning null.