I'm using a modal popup to run a create method from the controller using jQuery.
In the Post method, I do a check to see if the newly created value already exists.
Prior to using a modal popup, I was able to return an error message simply by using ViewBag when the Index view was returned following the Create method.
Since adding the modal popup, whilst the new value is not created if it already exists, I'm unable to return the error message.
Here's the code I'm using. Any help is much appreciated.
I've left in the different things I've tried as commented out code.
Thanks
View model:
using PoCStaffDatabase.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace PoCStaffDatabase.ViewModels
{
public partial class StaffDetailsVM
{
public IEnumerable<Employee> Employee { get; set; }
public IEnumerable<UserAccessLevel> UserAccessLevel { get; set; }
}
}
View model controller:
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using PoCStaffDatabase.Data;
using PoCStaffDatabase.Models;
using PoCStaffDatabase.ViewModels;
namespace PoCStaffDatabase.Controllers
{
public class StaffDetailsVMController : Controller
{
private readonly AppDbContext _context;
public StaffDetailsVMController(AppDbContext context)
{
_context = context;
}
//GET
public IActionResult Index(int id)
{
if (!EmployeeExists(id))
{
ViewBag.Err = "*Employee PID '" + id + "' does not exist in the Staff Database, please review submitted information!";
return PartialView("_invalidPID");
}
var employee = _context.Employee.Include(e => e.Area)
.Include(e => e.Grade)
.Include(e => e.Team)
.Where(e => e.EmployeeId == id);
ViewBag.EmpId = id;
StaffDetailsVM vm = new StaffDetailsVM
{
Employee = GetEmployee(id),
ContractedHours = GetContractedHours(id),
UserAccessLevel = GetUserAccessLevel(id),
};
//return PartialView("_partialIndex",vm);
return View("Index", vm);
}
// Function/Method - Get Employee
public List<Employee> GetEmployee(int id)
{
List<Employee> emp = _context.Employee.Include(e => e.Area)
.Include(e => e.Grade)
.Include(e => e.Team).ThenInclude(t => t.Stream)
.Where(e => e.EmployeeId == id).ToList();
return emp;
}
// Function/Method - Get Contracted Hours
public List<ContractedHours> GetContractedHours(int id)
{
List<ContractedHours> contractedhours = _context.ContractedHours.Where(ch => ch.EmployeeId == id).ToList();
return contractedhours;
}
// Function/Method - Get Employee
public List<UserAccessLevel> GetUserAccessLevel(int id)
{
List<UserAccessLevel> ual = _context.UserAccessLevel.Include(u => u.BdAppLibrary)
.Include(u => u.AccessLevel)
.Where(p => p.EmployeeId == id && p.Live == true).ToList();
return ual;
}
private bool EmployeeExists(int id)
{
return _context.Employee.Any(e => e.EmployeeId == id);
}
}
}
View - 'Index' where the button is clicked to create the new access level. The div where the error message used to appear before changing the Create view to a modal popup is still visible.
@model PoCStaffDatabase.ViewModels.StaffDetailsVM
@{
ViewData["Title"] = "Staff Details";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" />
<link rel="stylesheet" href="~/css/cards.css" />
<hr />
<h1>@ViewData["Title"]</h1>
<a style="margin: 3px; display: inline-block; float: right" class="btn btn-info" asp-controller="Employees" asp-action="SearchEmployee">Back to Employee Search</a>
<div id="PlaceHolderHere">
</div>
<div>
<div class="row">
@foreach (var emp in Model.Employee)
{
<div class="col-sm-6">
<h4>@Html.DisplayFor(modelItem => emp.Fullname)</h4>
<h4 style="font-weight: bold">PID: @Html.DisplayFor(modelItem => emp.EmployeeId)</h4>
}
</div>
</div>
<h1>User Access Level Details</h1>
<table class="table table-bordered table-hover table-striped w-auto">
<thead class="thead-dark">
<tr>
<th>
Access Level
</th>
<th>
BdApp
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var ual in Model.UserAccessLevel)
{
<tr>
<td>
@Html.DisplayFor(modelItem => ual.AccessLevel.AccessLevelName)
</td>
<td>
@Html.DisplayFor(modelItem => ual.BdAppLibrary.BdAppName)
</td>
<td>
@*<a class="btn btn-success btn-sm" style="margin: 2px" asp-controller="UserAccessLevels" asp-action="Edit" asp-route-id="@ual.UserAccessLevelId">Edit</a>*@
<button type="button" class="btn btn-success btn-sm" data-toggle="ajax-modal" data-target="#editUserAccessLevel" id="btnPopup" data-url="@Url.Action("Edit","UserAccessLevels", new { id = @ual.UserAccessLevelId})">Edit User Access Level</button>
</td>
</tr>
}
</tbody>
</table>
<br />
<div id="errMsg" name="errMsg" style="text-align:center">
<h2 style="font-size: 1.1em; font-weight: bold; color:red">@ViewBag.Err</h2>
</div>
<button type="button" class="btn btn-primary btn-sm" data-toggle="ajax-modal" data-target="#createUserAccessLevel" id="btnPopup" data-url="@Url.Action("Create","UserAccessLevels", new { empId = @ViewBag.EmpId})">Create Access Level for User</button>
<br />
<br />
@section Scripts {
}
The UserAccessLevelController where the Create method is located:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.EntityFrameworkCore;
using PoCStaffDatabase.Data;
using PoCStaffDatabase.Models;
namespace PoCStaffDatabase.Controllers
{
public class UserAccessLevelsController : Controller
{
private readonly AppDbContext _context;
public UserAccessLevelsController(AppDbContext context)
{
_context = context;
}
// GET: UserAccessLevels/Create
public IActionResult Create(int empId)
{
UserAccessLevel ual = new UserAccessLevel();
//var employee = _context.Employee.Find(empId);
List<SelectListItem> li = new List<SelectListItem>
{
new SelectListItem { Text = empId.ToString(), Value = empId.ToString() },
};
ViewData["EmployeeId"] = li;
ViewData["AccessLevelId"] = new SelectList(_context.AccessLevel, "AccessLevelId", "AccessLevelName");
ViewData["BdAppId"] = new SelectList(_context.BdAppLibrary, "BdAppId", "BdAppName");
//ViewData["EmployeeId"] = new SelectList(_context.Employee, "EmployeeId", "EmployeeId", employee.EmployeeId);
return PartialView("_partialCreateUAL", ual);
}
// POST: UserAccessLevels/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("UserAccessLevelId,EmployeeId,AccessLevelId,BdAppId,Live")] UserAccessLevel userAccessLevel)
{
if (ModelState.IsValid)
{
if (UserAccessLevelDuplicate(userAccessLevel.BdAppId, userAccessLevel.EmployeeId))
{
//var bdappName = _context.BdAppLibrary.Include(u => u.BdAppName).Where(u => u.BdAppId == userAccessLevel.BdAppId).FirstOrDefault();
//ViewBag.BdApp = userAccessLevel.BdAppLibrary.BdAppName;
//ViewBag.BdAppName = bdappName;
ViewBag.EmpId = userAccessLevel.EmployeeId;
var err = "An Access Level for this User already exists for the application submitted, please try again.";
ViewData["AccessLevelId"] = new SelectList(_context.AccessLevel, "AccessLevelId", "AccessLevelName", userAccessLevel.AccessLevelId);
ViewData["BdAppId"] = new SelectList(_context.BdAppLibrary, "BdAppId", "BdAppName", userAccessLevel.BdAppId);
ViewData["EmployeeId"] = new SelectList(_context.Employee, "EmployeeId", "EmployeeId", userAccessLevel.EmployeeId);
//return View();
//return RedirectToAction("Index", "StaffDetailsVM", new { id = userAccessLevel.EmployeeId }) ;
//return PartialView("_partialCreateUAL", userAccessLevel);
}
ViewBag.Err = err;
_context.Add(userAccessLevel);
await _context.SaveChangesAsync();
//return RedirectToAction(nameof(Index));
return RedirectToAction("Index", "StaffDetailsVM", new { id = userAccessLevel.EmployeeId });
}
ViewBag.Err = "Invalid Submission, please try again.";
ViewData["AccessLevelId"] = new SelectList(_context.AccessLevel, "AccessLevelId", "AccessLevelName", userAccessLevel.AccessLevelId);
ViewData["BdAppId"] = new SelectList(_context.BdAppLibrary, "BdAppId", "BdAppName", userAccessLevel.BdAppId);
ViewData["EmployeeId"] = new SelectList(_context.Employee, "EmployeeId", "EmployeeId", userAccessLevel.EmployeeId);
return View(userAccessLevel);
}
// Function - Checks that Access Level for the selected app doesn't already exist for this user-
// This assumes we will not allow multiple access levels per App.
private bool UserAccessLevelDuplicate(int app, int employee)
{
return _context.UserAccessLevel.Any(e => e.BdAppId == app && e.EmployeeId == employee && e.Live == true);
}
}
}
Partial view (modal popup):
@model PoCStaffDatabase.Models.UserAccessLevel
@*<div class="modal fade" id="createUserAccessLevel" tabindex="-1" role="dialog" aria-labelledby="createUserAccessLevelLabel" aria-hidden="true">*@
<div class="modal" id="createUserAccessLevel" tabindex="-1" role="dialog" aria-labelledby="createUserAccessLevelLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="createUserAccessLevelLabel">Create User Access Level</h5>
<button type="button" class="close" data-modal="#createUserAccessLevel" data-bs-dismiss="modal" id="btnClose" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div id="errMsg" name="errMsg" style="text-align:center">
<h2 style="font-size: 1.1em; font-weight: bold; color:red">@ViewBag.Err</h2>
</div>
<div class="modal-body">
<form asp-action="Create">
<div class="form-group" >
<label asp-for="EmployeeId" class="control-label"></label>
<select asp-for="EmployeeId" class="form-control" asp-items="ViewBag.EmployeeId"></select>
<span asp-validation-for="EmployeeId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="AccessLevelId" class="control-label"></label>
<select asp-for="AccessLevelId" class="form-control" asp-items="ViewBag.AccessLevelId"></select>
<span asp-validation-for="AccessLevelId" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="BdAppId" class="control-label"></label>
<select asp-for="BdAppId" class="form-control" asp-items="ViewBag.BdAppId"></select>
<span asp-validation-for="BdAppId" class="text-danger"></span>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="Live" /> @Html.DisplayNameFor(model => model.Live)
</label>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-modal="#createUserAccessLevel" data-bs-dismiss="modal" id="btnClose">Cancel</button>
<button type="button" class="btn btn-primary" data-save="modal" data-url='' id="btnSave">Update</button>
</div>
</form>
</div>
</div>
</div>
</div>
jQuery code:
$(document).ready(function () {
$('body').on("click", '#btnPopup', function (event) {
var PlaceHolderElement = $('#PlaceHolderHere'),
url = $(this).data('url');
PlaceHolderElement.empty();
$.get(url, function (data) {
PlaceHolderElement.html(data);
var data = PlaceHolderElement.find('.modal');
$(PlaceHolderElement.find('.modal')).modal('show');
});
PlaceHolderElement.on("click", '#btnSave', function (event) {
form = $(this).parents('.modal').find('form'),
actionUrl = form.attr('action'),
sendData = form.serialize();
$.post(actionUrl, sendData).done(function (data) {
$(PlaceHolderElement.find('.modal')).modal('hide');
location.reload(true);
//$('#detailsDiv').html(data);
});
});
});
})