ASP.Net Core MVC CRUD PopUp Modal - asp.net

I am just starting to work with ASP.Net Core MVC. I have difficulty in creating a popup modal. I've tried to create a simple page. 
Below is my model:
namespace CoreModal.Models
{
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
}
}
Below is my EmployeeController:
namespace CoreModal.Controllers
{
public class EmployeeController : Controller
{
public static List<Employee> empList = new List<Employee>() {
new Employee {Id=1, Name="John", Email="john#gmail.com", Address="Campbell", Phone="1234"}
};
public IActionResult Index()
{
ViewBag.Employee = empList;
return View();
}
[HttpPost]
[Route("create")]
public IActionResult Create(string name, string email, string address, string phone)
{
var newEmployee = new Employee
{
Name = name,
Email = email,
Address = address,
Phone = phone
};
empList.Add(newEmployee);
ViewBag.Employee = empList;
return RedirectToAction("Index");
}
}
}
In my Index View, I create a button to trigger a popup modal for creating a new Employee object as follow:
<i class="material-icons"></i><span>Add New Employee</span>
<d id="addEmployeeModal" class="modal fade" name="addEmployeeModal">
<div class="modal-dialog">
<div class="modal-content">
<form method="post" asp-controller="employee" asp-action="create">
<div class="modal-header">
<h4 class="modal-title">Add Employee</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" required="required" name="name"/>
</div>
<div class="form-group">
<label>Email</label>
<input type="text" class="form-control" required="required" name="email"/>
</div>
<div class="form-group">
<label>Address</label>
<input type="text" class="form-control" required="required" name="address"/>
</div>
<div class="form-group">
<label>Phone</label>
<input type="text" class="form-control" required="required" name="phone"/>
</div>
</div>
<div class="modal-footer">
<input type="button" class="btn btn-default" data-dismiss="modal" value="Cancel" />
<input type="Submit" class="btn btn-success" value="Add" />
</div>
</form>
</div>
</div>
</d>
But instead of directing to a popup modal, it directs it to url https://localhost:44330/#addEmployeeModal.
What did I do wrong?
Thanks

First of all, you should not be keeping your data inside the controller because the controller runs anew each time it is called and your data will be lost. Use a database for best results.
Your syntax for calling the modal is slightly wrong.
Check here for the correct syntax. It's not href (that's your mistake!) You can mostly copy this code and replace the inner parts with what you have.
https://getbootstrap.com/docs/4.0/components/modal/
*Note: you must be using bootstrap for this to work
Good Luck!
Edit : You can try this: (may need some tweaking)
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Add Employee
</button>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form method="post" asp-controller="employee" asp-action="create">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Add Employee</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" required="required" name="name"/>
</div>
<div class="form-group">
<label>Email</label>
<input type="text" class="form-control" required="required" name="email"/>
</div>
<div class="form-group">
<label>Address</label>
<input type="text" class="form-control" required="required" name="address"/>
</div>
<div class="form-group">
<label>Phone</label>
<input type="text" class="form-control" required="required" name="phone"/>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<input type="submit" class="btn btn-primary">Add Employee</button>
</div>
</form>
</div>
</div>
</div>
Additionally, It is better practice to send a model into the controller. Use a model on the top of your view, link it to your employee model, and send that into the controller instead.

Related

ASP.NET Double validation, custom message for numbers only

