Data Tables Editor MVC Routing & Ajax Error
Data Tables Editor MVC Routing & Ajax Error
I have a proof of concept successfully working from Editor Generator.
Now I'm pushing forward trying to integrate editor into an existing project, here is the latest challenge.
I need help.
I am getting the following error in the bowser that tells me AJAX request isn't making it to the controller.
Here is the error in the browser.
I am using two routers. The original MVC router, plus now Ive added in the router for the datatable editor api. I don't quite understand why datatable editor needs a router different than the stock MVC router, so I decided to not question the reason and include both routers in my MVC project.
Here is the original MVC router (filename: App_Start/RouteConfig.cs)
// ----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// ----------------------------------------------------------------------------
namespace AppOwnsData
{
using System.Web.Mvc;
using System.Web.Routing;
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
and here is the router for DataTable editor (filename: App_Start/WebApiConfig.cs)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
namespace AppOwnsData
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
Here is my controller (filename Controller/OnCallController.cs):
I put a program break on line 22, and its not getting triggered so I know the AJAX request isn't making it to the controller.
namespace AppOwnsData.Controllers
{
public class OnCallController : Controller
{
public ActionResult Index()
{
return View();
}
}
public class OnCallDataController : ApiController
{
[System.Web.Http.Route("api/OnCallData")]
[System.Web.Http.HttpGet]
[System.Web.Http.HttpPost]
public IHttpActionResult DataTransport()
{
var settings = Properties.Settings.Default;
var request = HttpContext.Current.Request;
using (var db = new Database(settings.DbType, settings.DbConnection))
{
var response = new Editor(db, "Flex_OnCal", "TableID")
.Model<Flex_OnCall>()
.Field(new Field("day")
.Validator(Validation.DateFormat(Format.DATE_ISO_2822))
.GetFormatter(Format.DateSqlToFormat(Format.DATE_ISO_2822))
.SetFormatter(Format.DateFormatToSql(Format.DATE_ISO_2822))
)
.Process(request)
.Data();
return Json(response);
}
}
}
}
and here is my view. Filename(View/OnCall/index.cshtml)
@{
ViewBag.Title = "On Call";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>On Call</h2>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.13.3/css/jquery.dataTables.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/buttons/2.3.5/css/buttons.dataTables.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/select/1.6.1/css/select.dataTables.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/datetime/1.3.1/css/dataTables.dateTime.min.css">
<link href="~/Content/style/editor.dataTables.css" rel="stylesheet" />
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://cdn.datatables.net/1.13.3/js/jquery.dataTables.min.js"></script>
<script src="~/scripts/dataTables.responsive.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.3.5/js/dataTables.buttons.min.js"></script>
<script src="https://cdn.datatables.net/select/1.6.1/js/dataTables.select.min.js"></script>
<script src="https://cdn.datatables.net/datetime/1.3.1/js/dataTables.dateTime.min.js"></script>
<script type="text/javascript" src="~/scripts/dataTables.editor.min.js"></script>
<style>
</style>
<script>
var editor;
$(document).ready(function () {
editor = new $.fn.dataTable.Editor({
ajax: {
create: {
type: 'POST',
url: 'api/OnCallData'
},
edit: {
type: 'PUT',
url: 'api/OnCallData'
},
remove: {
type: 'DELETE',
url: 'api/OnCallData'
}
},
table: "#onCall",
fields: [{
label: "TableID",
name: "TableID"
}, {
label: "Day",
name: "Day"
}, {
label: "Shop",
name: "Shop"
}, {
label: "Name",
name: "Name"
}, {
label: "Phone",
name: "Phone"
}, {
label: "Email",
name: "Email"
}
]
});
$("#onCall").DataTable({
dom: "Bfrtip",
order: [[2, 'asc']],
"responsive": true,
"processing": true, // for show progress bar
"serverSide": true, // for process server side
"filter": true, // this is for disable filter (search box)
"orderMulti": false, // for disable multiple column at once
"pageLength": 25,
"ajax": {
"url": "/api/OnCallData",
"type": "POST",
"datatype": "json",
"data": function (d) {
return $.extend({}, d, {
"start_date": $('#datemin').val(),
"form_id": "InboundGrid",
});
}
},
"columnDefs":
[
{ "defaultContent": "-", "targets": "_all" },
{
"targets": [0],
"visible": false,
"searchable": false,
"orderable": true,
},
{
"targets": [1],
"visible": true,
"searchable": true,
"orderable": true,
"type": "date",
},
],
"columns": [
{ "data": "TableID", "name": "ID", "title": "ID", "autoWidth": true },
{
"data": "Day", "title": "Day", "name": "Day", "autoWidth": true,
"type": "datetime",
"format": "dddd, DD-MM-YY",
"render": function (value) {
if (value === null) return "";
const date = new Date(parseInt(value.replace(/\/+Date\(([\d+-]+)\)\/+/, '$1')));
const formattedDate = date.toLocaleDateString('en-GB', {
day: 'numeric', month: 'short', year: 'numeric'
}).replace(/ /g, '-');
return formattedDate;
}
},
{ "data": "Shop", "title": "Shop", "name": "Shop", "autoWidth": true },
{ "data": "Name", "title": "Name", "name": "Name", "autoWidth": true },
{ "data": "Phone", "title": "Phone", "name": "Phone", "autoWidth": true },
{ "data": "Email", "title": "Email", "name": "Email", "autoWidth": true },
],
select: true,
buttons: [
{ extend: "create", editor: editor },
{ extend: "edit", editor: editor },
{ extend: "remove", editor: editor }
]
});
});
</script>
</head>
<body>
<div class="container">
<br />
<div style="width:90%; margin:0 auto;">
<table border="0" class="display nowrap" style="width:100%" cellspacing="5" cellpadding="5">
<tbody>
</tbody>
</table>
<table id="onCall" class="row-border table-striped table-bordered dt-responsive nowrap" width="100%" cellspacing="0">
<thead>
<tr>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
</table>
</div>
</div>
</body>
</html>
Answers
Did you follow the troubleshooting steps at the link in the error?
https://datatables.net/manual/tech-notes/7
Basically use the browser's network inspector tool to see the request and more importantly the response. Let us know what you find.
Kevin
Hi Kevin,
I don't believe this is going to be the response from me that you were anticipating.
As I stated above I am not getting into the controller.
Therefore here is the response showing error where otherwise a successful ajax query one would expect to see a nice array.
Here is a visual of the network inspector;
and here is the response of OnCallData
-David
This is in the response:
That suggests the URL is incorrect or a misconfiguration in your server code. This is not an error with the Editor.
Kevin
double post removed
Hi Kevin,
I believe the issue is the router is not delivering the ajax request to the proper controller.
I cant figure out why "editor generator" (https://editor.datatables.net/generator/) uses a custom router that is not the stock MVC router.
I attempted to combine both the stock router (which is in use in my existing solution across 5 different data tables) and the router provided with "editor generator". It would appear the router provided via "editor generator" is not routing.
I think I do not understand how to have two routers in one MVC project. The stock MVC router for general MVC controllers and datatables without an editor and a 2nd router for editor controllers.
Im so smart. I figured it out.
In the file global.axas.cs
change this;
to this
Nice one - thanks for posting back. I'll look into how Generator is setting up routing - I was under the impression that it was fairly stock.
Allan