Skip to content

945064: Show custom error #4095

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 58 additions & 1 deletion ej2-asp-core-mvc/grid/EJ2_ASP.MVC/data-binding/remote-data.md
Original file line number Diff line number Diff line change
Expand Up @@ -698,4 +698,61 @@ On remote data binding, all grid actions such as paging, sorting, editing, group
{% highlight c# tabtitle="Offline.cs" %}
{% include code-snippet/grid/data-binding/offline/offline.cs %}
{% endhighlight %}
{% endtabs %}
{% endtabs %}

## Fetch result from the DataManager query using external button

By default, Syncfusion ASP.NET MVC Grid automatically binds a remote data source using the `DataManager`. However, in some scenarios, you may need to fetch data dynamically from the server using a query triggered by an external button. This approach allows greater control over when and how data is loaded into the Grid.

To achieve this, you can use the `executeQuery` method of `DataManager` with a `Query` object. This method allows you to run a custom query and retrieve results dynamically.

The following example demonstrates how to fetch data from the server when an external button is clicked and display a status message indicating the data fetch status:

{% tabs %}
{% highlight razor tabtitle="CSHTML" %}

@using Syncfusion.EJ2

<div id='container'>
@Html.EJS().Button("fetchButton").Content("Execute Query").CssClass("e-primary").Render()
<p id="statusMessage" style="text-align:center;color:blue"></p>
@Html.EJS().Grid("Grid").Columns(col =>
{
col.Field("OrderID").HeaderText("Order ID").Width("120").TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Type("number").Add();
col.Field("CustomerID").HeaderText("Customer ID").Width("160").Type("string").Add();
col.Field("EmployeeID").HeaderText("Employee ID").Width("120").TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Type("number").Add();
col.Field("Freight").HeaderText("Freight").Width("150").Format("C2").TextAlign(Syncfusion.EJ2.Grids.TextAlign.Right).Type("number").Add();
col.Field("ShipCountry").HeaderText("Ship Country").Width("150").Type("string").Add();
}).Render()
</div>

<script>
document.addEventListener("DOMContentLoaded", function () {
let SERVICE_URL = 'https://ej2services.syncfusion.com/production/web-services/api/Orders';
let statusMessage = document.getElementById("statusMessage");

fetchButton.addEventListener("click", function () {
statusMessage.textContent = "Fetching data...";
var grid = document.getElementById("Grid")?.ej2_instances?.[0];

let getData = new ej.data.DataManager({
url: SERVICE_URL,
adaptor: new ej.data.WebApiAdaptor()
});

getData.executeQuery(new ej.data.Query()).then(function (e) {
grid.dataSource = e.result;
statusMessage.textContent = "Data fetched successfully! Total Records: " + e.result.length;
statusMessage.style.color = "green";
}).catch(function () {
statusMessage.textContent = "Error fetching data!";
statusMessage.style.color = "red";
});
});
});
</script>

{% endhighlight %}
{% endtabs %}

![Fetch result from DataManager Query](../images/databinding/fetch-data.png)
218 changes: 216 additions & 2 deletions ej2-asp-core-mvc/grid/EJ2_ASP.MVC/editing/validation.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
layout: post
title: Validation in ##Platform_Name## Grid Component
title: Validation in ##Platform_Name## Grid Control | Syncfusion
description: Learn here all about Validation in Syncfusion ##Platform_Name## Grid component of Syncfusion Essential JS 2 and more.
platform: ej2-asp-core-mvc
control: Validation
publishingplatform: ##Platform_Name##
documentation: ug
---

# Validation in ASP.NET MVC Grid component
# Validation in ASP.NET MVC Syncfusion Grid component

Validation is a crucial aspect of data integrity in any application. The ASP.NET MVC Grid component in Syncfusion<sup style="font-size:70%">&reg;</sup> 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.

Expand Down Expand Up @@ -120,3 +120,217 @@ Here's an example that demonstrates how to change the position of the validation

![Change the position of validation error message](../images/editing/validation-position.png)

## 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](https://help.syncfusion.com/cr/aspnetmvc-js2/Syncfusion.EJ2.Grids.Grid.html#Syncfusion_EJ2_Grids_Grid_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:

{% tabs %}
{% highlight razor tabtitle="CSHTML" %}
<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>

{% endhighlight %}

{% highlight c# tabtitle="GridController.cs" %}

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

{% endhighlight %}
{% endtabs %}

![Show custom error message](../images/editing/custom-message.png)
Loading