I have a validation for Fueling property which is a double.
[Display(Name = "Tankolás")]
[DisplayFormat(DataFormatString = "{0} l", ApplyFormatInEditMode = false)]
public double? Fueling { get; set; }
If I type letters instead of number in the input I get the error message: The value 'test' is not valid for Tankolás.
How could I change the error message?
Here is the view:
<div class="form-group">
<label asp-for="Fueling" class="control-label"></label>
<input id="Fueling" asp-for="Fueling" class="form-control" placeholder="Tankolás" />
<span asp-validation-for="Fueling" class="text-danger"></span>
</div>
EDIT - Full View code
#model MainProject.Models.RoadRecord
#{
ViewData["Title"] = "Hozzáadás";
}
<head>
<link rel="stylesheet" href="~/css/RoadRecords/create.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<div class="container">
<div class="text-center">
<h2>Új Menetlevél hozzáadása</h2>
</div>
<div class="row justify-content-center">
<div class="col-8">
<form asp-action="Create">
<input type="hidden" asp-for="UserId" />
<input type="hidden" asp-for="LicencePlate" />
<div class="form-group">
<label asp-for="Mileage" class="control-label"></label>
<div class="input-group-sm">
<input asp-for="Mileage" class="form-control" placeholder="Kilométer" />
<div id="mileageContainer" class="input-group-append">
<partial name="_ShowMileagePartialView.cshtml" model="#Model" />
</div>
</div>
<span asp-validation-for="Mileage" class="text-danger"></span>
#if (!string.IsNullOrEmpty(ViewBag.Message))
{
<span class="text-danger">
#ViewBag.Message
</span>
}
</div>
#*
<div class="form-group">
<label asp-for="TimeStamp" class="control-label"></label>
<input type="datetime-local" asp-for="TimeStamp" class="form-control" value="#DateTime.Now.ToString("yyyy-MM-ddTHH:mm")" />
<span asp-validation-for="TimeStamp" class="text-danger"></span>
</div>
*#
<div class="form-group">
<label asp-for="Location" class="control-label"></label>
<div class="input-group">
<input id="varos" type="text" asp-for="Location" class="form-control" aria-describedby="getLocationButton" />
<div class="input-group-append">
<button type="button" class="btn btn-primary" id="getLocationButton">Pozícióm</button>
</div>
</div>
<span asp-validation-for="Location" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Type" class="control-label"></label>
<select id="selectType" asp-for="Type" class="form-control">
<option selected value="C">Céges</option>
<option value="M">Magán</option>
</select>
</div>
<div class="form-group">
<label asp-for="Fueling" class="control-label"></label>
<input id="Fueling" asp-for="Fueling" class="form-control" placeholder="Tankolás" />
<span asp-validation-for="Fueling" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Note" class="control-label"></label>
<input asp-for="Note" class="form-control" placeholder="Megjegyzés" />
<span asp-validation-for="Note" class="text-danger"></span>
</div>
<div class="form-group">
#Html.AntiForgeryToken()<input onclick="ConvertDouble()" type="submit" value="Hozzáadás" class="btn btn-primary w-100" />
</div>
</form>
<a class="add" asp-action="Index" asp-route-licencePlate="#ViewBag.LicencePlate">
<button type="button" class="btn btn-secondary w-100">
Vissza
</button>
</a>
</div>
</div>
</div>
#section Scripts {
<!--GEO Location-->
<script>
$(document).ready(function () {
$('#getLocationButton').click(function () {
$.getJSON('https://geolocation-db.com/json/')
.done(function (location) {
$('#country').html(location.country_name);
$('#state').html(location.state);
$('#city').html(location.city);
$('#latitude').html(location.latitude);
$('#longitude').html(location.longitude);
$('#ip').html(location.IPv4);
document.getElementById('varos').value = location.city;
});
});
});
$.getJSON('https://geolocation-db.com/json/')
.done(function (location) {
console.log("kint");
if (document.getElementById('varos').value == '') {
console.log("bent");
$('#country').html(location.country_name);
$('#state').html(location.state);
$('#city').html(location.city);
$('#latitude').html(location.latitude);
$('#longitude').html(location.longitude);
$('#ip').html(location.IPv4);
document.getElementById('varos').value = location.city;
}
});
</script>
<!--Get Milage-->
<script>
$(function () {
$.ajax({
type: "Get",
url: "../RoadRecords/ShowMileage?licencePlate=" + "#ViewBag.LicencePlate",
success: function (data) {
$("#mileageContainer").html(data);
},
error: function (response) {
console.log(response.responseText);
}
});
});
</script>
<script>
function ConvertDouble() {
var param = $("#Fueling").val();
if (param.indexOf(".") != -1) {
param = param.replace(".", ",");
}
$("#Fueling").val(param);
}
</script>
}
Here is my full view code. I had to remove validation js because the fueling input, if I type for example 12,5 or 12.5 I got error message, so I removed it, and because of the Culture thing it's work with commas (I am from Hungary), and in the javascript I replace the dot with comma if the user type dot instead of comma.
You can add RegularExpression and ErrorMessage in your property to add rules and custom ErrorMessage
[Display(Name = "Tankolás")]
[RegularExpression(#"^[0-9]*$",ErrorMessage = "You can use numbers only")]
public double? Fueling { get; set; }
View
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}

how to display data in edit modal with thymleaf

I want to populate the data in my table when an edit button is clicked, I have already displayed those data in a table with a button corresponding to each row and when I click the button,I want the edti modal popup to populate the information in that row, the popup modal is displayed when I click on it but it is blank. No data is populated in it. I don't really know how to go about it.
Here is the code
Data class
#Entity
#Data
#NoArgsConstructor
#AllArgsConstructor
public class Country {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String code;
private String capital;
private String description;
private String nationality;
private String continent;
#OneToMany(mappedBy = "country")
private List<State> states;
}
here is my controller
#Controller
public class CountryController {
#Autowired
private CountryService countryService;
#GetMapping("/countries")
public String getCountries(Model model) {
List<Country> countryList = countryService.getAllCountries();
model.addAttribute("countries",countryList);
return "country";
}
#PostMapping("/countries/addNew")
public String saveInfo(Country country){
countryService.saveCountryInfo(country);
return "redirect:/countries";
}
#GetMapping("/country/{id}")
public String findById(#PathVariable Long id, ModelMap modelMap) {
modelMap.put("id", id);
Country country = new Country();
country.setId(id);
country.setCapital(country.getCapital());
country.setCode(country.getCode());
country.setContinent(country.getContinent());
country.setDescription(country.getDescription());
country.setNationality(country.getNationality());
modelMap.put("country", country);
return "country";
}
}
Here is my html page
<section class="section dashboard">
<div class="row">
<!-- Left side columns -->
<div class="row">
<div class="col-lg-9 col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<!-- Image background -->
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addModal" data-whatever="#mdo">Add A Country</button>
<h1>List of Country</h1>
<table class="table">
<thead>
<tr>
<th>Id</th>
<th>Code</th>
<th>Capital</th>
<th>Description</th>
<th>Nationality</th>
<th>Continent</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr th:each="country:${countries}">
<td th:text="${country.getId}"></td>
<td th:text="${country.getCode}"></td>
<td th:text="${country.getCapital}"></td>
<td th:text="${country.getDescription}"></td>
<td th:text="${country.getNationality}"></td>
<td th:text="${country.getContinent}"></td>
<td>
<div class="btn-group">
<a th:href="#{/country/{id} (id=${country.getId})}" class="btn btn-primary"data-bs-toggle="modal" data-bs-target="#editModal" data-whatever="#mdo">Edit</a>
</div>
</td>
</tr>
</tbody>
</table>
</div><!-- End of Image background -->
</div><!-- End Left side columns -->
</div>
</div>
</div>
</section>
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="editModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editModalLabel">Update Country</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form th:objec="${country}" th:action="#{/country/update}" method="put">
<div class="form-group">
<label for="idEdit" class="col-form-label">Id:</label>
<input type="text" class="form-control" id="idEdit" name="id" th:value="*{id}">
</div>
<div class="form-group">
<label for="codeEdit" class="col-form-label">Code:</label>
<input type="text" class="form-control" id="codeEdit" name="code" th:value="*{code}">
</div>
<div class="form-group">
<label for="capitalEdit" class="col-form-label">Capital:</label>
<input type="text" class="form-control" id="capitalEdit" name="capital" th:value="*{capital}">
</div>
<div class="form-group">
<label for="descriptionEdit" class="col-form-label">Description:</label>
<input type="text" class="form-control" id="descriptionEdit" name="description" th:value="*{description}">
</div>
<div class="form-group">
<label for="nationalityEdit" class="col-form-label">Nationality:</label>
<input type="text" class="form-control" id="nationalityEdit" name="nationality" th:value="*{nationality}">
</div>
<div class="form-group">
<label for="continentEdit" class="col-form-label">Continent:</label>
<input type="text" class="form-control" id="continentEdit" name="continent" th:value="*{continent}">
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>

How can I create registration page without refreshing in Asp.Net MVC with Razor?

I need to get advice about in Registration Page in Asp.net MVC5 and razor page.
what is the best way for it:
My scenario is I have a registration process in three-step :
In the First Step, the client enters a username and captcha.
In the Second Phase client Enter the Phone number and send SMS by Identity.
If the Entered validation code was code the confirmation message and welcome page appears.
An easy way is we can make a three action result by the separate razor view.
But the problem is I need to do the noted process without any page refreshing.
what is the best way to do it?
Thanks a lot.
I would solve your task with following steps
Download jquery.unobtrusive-ajax.js from here and add a link in your layout.cshtml
create a Components folder in your pages folder
create a Register folder in your Components folder
add a file for your dto
RegisterDto.cs
public class RegisterDto
{
public string Email { get; set; }
public string FirstName { get; set; }
public string SurName { get; set; }
public string Phone { get; set; }
public string Validation { get; set; }
}
create your first form.
I created a new form in the index.cshtml. Here you can see, that I'm using ajax for handling the form. Use a container for replacing with your viewcomponents. In my example, my DOM Object is "content".
index.cshtml
<div id="content">
<div class="col-6">
<form method="post" data-ajax="true" data-ajax-method="post" asp-page="/Index" asp-page-handler="SubPage1" data-ajax-update="#content">
<div class="form-group">
<label asp-for="RegisterDto.Email"></label>
<input asp-for="RegisterDto.Email" class="form-control" />
</div>
<div class="form-group">
<label asp-for="RegisterDto.FirstName"></label>
<input asp-for="RegisterDto.FirstName" class="form-control" />
</div>
<div class="form-group">
<label asp-for="RegisterDto.SurName"></label>
<input asp-for="RegisterDto.SurName" class="form-control" />
</div>
<button class="btn btn-success" type="submit">next</button>
</form>
</div>
Create a new ViewComponentClass. Over the page-parameter you can switch between pages, and the registerDto is your model you can pass between pages.
RegisterViewComponent.cs
public class RegisterViewComponent : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync(string Page, RegisterDto registerDto)
{
return View(Page, registerDto);
}
}
create your views in your viewcomponent.
SubPage1.cshtml
<div class="col-6">
<form method="post" data-ajax="true" data-ajax-method="post" asp-page-handler="SubPage2" data-ajax-update="#content">
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control disabled" />
</div>
<div class="form-group">
<label asp-for="FirstName"></label>
<input asp-for="FirstName" class="form-control disabled" />
</div>
<div class="form-group">
<label asp-for="SurName"></label>
<input asp-for="SurName" class="form-control disabled" />
</div>
<div class="form-group">
<label asp-for="Phone"></label>
<input asp-for="Phone" class="form-control" />
</div>
<button class="btn btn-success" type="submit">next</button>
</form>
SubPage2.cshtml
<div class="col-6">
<form method="post" data-ajax="true" data-ajax-method="post" asp-page-handler="SubPage3" data-ajax-update="#content">
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control disabled" />
</div>
<div class="form-group">
<label asp-for="FirstName"></label>
<input asp-for="FirstName" class="form-control disabled" />
</div>
<div class="form-group">
<label asp-for="SurName"></label>
<input asp-for="SurName" class="form-control disabled" />
</div>
<div class="form-group">
<label asp-for="Phone"></label>
<input asp-for="Phone" class="form-control disabled" />
</div>
<div class="form-group">
<label asp-for="Validation"></label>
<input asp-for="Validation" class="form-control" />
</div>
<button class="btn btn-success" type="submit">Done</button>
</form>
</div>
default.cshtml
<h1>done</h1>
done!

