Validation in ASP.NET MVC Syncfusion Grid component
1 Apr 202524 minutes to read
Validation is a crucial aspect of data integrity in any application. The ASP.NET MVC Grid component in Syncfusion® provides built-in support for easy and effective data validation. This feature ensures that the data entered or modified adheres to predefined rules, preventing errors and guaranteeing the accuracy of the displayed information.
Column validation
Column validation allows you to validate the edited or added row data before saving it. This feature is particularly useful when you need to enforce specific rules or constraints on individual columns to ensure data integrity. By applying validation rules to columns, you can display error messages for invalid fields and prevent the saving of erroneous data. This feature leverages the Form Validator component to perform the validation. You can define validation rules using the Columns.ValidationRules
property to specify the criteria for validating column values.
The following code example demonstrates how to define a validation rule for grid column:
@Html.EJS().Grid("grid").DataSource((IEnumerable<object>)ViewBag.DataSource).Height("348px").Columns(col =>
{
col.Field("OrderID").HeaderText("Order ID").IsPrimaryKey(true).Width("120").ValidationRules(new { required = "true"}).TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Add();
col.Field("CustomerID").HeaderText("Customer Name").Width("150").ValidationRules(new { required = "true", minLength=5 }).Add();
col.Field("Freight").HeaderText("Freight").Width("120").Format("C2").EditType("numericedit").TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).ValidationRules(new { required = "true", min=1, max=1000 }).Add();
col.Field("ShipCountry").HeaderText("Ship Country").EditType("dropdownedit").Width("150").ValidationRules(new { required = "true"}).Add();
}).EditSettings(edit => { edit.AllowAdding(true).AllowEditing(true).AllowDeleting(true).Mode(Syncfusion.EJ2.Grids.EditMode.Normal); }).Toolbar(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" }).Render()
public IActionResult Index()
{
ViewBag.DataSource = OrderDetails.GetAllRecords();
return View();
}
Custom validation
The Custom validation feature is used to define and enforce your own validation rules for specific columns in the Grid. This is achieved by leveraging the utilizing the Form Validator custom rules, you can enforce your desired validation logic and display error messages for invalid fields.
In the below demo, custom validation applied for CustomerID column.
@Html.EJS().Grid("grid").DataSource((IEnumerable<object>)ViewBag.DataSource).Height("348px").Columns(col =>
{
col.Field("OrderID").HeaderText("Order ID").IsPrimaryKey(true).Width("120").ValidationRules(new { required = "true"}).TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Add();
col.Field("CustomerID").HeaderText("Customer Name").Width("150").Add();
col.Field("Freight").HeaderText("Freight").Width("120").Format("C2").EditType("numericedit").TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).ValidationRules(new { required = "true", min=1, max=1000 }).Add();
col.Field("ShipCountry").HeaderText("Ship Country").EditType("dropdownedit").Width("150").ValidationRules(new { required = "true"}).Add();
}).Load("load").EditSettings(edit => { edit.AllowAdding(true).AllowEditing(true).AllowDeleting(true).Mode(Syncfusion.EJ2.Grids.EditMode.Normal); }).Toolbar(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" }).Render()
<script>
function load(args) {
var grid = document.getElementById("grid").ej2_instances[0];
grid.getColumnByField("CustomerID").validationRules = { required: true, minLength: [customFunction, 'Need atleast 5 letters'] };
}
function customFunction(args) {
return args['value'].length >= 5;
};
</script>
public IActionResult Index()
{
ViewBag.DataSource = OrdersDetails.GetAllRecords();
return View();
}
Custom validation based on dropdown change
The Custom validation feature in the Grid allows you to apply validation rules and messages to a column based on the value of another column in edit mode. This feature is particularly useful when you need to enforce specific validation criteria that depend on the selection made in a dropdown column.
In the following sample, dropdownlist edit type is used for the Role and Salary columns. Here, you can apply the custom validation in the Salary column based on the value selected in the Role column.
@{
var jobRole = new List<object>
{
new { role = "Team Lead" },
new { role = "Manager" },
new { role = "Engineer" },
new { role = "Sales" },
new { role = "Support" }
};
var salaryDetails = new List<object>
{
new { Salary = 6000 },
new { Salary = 17000 },
new { Salary = 18000 },
new { Salary = 26000 },
new { Salary = 25000 },
new { Salary = 40000 },
new { Salary = 35000 },
new { Salary = 55000 },
new { Salary = 65000 }
};
var roleDropDownList = new Syncfusion.EJ2.DropDowns.DropDownList() { DataSource = jobRole, Query = "new ej.data.Query()", Fields = new Syncfusion.EJ2.DropDowns.DropDownListFieldSettings() { Value = "role", Text = "role" }, AllowFiltering = true,Change="valueChange" };
var salaryDropDownList = new Syncfusion.EJ2.DropDowns.DropDownList() { DataSource = salaryDetails, Query = "new ej.data.Query()", Fields = new Syncfusion.EJ2.DropDowns.DropDownListFieldSettings() { Value = "Salary", Text = "Salary" }, AllowFiltering = true,Change="customFunction" };
}
@Html.EJS().Grid("grid").DataSource((IEnumerable<object>)ViewBag.DataSource).Height("348px").Columns(col =>
{
col.Field("EmployeeID").HeaderText("Employee ID").IsPrimaryKey(true).Width("120").ValidationRules(new { required = "true"}).TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Add();
col.Field("Role").HeaderText("Role").EditType("dropdownedit").Width("150").Edit(new { @params = roleDropDownList }).Add();
col.Field("Salary").HeaderText("Salary").EditType("dropdownedit").Width("150").Edit(new { @params = salaryDropDownList }).Add();
col.Field("Address").HeaderText("Address").Width("150").ValidationRules(new { required = "true"}).Add();
}).Load("load").ActionBegin("actionBegin").EditSettings(edit => { edit.AllowAdding(true).AllowEditing(true).AllowDeleting(true).Mode(Syncfusion.EJ2.Grids.EditMode.Normal); }).Toolbar(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" }).Render()
<script>
window.role = '';
function customFunction(args) {
var grid = document.getElementById("grid").ej2_instances[0];
var formObject = grid.editModule.formObj.element['ej2_instances'][0];
let salary = parseInt(args.value)
switch (window['role']) {
case 'Sales':
if ((salary >= 5000) && (salary < 15000))
return true;
else
formObject.rules['Salary']['required'][1] = 'Please enter valid Sales Salary >=5000 and< 15000';
break;
case 'Support':
if ((salary >= 15000 && salary < 19000))
return true;
else
formObject.rules['Salary']['required'][1] = 'Please enter valid Support Salary >=15000 and < 19000';
break;
case 'Engineer':
if ((salary >= 25000 && salary < 30000))
return true;
else
formObject.rules['Salary']['required'][1] = 'Please enter valid Engineer Salary between >=25000 and < 30000';
break;
case 'Team Lead':
if ((salary >= 30000) && (salary < 50000))
return true;
else
formObject.rules['Salary']['required'][1] = 'Please enter valid TeamLead Salary >= 30000 and < 50000';
break;
case 'Manager':
if ((salary >= 50000) && (salary < 70000))
return true;
else
formObject.rules['Salary']['required'][1] = 'Please enter valid Manager Salary >=50000 and < 70000';
break;
}
return false;
}
function valueChange(args) {
var grid = document.getElementById("grid").ej2_instances[0];
window.role = args.value.toString();
var formObject = grid.editModule.formObj.element['ej2_instances'][0];
switch ( window.role) {
case 'Sales':
formObject.rules['Salary']['required'][1] = 'Please enter valid Sales Salary >=5000 and< 15000';
break;
case 'Support':
formObject.rules['Salary']['required'][1] = 'Please enter valid Support Salary >=15000 and < 19000';
break;
case 'Engineer':
formObject.rules['Salary']['required'][1] = 'Please enter valid Engineer Salary between >=25000 and < 30000';
break;
case 'Team Lead':
formObject.rules['Salary']['required'][1] = 'Please enter valid TeamLead Salary >= 30000 and < 50000';
break;
case 'Manager':
formObject.rules['Salary']['required'][1] = 'Please enter valid Manager Salary >=50000 and < 70000';
break;
}
}
function load() {
var grid = document.getElementById("grid").ej2_instances[0];
var column = grid.getColumnByField('Salary');
column.validationRules = {
required: [customFunction,'Please enter valid salary'],
};
}
function actionBegin(args){
window.role = args.rowData.Role;
}
</script>
public IActionResult Index()
{
ViewBag.DataSource = OrderDetails.GetAllRecords();
return View();
}
Custom validation for numeric column
Custom validation for a numeric column Grid is useful when you want to enforce specific validation rules on numeric values in a column. This allows you to define your own validation logic and display custom error messages when the you enters invalid data.
In the following example, custom validation functions, namely customFunction and customFunctionOne, are defined to check the entered numeric value against your validation criteria. Then, the grid column is configured with the appropriate validation settings using the freightRules object, specifying the custom validation functions along with corresponding error messages. Additionally, the Change event of the numeric column is bound to the validate
method of the form element through the edit params. This enables you to trigger validation and display error messages whenever the you modifies the value in the NumericTextBox.
@Html.EJS().Grid("grid").DataSource((IEnumerable<object>)ViewBag.DataSource).Height("348px").Columns(col =>
{
col.Field("OrderID").HeaderText("Order ID").IsPrimaryKey(true).Width("120").ValidationRules(new { required = "true"}).TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Add();
col.Field("CustomerID").HeaderText("Customer Name").Width("150").Add();
col.Field("Freight").HeaderText("Freight").Width("120").Format("C2").EditType("numericedit").TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Edit(new { @params = new Syncfusion.EJ2.Inputs.NumericTextBox() { Change= "onChange" }}).Add();
col.Field("ShipCountry").HeaderText("Ship Country").EditType("dropdownedit").Width("150").ValidationRules(new { required = "true"}).Add();
}).Load("load").EditSettings(edit => { edit.AllowAdding(true).AllowEditing(true).AllowDeleting(true).Mode(Syncfusion.EJ2.Grids.EditMode.Normal); }).Toolbar(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" }).Render()
<script>
function load(args) {
var grid = document.getElementById("grid").ej2_instances[0];
grid.getColumnByField("Freight").validationRules = { required: true, min: [customFunctionOne, 'Please enter a value greater than 1'], max: [customFunction, 'Please enter a value less than 1000'] };
}
function customFunction(args) {
return args['value'].length >= 5;
};
function customFunction (args) {
return (args['value'] <= 1000);
}
function customFunctionOne (args) {
return (args['value'] >= 1);
}
function onActionComplete(args) {
if (args.requestType === "beginEdit" || args.requestType === "add") {
formElement = args.form;
}
}
function onChange() {
formElement['ej2_instances'][0].validate();
}
</script>
public IActionResult Index()
{
ViewBag.DataSource = OrderDetails.GetAllRecords();
return View();
}
Dynamically add or remove validation rules from the form
You can dynamically add or remove validation rules from input elements within a form. This feature is particularly useful when you need to adjust the validation rules based on different scenarios or dynamically changing data.
To add validation rules dynamically to an input element, you can use the addRules
method. This method enables you to add validation rules to the corresponding input element based on the name attribute.
The following example to demonstrates how to dynamically add or remove a required validation rule for an input field based on a CheckBox selection:
<div style='padding-bottom:20px'>
@Html.EJS().CheckBox("checkbox").Label("Enable/Disable validation rule for customerID coulumn").Checked(true).Render()
</div>
@Html.EJS().Grid("grid").DataSource((IEnumerable<object>)ViewBag.DataSource).Height("348px").Columns(col =>
{
col.Field("OrderID").HeaderText("Order ID").IsPrimaryKey(true).Width("120").ValidationRules(new { required = "true"}).TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Add();
col.Field("CustomerID").HeaderText("Customer Name").Width("150").Add();
col.Field("Freight").HeaderText("Freight").Width("120").Format("C2").EditType("numericedit").TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).ValidationRules(new { required = "true", min=1, max=1000 }).Add();
col.Field("ShipCountry").HeaderText("Ship Country").EditType("dropdownedit").Width("150").ValidationRules(new { required = "true"}).Add();
}).ActionComplete("actionComplete").EditSettings(edit => { edit.AllowAdding(true).AllowEditing(true).AllowDeleting(true).Mode(Syncfusion.EJ2.Grids.EditMode.Normal); }).Toolbar(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" }).Render()
<script>
function actionComplete(args) {
var grid = document.getElementById("grid").ej2_instances[0];
var formObject = grid.editModule.formObj;
var customerIDRules = {
required: true,
minLength: [5, 'Customer ID should have a minimum length of 5 characters'],
};
if (args.requestType === 'beginEdit' || args.requestType === 'add') {
var checkbox = document.getElementById("checkbox").ej2_instances[0];
if (checkbox.checked) {
formObject.addRules('CustomerID', customerIDRules);
}
}
}
</script>
public IActionResult Index()
{
ViewBag.DataSource = OrderDetails.GetAllRecords();
return View();
}
To remove an existing validation rule from an input element, you can use the
removeRules
method.
Change the position of validation error message
By default, the validation error message in Grid is displayed below the input field. However, you have an option to customize its position and display it in a different location. This feature is particularly useful when you want to align the error message according to your application’s design and layout.
To change the position of the validation error message in Grid, you can utilize the CustomPlacement
event. This event allows you to define a custom logic to position the error message at the desired location.
Here’s an example that demonstrates how to change the position of the validation error message to the top of the input field:
@Html.EJS().Grid("grid").DataSource((IEnumerable<object>)ViewBag.DataSource).ActionComplete("onActionComplete").Height("348px").Columns(col =>
{
col.Field("OrderID").HeaderText("Order ID").IsPrimaryKey(true).Width("120").ValidationRules(new { required = true }).TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Add();
col.Field("CustomerID").HeaderText("Customer Name").Width("150").ValidationRules(new { required = true, minLength = 3 }).Add();
col.Field("Freight").HeaderText("Freight").Format("C2").EditType("numericedit").ValidationRules(new { required = true, min = 1, max=1000 }).Width("150").Add();
col.Field("ShipCountry").HeaderText("Ship Country").EditType("dropdownedit").ValidationRules(new { required = true }).Width("150").Add();
}).AllowPaging().EditSettings(edit => { edit.AllowAdding(true).AllowEditing(true).AllowDeleting(true).Mode(Syncfusion.EJ2.Grids.EditMode.Dialog).Template("#dialogtemplate"); }).Toolbar(new List<string>() { "Add", "Edit", "Delete", "Update", "Cancel" }).Render()
<script>
function onActionComplete(args) {
if (args.requestType == "beginEdit" || args.requestType == "add") {
var grid = document.getElementById("grid").ej2_instances[0];
var valueError = ej.grids.getObject('valErrorPlacement', grid.editModule).bind(grid.editModule);
grid.editModule.formObj.customPlacement = (input, error) => {
valueError(input, error);
var element = document.getElementById(input.name + '_Error');
var tooltipWidth = element.offsetWidth;
var inputElement = null;
if (document.querySelector('#' + grid.element.id + input.name)) {
inputElement = document.querySelector('#' +grid.element.id + input.name);
} else if (document.querySelector('#' + input.name)) {
inputElement = document.querySelector('#' + input.name);
}
var inputPosition = inputElement.getBoundingClientRect();
var leftPosition = (inputPosition.left - tooltipWidth - 16).toString() + 'px'; //for right side
var topPosition = inputPosition.top.toString() + 'px';
element.style.left = leftPosition;
element.style.top = topPosition;
element.style.position = 'fixed';
}
}
}
</script>
<style>
.e-gridform .e-arrow-tip.e-tip-top {
transform: rotate(95deg);
left: 121px;
top: 13px;
}
</style>
public IActionResult Index()
{
ViewBag.DataSource =OrderDetails.GetAllRecords();
return View();
}
Show custom error message while performing CRUD actions
While performing CRUD actions in the Syncfusion ASP.NET MVC Grid, errors may occur due to various reasons such as validation failures, network issues, or server-side exceptions. Handling these errors effectively is essential for providing meaningful error messages when an operation fails.
To achieve this, you can use the ActionFailure event, which is triggered when an action (such as update, delete, or insert) fails. This event allows you to retrieve the error message from the server response and display it in the UI.
The following sample demonstrates how to retrieve and display error messages in the Syncfusion ASP.NET MVC Grid:
<div id="errorMessage" class="error-message" style="display:none; color: red; text-align: center"></div>
@*Replace xxxx with your actual port number*@
@Html.EJS().Grid("grid").DataSource(ds => ds.Url("https://localhost:xxxx/Grid/UrlDatasource")
.InsertUrl("https://localhost:xxxx/Grid/Insert")
.UpdateUrl("https://localhost:xxxx/Grid/Update")
.RemoveUrl("https://localhost:xxxx/Grid/Remove")
.Adaptor("UrlAdaptor")).Columns(col =>
{
col.Field("OrderID").HeaderText("Order ID").IsPrimaryKey(true).Width("150")
.TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Add();
col.Field("CustomerID").HeaderText("Customer Name").Width("150").Add();
col.Field("Freight").HeaderText("Freight").Width("150").Format("C2")
.TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Add();
col.Field("ShipCity").HeaderText("Ship City").Width("150").Add();
}).EditSettings(edit => edit.AllowAdding(true).AllowEditing(true).AllowDeleting(true)).Toolbar(new List<string>
{ "Add", "Edit", "Delete", "Update", "Cancel" }).Height(320).ActionFailure("actionFailure").AllowPaging(true).Render()
<script>
function actionFailure(args) {
let errorDiv = document.getElementById("errorMessage");
if (args.error && args.error[0] && args.error[0].error) {
let response = args.error[0].error;
response.text().then(errorMessage => {
// Extract meaningful error message.
let match = errorMessage.match(/<h3>HTTP Error 400.*? - (.*?)<\/h3>/);
if (match && match[1]) {
errorDiv.innerText = match[1]; // Display only the relevant error message.
} else {
errorDiv.innerText = "An unexpected error occurred.";
}
}).catch(() => {
errorDiv.innerText = "An unexpected error occurred.";
});
} else {
errorDiv.innerText = "An unexpected error occurred.";
}
}
</script>
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using Syncfusion.EJ2.Base;
using UrlAdaptor.Models;
namespace UrlAdaptor.Controllers
{
public class GridController : Controller
{
private static List<OrdersDetails> order = OrdersDetails.GetAllRecords();
/// <summary>
/// Handles the HTTP POST request to retrieve data from the data source based on the DataManagerRequest.
/// Supports filtering,searching, sorting, and paging operations (skip and take).
/// </summary>
/// <param name="dataManager">Contains the filtering, sorting, and paging options requested by the client.</param>
/// <returns>Returns the filtered,searched, sorted, and paginated data along with the total record count.</returns>
[HttpPost]
public ActionResult UrlDatasource(DataManagerRequest dataManager)
{
// Retrieve data source and convert to queryable.
IEnumerable<OrdersDetails> DataSource = order;
// Initialize DataOperations instance.
DataOperations queryableOperation = new DataOperations();
// Handling searching operation.
if (dataManager.Search != null && dataManager.Search.Count > 0)
{
DataSource = queryableOperation.PerformSearching(DataSource, dataManager.Search);
}
// Handling filtering operation.
if (dataManager.Where != null && dataManager.Where.Count > 0)
{
foreach (var condition in dataManager.Where)
{
foreach (var predicate in condition.predicates)
{
DataSource = queryableOperation.PerformFiltering(DataSource, dataManager.Where, predicate.Operator);
}
}
}
// Handling sorting operation.
if (dataManager.Sorted != null && dataManager.Sorted.Count > 0)
{
DataSource = queryableOperation.PerformSorting(DataSource, dataManager.Sorted);
}
// Get the total count of records.
int totalRecordsCount = DataSource.Count();
// Handling paging operation.
if (dataManager.Skip != 0)
{
DataSource = queryableOperation.PerformSkip(DataSource, dataManager.Skip);
}
if (dataManager.Take != 0)
{
DataSource = queryableOperation.PerformTake(DataSource, dataManager.Take);
}
// Return result and total record count.
return dataManager.RequiresCounts ? Json(new { result = DataSource, count = totalRecordsCount }) : Json(DataSource);
}
/// <summary>
/// Inserts a new data item into the data collection.
/// </summary>
/// <param name="newRecord">It contains the new record detail which is need to be inserted.</param>
/// <returns>Returns void.</returns>
[HttpPost]
[Route("Grid/Insert")]
public ActionResult Insert(CRUDModel<OrdersDetails> newRecord)
{
if (newRecord != null)
{
var existingOrder = order.FirstOrDefault(or => or.OrderID == newRecord.value.OrderID);
if (existingOrder == null)
{
order.Insert(0, newRecord.value);
return Json(new { success = true, message = "Order added successfully.", data = newRecord });
}
else
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Duplicate values cannot be inserted.");
}
}
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Invalid data received.");
}
/// <summary>
/// Update a existing data item from the data collection.
/// </summary>
/// <param name="updateRecord">It contains the updated record detail which is need to be updated.</param>
/// <returns>Returns void.</returns>
[HttpPost]
[Route("Grid/Update")]
public ActionResult Update(CRUDModel<OrdersDetails> updateRecord)
{
if (updateRecord.value == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "Invalid data received.");
}
// Corrected condition to validate OrderID range.
if (updateRecord.value.OrderID < 10010 || updateRecord.value.OrderID > 10030)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "OrderID must be between 10010 and 10030 to update.");
}
var data = OrdersDetails.GetAllRecords().FirstOrDefault(or => or.OrderID == updateRecord.value.OrderID);
if (data == null)
{
return new HttpStatusCodeResult(HttpStatusCode.NotFound, "Order not found.");
}
// Update the existing record.
data.CustomerID = updateRecord.value.CustomerID;
data.Freight = updateRecord.value.Freight;
data.ShipCity = updateRecord.value.ShipCity;
data.ShipCountry = updateRecord.value.ShipCountry;
return Json(new { success = true, message = "Order updated successfully.", data = updateRecord });
}
/// <summary>
/// Remove a specific data item from the data collection.
/// </summary>
/// <param name="value">It contains the specific record detail which is need to be removed.</param>
/// <return>Returns void.</return>
[HttpPost]
[Route("Grid/Remove")]
public ActionResult Remove(CRUDModel<OrdersDetails> value)
{
int orderId = int.Parse(value.key.ToString());
if (orderId < 10031 || orderId > 10045)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "OrderID must be between 10031 and 10045 to delete.");
}
var data = OrdersDetails.GetAllRecords().FirstOrDefault(orderData => orderData.OrderID == orderId);
OrdersDetails.GetAllRecords().Remove(data);
return Json(new { success = true, message = "Order deleted successfully." });
}
}
public class CRUDModel<T>
{
public string action { get; set; }
public string keyColumn { get; set; }
public object key { get; set; }
public T value { get; set; }
public List<T> Added { get; set; }
public List<T> Changed { get; set; }
public List<T> Deleted { get; set; }
public IDictionary<string, object> @params { get; set; }
}
}