Neither BindingResult nor plain target object for bean name available as request attribute when trying to load a bootstrap modal element

In my JSP im trying to load a bootstrap modal in order to save and edit entities with relevant spring controller methods and model attributes. But when I add this modal i'm getting the following errors. When the tabs are changed, following request is passed to the spring controller which then pass a modal attribute to the view and if thats true the relevant modal shown.
http://localhost:8080/admin/setting/systemRole/load
The error on tomcat log :
DEBUG org.springframework.web.servlet.DispatcherServlet - Could not complete request
org.apache.jasper.JasperException: An exception occurred processing JSP page /WEB-INF/jsp/settings.jsp at line 181
178: <form:form method="post" modelAttribute="user" action="save">
179: <div class="form-group">
180: <label class="col-form-label">User Name</label>
181: <form:input type="text" required="required" class="form-control" path="username"/>
182: <h6 class="fieldError"><form:errors path="username"/></h6>
183: </div>
184: <div class="form-group">
But it works fine for the following request when i change the tab to the users.
http://localhost:8080/admin/setting/systemUser/load
When I remove the code of the modal from the code, the other parts of the UI work fine.
The view (settings.jsp):
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%# taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<jsp:include page="header_new.jsp"/>
<div class="page-title-area">
<div class="container-fluid">
<div class="row">
<div class="col-sm-11 col-sm-offset-1 page-title-section">
<h2 class="page-title">
<span>Settings</span>
</h2>
<ul class="page-title__nav common-list nav nav-tabs" style="margin-bottom: -5px">
<li <c:if test="${userTabActive}"> class="active" </c:if>><a data-toggle="tab"
onclick="loadUsers()">Users</a></li>
<li <c:if test="${roleTabActive}"> class="active" </c:if>><a data-toggle="tab"
onclick="loadRoles()">Roles</a></li>
</ul>
</div>
</div>
</div>
</div>
<script>
function loadUsers() {
window.location = '/admin/setting/systemUser/load';
}
function loadRoles() {
window.location = '/admin/setting/systemRole/load';
}
$(document).ready(function () {
$('#usersTable').DataTable({})
$('#rolesTable').DataTable({})
});
function loadUser(id) {
window.location = 'loadUser?id=' + id;
}
function loadRole(id) {
window.location = 'loadRole?id=' + id;
}
function deleteUser(id) {
$('#user-id').val(id);
$('#userDeleteModal').modal("show");
}
var checkPasswords = function () {
if (document.getElementById('password').value ==
document.getElementById('confirm-password').value) {
document.getElementById('passwordsMatchMessage').style.color = 'green';
document.getElementById('passwordsMatchMessage').innerHTML = 'Passwords are matching';
document.getElementById("submitButton").disabled = false;
} else {
document.getElementById('passwordsMatchMessage').style.color = 'red';
document.getElementById('passwordsMatchMessage').innerHTML = 'Passwords are not matching';
document.getElementById("submitButton").disabled = true;
}
}
</script>
<c:if test="${loadUserModal}">
<script>
window.alert("user edit modal");
$("#userSaveModal").modal()
document.getElementById('userModalLabel').innerHTML = 'Edit User';
document.getElementById('password').value = '';
</script>
</c:if>
<c:if test="${saveUser}">
<script>
window.alert("user save modal");
$("#userSaveModal").modal()
document.getElementById('userModalLabel').innerHTML = 'Save User';
</script>
</c:if>
<c:if test="${loadRoleModal}">
<script>
window.alert("role modal");
$("#roleSaveModal").modal()
document.getElementById('roleModalLabel').innerHTML = 'Save Role';
</script>
</c:if>
<!-- Begin page content -->
<div class="container-fluid">
<div class="row">
<jsp:include page="components/common/sidemenu.jsp">
<jsp:param name="activeTab" value="settings"/>
</jsp:include>
<div class="tab-content">
<div id="merchants" class="tab-pane fade active">
<c:if test="${errorView ne 'E1020'}">
<div class="col-md-11 col-md-offset-1">
<div class="page-card" style="padding-right: 20px;margin-left: 20px;margin-top: 20px">
</div>
</div>
</c:if>
</div>
</div>
</div>
</div>
<c:if test="${viewUsers}">
<div class="tab-content">
<div class="tab-pane fade in active">
<div class="container-fluid">
<div style="padding-top: 10px; padding-right: 20px">
<button type="button" class="btn btn-primary" style="float: right;" onclick="loadUser(0)"><i
class="fa fa-plus" style="margin-right: 5px"></i>New User
</button>
</div>
<div class="row">
<div class="col-md-11 col-md-offset-1">
<div class="page-card">
<div class="page-card__body">
<div class="table-responsive">
<table id="usersTable" class="table table-bordered table-striped dataTable">
<thead>
<tr>
<th>User Name</th>
<th>Name</th>
<th>Status</th>
<th>Role</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<c:forEach items="${users}" var="user">
<tr>
<td>${user.username}</td>
<td>${user.name}</td>
<td>${user.state}</td>
<td>${user.role.roleName}</td>
<td>
<button type="button" class="btn btn-primary" data-toggle="modal"
onclick="loadUser('${user.id}')">
<i class="fa fa-edit"></i> Edit
</button>
<button type="button" data-toggle="modal" id="delete"
onclick="deleteUser('${user.id}')" name="delete"
class="btn btn-danger">
<i class="fa fa-trash-o"></i> Delete
</button>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</c:if>
<c:if test="${viewRoles}">
<div class="tab-content">
<div class="tab-pane fade in active">
<div class="container-fluid">
<div style="padding-top: 10px; padding-right: 20px">
<button type="button" class="btn btn-primary" style="float: right;" onclick="loadRole(0)"><i
class="fa fa-plus" style="margin-right: 5px"></i>Add Role
</button>
</div>
<div class="row">
<div class="col-md-11 col-md-offset-1">
<div class="page-card">
<div class="page-card__body">
<div class="table-responsive">
<table id="rolesTable" class="table table-bordered table-striped dataTable">
<thead>
<tr>
<th>Name</th>
<th>Permissions</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<c:forEach items="${roles}" var="role">
<tr>
<td>${role.roleName}</td>
<td>
<a href="#" data-toggle="popover" data-container="body"
data-content="<c:forEach var="permission" items="${role.permissionList}">
${permission.name}
</c:forEach>">View Permissions</a>
</td>
<td>
<button type="button" class="btn btn-primary" data-toggle="modal"
onclick="loadRole('${role.id}')">
<i class="fa fa-edit"></i> Edit
</button>
<%--<button type="button" class="btn btn-primary" data-toggle="modal"--%>
<%--onclick="editRole('${role.id}','${role.roleName}')" ><i class="fa fa-edit"></i> Edit--%>
<%--</button>--%>
<%--<button type="button" data-toggle="modal" id="delete"--%>
<%--onclick="deleteRole('${role.id}')" name="delete" class="btn btn-danger">--%>
<%--<i class="fa fa-trash-o"></i> Delete--%>
<%--</button>--%>
</td>
</tr>
</c:forEach>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</c:if>
<div class="modal fade" id="userDeleteModal" tabindex="-1" role="dialog" aria-labelledby="userDeleteModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="modalLabel">Delete Record</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Are you sure you need to remove this record ?
</div>
<form id="systemUserDeleteForm" method="post" class="w3-margin" action="remove">
<input style="visibility: hidden !important;" id="user-id" name="id">
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary">Delete</button>
</div>
</form>
</div>
</div>
</div>
<div class="modal fade" id="userSaveModal" tabindex="-1" role="dialog" aria-labelledby="userSaveModalLabel"
aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<div class="col-md-4">
<h5 class="modal-title" id="userModalLabel"></h5>
</div>
<div class="col-md-8">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
<div class="modal-body">
<form:form method="post" modelAttribute="user" action="save">
<div class="form-group">
<label class="col-form-label">User Name</label>
<form:input type="text" required="required" class="form-control" path="username"/>
<h6 class="fieldError"><form:errors path="username"/></h6>
</div>
<div class="form-group">
<label for="name" class="col-form-label">Name</label>
<form:input type="text" required="required" class="form-control" path="name"/>
<h6 class="fieldError"><form:errors path="name"/></h6>
</div>
<div class="form-group">
<label>Role</label>
<form:select class="form-control"
required="required" path="role.id">
<c:forEach items="${roles}" var="role">
<form:option value="${role.id}" label="${role.roleName}" />
</c:forEach>
</form:select>
</div>
<div class="form-group">
<label for="state">Status</label>
<form:select class="form-control"
required="required" path="state">
<form:option value="ACTIVE" label="ACTIVE"/>
<form:option value="INACTIVE" label="INACTIVE"/>
</form:select>
</div>
<c:if test="${saveUser}">
<div class="form-group">
<label class="col-form-label">Password</label>
<form:input onkeyup='checkPasswords();' type="password" class="form-control"
path="password"/>
<h6 class="fieldError"><form:errors path="password"/></h6>
</div>
<div class="form-group">
<label class="col-form-label">Confirm Password</label>
<input onkeyup='checkPasswords();' type="password" class="form-control" />
</div>
<span id='passwordsMatchMessage'></span>
</c:if>
<c:if test="${not saveUser}">
<%--hidden input value is passed for editing record to avoid getting a null value for the password for user object--%>
<form:input type="hidden" path="password"/>
</c:if>
<form:input type="hidden" name="id" path="id"/>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" id="submitButton" class="btn btn-primary">Submit</button>
</div>
</form:form>
</div>
</div>
</div>
</div>
<div class="modal fade" id="roleSaveModal" tabindex="-1" role="dialog" aria-labelledby="roleSaveModalLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<div class="col-md-4" style="float: left">
<h5 class="modal-title" id="roleModalLabel"></h5>
</div>
<div class="col-md-8">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
</div>
<div class="modal-body">
<form:form method="post" modelAttribute="role" action="save">
<div class="form-group">
<label for="role-name" class="col-form-label">Role Name</label>
<form:input type="text" required="required" class="form-control" id="role-name"
path="roleName"/>
<h6 class="fieldError"><form:errors path="roleName"/></h6>
</div>
<div class="form-group">
<label class="col-form-label">Permissions</label>
<c:forEach items="${permissions}" var="permission">
<div class="check-box" style="padding-left: 20px">
<c:choose>
<c:when test="${permission.checked}">
<form:checkbox value="${permission.id}"
path="checkedPermissions" checked="checked"/>
<label style=" margin-left: 10px">${permission.name}</label>
</c:when>
<c:otherwise>
<form:checkbox value="${permission.id}"
path="checkedPermissions"/>
<label style=" margin-left: 10px">${permission.name}</label>
</c:otherwise>
</c:choose>
</div>
</c:forEach>
</div>
<form:input type="hidden" id="id" name="id" path="id"/>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form:form>
</div>
</div>
</div>
</div>
The users controller :
#Controller
#RequestMapping("/setting/systemUser")
public class SystemUserController {
private final static Logger logger = LoggerFactory.getLogger(SystemUserController.class);
#Autowired
#Qualifier("systemUserValidator")
private Validator validator;
#Autowired
private SystemUserService systemUserService;
#Autowired
private SystemRoleService systemRoleService;
#Autowired
private UserDetailsHelper userDetailsHelper;
#InitBinder
private void initBinder(WebDataBinder binder) {
binder.setValidator(validator);
}
#RequestMapping(value = "/load", method = RequestMethod.GET)
public String viewRoles(Model model) {
loadData(model);
return "settings";
}
#RequestMapping(value = "/save", method = RequestMethod.POST)
public String saveUser(Model model, #Validated #ModelAttribute("user") SystemUser user, BindingResult result) {
logger.info("User save/update request received [{}]", user.toString());
if (result.hasErrors()) {
model.addAttribute("users", systemUserService.getAllUsers());
model.addAttribute("roles", systemRoleService.getAllUserRoles());
model.addAttribute("loadUserModal", true);
return "settings";
}
systemUserService.saveSystemUser(user);
loadData(model);
return "settings";
}
#RequestMapping(value = "/remove", method = RequestMethod.POST)
public String deleteRole(Model model, #RequestParam("id") Long id) {
SystemUser user = systemUserService.getSystemUser(id);
logger.info("User remove request received [{}]", user.toString());
systemUserService.deleteUser(user);
loadData(model);
return "settings";
}
#RequestMapping(value = "/loadUser", method = RequestMethod.GET)
public String loadUser(Model model, #RequestParam("id") Long id) {
loadData(model);
model.addAttribute("user", systemUserService.getSystemUser(id));
model.addAttribute("loadUserModal", true);
if (id == 0){
model.addAttribute("saveUser", true);
}
model.addAttribute("userTabActive", true);
model.addAttribute("viewUsers", true);
return "settings";
}
private void loadData(Model model) {
model.addAttribute("userDetails", userDetailsHelper.getSystemUser().getUsername());
model.addAttribute("users", systemUserService.getAllUsers());
model.addAttribute("roles", systemRoleService.getAllUserRoles());
model.addAttribute("user", new SystemUser());
model.addAttribute("userTabActive", true);
model.addAttribute("viewUsers", true);
}
}
The roles controller :
#Controller
#RequestMapping("/setting/systemRole")
public class SystemRoleController {
#Autowired
#Qualifier("systemRoleValidator")
private Validator validator;
#Autowired
private SystemRoleService roleService;
#Autowired
private UserDetailsHelper userDetailsHelper;
#InitBinder
private void initBinder(WebDataBinder binder) {
binder.setValidator(validator);
}
#RequestMapping(value = "/load", method = RequestMethod.GET)
public String viewRoles(Model model) {
loadData(model);
return "settings";
}
#RequestMapping(value = "/save", method = RequestMethod.POST)
public String saveRole(Model model, #Validated #ModelAttribute("role") SystemRole role, BindingResult result) {
logger.info("Role save/update request received [{}]", role.toString());
if (result.hasErrors()) {
model.addAttribute("roles", roleService.getAllUserRoles());
model.addAttribute("permissions", roleService.getAllPermission());
model.addAttribute("loadRoleModal", true);
return "settings";
}
roleService.saveSystemRole(role);
loadData(model);
return "settings";
}
#RequestMapping(value = "/delete", method = RequestMethod.POST)
public String deleteRole(Model model, #RequestParam("id") Long id) {
roleService.deleteRole(roleService.getUserRole(id));
loadData(model);
return "settings";
}
#RequestMapping(value = "/loadRole", method = RequestMethod.GET)
public String loadRole(Model model, #RequestParam("id") Long id) {
loadData(model);
model.addAttribute("loadRoleModal", true);
model.addAttribute("role", roleService.getUserRole(id));
SystemRole role = roleService.getUserRole(id);
model.addAttribute("permissions", roleService.getAllPermission(role));
return "settings";
}
private void loadData(Model model) {
model.addAttribute("roles", roleService.getAllUserRoles());
model.addAttribute("permissions", roleService.getAllPermission());
model.addAttribute("role", new SystemRole());
model.addAttribute("userDetails", userDetailsHelper.getSystemUser().getUsername());
model.addAttribute("roleTabActive", true);
model.addAttribute("viewRoles", true);
}
}
SystemRole model class :
#Entity(name = "system_user_role")
public class SystemRole implements Serializable {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private long id;
#Column(name = "name")
private String roleName;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
#JoinTable(name = "system_role_permission", joinColumns = {
#JoinColumn(name = "id", nullable = false)},
inverseJoinColumns = {#JoinColumn(name = "permission_id", nullable = false)})
private List<Permission> permissionList = new ArrayList<Permission>();
#Transient
private List<Long> checkedPermissions = new ArrayList<>();
public SystemRole() {
}
The HTML views (when the modals are removed):
This doesnt seem to load when the modal are added. And the delete modal seems to work fine. What could be going wrong in here?

When model is not valid, return to partial view inside a view, with error message using asp.net core

I´ve got a modal boostrap. I want to show the error of validation on boostrap modal. But when I leave the model empty and click on submit button Its just viewed as a standalone page.
Partial view:
#model WebApplication1.Models.Book
<form asp-controller="Home" asp-action="AddBook"
data-ajax="true" data-ajax-method="POST" data-ajax-mode="replace" data-ajax-update="#frmaddbook">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel">Header of Modal</h4>
</div>
<div class="modal-body form-horizontal" id="frmaddbook ">
<span class="alert-danger">
#Html.ValidationSummary()
</span>
<div class="row">
<div class="form-group">
<label asp-for="BookName" class="col-lg-3 col-sm-3 control-label"></label>
<div class="col-lg-6">
<input asp-for="BookName" class="form-control" />
<span asp-validation-for="BookName" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="BookDescription" class="col-lg-3 col-sm-3 control-label"></label>
<div class="col-lg-6">
<input asp-for="BookDescription" class="form-control" />
<span asp-validation-for="BookDescription" class="text-danger"></span>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-primary" value="Submit" />
</div>
Index View :
<div class="panel panel-primary">
<div class="panel-body">
<div class="btn-group">
<a class="btn btn-primary marginbutoon" id="showBookgroup" data-toggle="modal" asp-action="AddBook"
data-target="#modal-book">
<i class="glyphicon glyphicon-plus"></i>
Add Book
</a>
</div>
</div>
i use this libraries at top of index view:
jquery.unobtrusive-ajax.min.js
jquery.validate.unobtrusive.min.js
and use at the bottom of index view:
<script src="~/js/book-index.js"></script>
book-index.js:
(function ($) {
function Home() {
var $this = this;
function initilizeModel() {
$("#modal-book").on('loaded.bs.modal', function (e) {
}).on('hidden.bs.modal', function (e) {
$(this).removeData('bs.modal');
});
}
$this.init = function () {
initilizeModel();
}
}
$(function () {
var self = new Home();
self.init();
})
}(jQuery))
Controller:
[HttpGet]
public IActionResult AddBook()
{
var b = new Book();
return PartialView("_AddBook", b);
}
[HttpPost]
[ValidateAntiForgeryToken]
//[HandleError]//not in core
public IActionResult AddBook(Book model)
{
if (ModelState.IsValid)
{
return RedirectToAction("Index");
}
return PartialView("_AddBook", model);
}
Model :
public class Book
{
[Key]
public int BookId { get; set; }
[Display(Name = "Book Name :")]
[Required(ErrorMessage = "Enter Book Name Please ")]
public string BookName { get; set; }
[Display(Name = "Book Description")]
[Required(ErrorMessage = "Enter Book Description Please ")]
public string BookDescription { get; set; }
}
My code is shown above. How can i show validation error in modal partial view ?
You can set the Id of form as the data-ajax-update property value of the form , which is ajaxified. This value will be used as the jQuery selector when the result is received from the ajax call.
#model Book
<form asp-controller="Home" asp-action="AddBook" id="myform"
data-ajax="true" data-ajax-method="POST"
data-ajax-mode="replace" data-ajax-update="#myform">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel">Add Book</h4>
</div>
<div class="modal-body form-horizontal" id="frmaddbook ">
<span class="alert-danger">
#Html.ValidationSummary()
</span>
<div class="row">
<div class="form-group">
<label asp-for="BookName" class="col-sm-3 control-label"></label>
<div class="col-lg-6">
<input asp-for="BookName" class="form-control" />
<span asp-validation-for="BookName" class="text-danger"></span>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-primary" value="Submit" />
</div>
</form>
Now when you submit the form and model state validation fails, the action method code will return the partial view result with the validation error messages (generated by the validation helpers) and the jquery.unobtrusive-ajax.js library code will replace (because we specified that with data-ajax-mode="replace") the content of the result of the jquery selector #data-ajax-update (the form tag and it's inner contents) with the response coming back from the server.

Resources