Click here to Skip to main content
15,887,746 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I'm struggling with:
I have a Database-WEB API -Web application tier. My web application has a jquery datatable which post its request to the following method in the WEB API

public class DataTableAjaxPostModel
   {
       public int? draw { get; set; }
       public int? start { get; set; }
       public int? length { get; set; }
       public List<Column> columns { get; set; }
       public Search search { get; set; }
       public List<Order> order { get; set; }
   }
   public class Column
   {
       public string? data { get; set; }
       public string? name { get; set; }
       public bool? searchable { get; set; }
       public bool? orderable { get; set; }
       public Search? search { get; set; }
   }
   public class Search
   {
       public string? value { get; set; }
       public string? regex { get; set; }
   }
    [HttpPost]
       [Route("Plots/Postdata")]
       public  async Task<ActionResult> Postdata([FromForm] DataTableAjaxPostModel model)
       {
           using (var client = new HttpClient())
           {
               client.DefaultRequestHeaders.Clear();
               client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
               HttpContent body = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");
               HttpResponseMessage Res = await client.PostAsync("https://localhost:7193/api/Erven",body);

               if (Res.IsSuccessStatusCode)
               {

                   var EmpResponse = Res.Content.ReadAsStringAsync().Result;


               return Ok(EmpResponse);
                 }
               }
           return null;
       }




First question: Does the datatable parameters bind automatically to the DataTableAjaxPostmodel ?
Second question: Is the above code correct ? It looks a bit clumsy for me ( I'm not a developer but a civil engineer who likes coding)
The PostAsync of HttpResponseMessage targets the following WEB API method which is "outside"the WEB application project.

[HttpPost]
      public async Task<ActionResult>Getdata([FromBody] DataTableAjaxPostModel model)
      {
          string? searchValue = model?.search?.value;

             int? draw = model.draw;
             int? start = model.start;
             int? length = model.length;
             string? sortColumn = model?.columns[model.order[0].column]?.name;
            string? sortColumnDirection = model?.order?[0].dir;
             int pageSize = length != null ? Convert.ToInt32(length) : 0;
             int skip = start != null ? Convert.ToInt32(start) : 0;
             int filteredRecords = 0;

          var query =this._UoW.Repository<Progressreport>().Query();

         if (!(string.IsNullOrEmpty(sortColumn) && string.IsNullOrEmpty(sortColumnDirection)))
          {
              query = query.OrderBy(sortColumn + " " + sortColumnDirection);
          }
          if (!string.IsNullOrEmpty(searchValue))
          {
              query = query.Where( p => p.Inspector.ToLower().Contains(searchValue.ToLower()) ||
                                   p.Projectname.ToLower().Contains(searchValue.ToLower()) ||
                                   p.Plot.ToString().ToLower().Contains(searchValue.ToLower()) ||
                                   p.Status.ToLower().Contains(searchValue.ToLower()));
          }

           int recordsTotal = await query.CountAsync();

          var data = await query.Skip(skip).Take(pageSize).ToListAsync();
          filteredRecords =  data.Count();


          var jsonData = new { draw = draw, recordsFiltered = filteredRecords, recordsTotal = recordsTotal, data = data };
          return Ok(jsonData);
      }


Third question; Is this coding correct? Is the JSonData return right ?
Lastly, the Jquery datatable script

<script>
        $(document).ready(function () {
            bindDatatable();
        });
        function bindDatatable() {
            datatable = $('#tblStudent')
                .DataTable({
                    "sAjaxSource": "Plots/Postdata,
                    "bServerSide": true,
                    "bProcessing": true,
                    "type":"POST",
                     "datatype": "json",
                    "bSearchable": true,
                    "order": [[1, 'asc']],
                    "language": {
                        "emptyTable": "No record found.",
                        "processing":
                            '" style="color: rgba(42, 43, 43, 1)">Loading... '
                    },
                    "columns": [
                        {
                            "data": "plot",
                            "autoWidth": true,
                            "searchable": true
                        },
                        {
                            "data": "status",
                            "autoWidth": true,
                            "searchable": true
                        },
                        {
                            "data": "contractor",
                            "autoWidth": true,
                            "searchable": true
                        },
                        {
                            "data": "inspector",
                            "autoWidth": true,
                            "searchable": true
                        }, 
                    ]
                });
        }
    </script>


What I have tried:

Tried to find the solution in various forums without success
Posted
Updated 5-Apr-23 1:24am

To answer your first question, yes, the datatable parameters should bind automatically to the DataTableAjaxPostModel class when it's sent to the Postdata method via the HTTP POST request.

Regarding your second question, the code seems okay, but there are a few things that can be improved. For example, the using statement is not necessary for the HttpClient instance because it's already managed by the ASP.NET Core Dependency Injection container. Also, you should use the ActionResult<t> instead of ActionResult for returning data from your controller actions.

Here's a modified version of your code that takes into account the points mentioned above:

C#

[HttpPost]
[Route("Plots/Postdata")]
public async Task<ActionResult<string>> Postdata([FromForm] DataTableAjaxPostModel model)
{
    using var client = new HttpClient();
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    var body = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");
    var response = await client.PostAsync("https://localhost:7193/api/Erven", body);
    if (response.IsSuccessStatusCode)
    {
        var content = await response.Content.ReadAsStringAsync();
        return Ok(content);
    }
    return NotFound();
}

Regarding your third question, the code also seems okay. However, you might want to consider using a view model instead of returning an anonymous object. This can help improve the readability and maintainability of your code.

Here's an example of how you could modify the Getdata method to use a view model:
C#

public class DataTableResultViewModel<T>
{
    public int Draw { get; set; }
    public int RecordsTotal { get; set; }
    public int RecordsFiltered { get; set; }
    public List<T> Data { get; set; }
}

[HttpPost]
public async Task<ActionResult<DataTableResultViewModel<Progressreport>>> Getdata([FromBody] DataTableAjaxPostModel model)
{
    var searchValue = model?.search?.value;
    var draw = model.draw ?? 0;
    var start = model.start ?? 0;
    var length = model.length ?? 0;
    var sortColumn = model.columns[model.order[0].column]?.name;
    var sortColumnDirection = model.order?[0].dir;
    var pageSize = length != 0 ? length.Value : 0;
    var skip = start != 0 ? start.Value : 0;
    var filteredRecords = 0;

    var query = this._UoW.Repository<Progressreport>().Query();

    if (!string.IsNullOrEmpty(sortColumn) && !string.IsNullOrEmpty(sortColumnDirection))
    {
        query = query.OrderBy(sortColumn + " " + sortColumnDirection);
    }
    if (!string.IsNullOrEmpty(searchValue))
    {
        query = query.Where(p => p.Inspector.ToLower().Contains(searchValue.ToLower()) ||
                                 p.Projectname.ToLower().Contains(searchValue.ToLower()) ||
                                 p.Plot.ToString().ToLower().Contains(searchValue.ToLower()) ||
                                 p.Status.ToLower().Contains(searchValue.ToLower()));
    }

    var recordsTotal = await query.CountAsync();

    var data = await query.Skip(skip).Take(pageSize).ToListAsync();
    filteredRecords = data.Count();

    var result = new DataTableResultViewModel<Progressreport>
    {
        Draw = draw,
        RecordsTotal = recordsTotal,
        RecordsFiltered = filteredRecords,
        Data = data
    };

    return Ok(result);
}

Finally, regarding your last question, the jQuery datatable script seems fine, but you might want to change the "sAjaxSource" parameter to "ajax" since it's the recommended way of specifying the data source. Also, you should add error handling code to the bindDatatable function to handle any errors that may occur during the data retrieval process. You can use the error parameter in the DataTable initialization to handle any errors that occur during the data retrieval process. Here's an example of how you can add error handling to the bindDatatable function:

lua

function bindDatatable() {
    datatable = $('#tblStudent').DataTable({
        "ajax": {
            "url": "Plots/Postdata",
            "type": "POST",
            "dataType": "json"
        },
        "serverSide": true,
        "processing": true,
        "searching": true,
        "order": [[1, 'asc']],
        "language": {
            "emptyTable": "No record found.",
            "processing": 'Loading...'
        },
        "columns": [
            { "data": "plot", "autoWidth": true },
            { "data": "status", "autoWidth": true },
            { "data": "contractor", "autoWidth": true },
            { "data": "inspector", "autoWidth": true }
        ],
        "error": function (xhr, error, thrown) {
            alert("Error occurred while loading data. Please try again.");
        }
    });
}

This code adds an error function to the DataTable initialization that displays an error message in case an error occurs during the data retrieval process. You can customize this function to handle errors in a way that suits your requirements.
 
Share this answer
 
Comments
chocusatergus 18-Apr-23 13:16pm    
Hi Nima:

Apologies for the late response. the sorting method below throw an exception

if (!string.IsNullOrEmpty(sortColumn) && !string.IsNullOrEmpty(sortColumnDirection))
{
query = query.OrderBy(sortColumn + " " + sortColumnDirection);
}

The exception is =.>No property of field 'asc exists in the type 'Progressreport' at Index 1

it seems that the code below isn't appropriate

var result = new DataTableResultViewModel<progressreport>
{
Draw = draw,
RecordsTotal = recordsTotal,
RecordsFiltered = filteredRecords,
Data = data
};
To pass the jQuery DataTable post parameters to an external ASP.NET Core Web API, you can follow the below steps:

Add the necessary jQuery DataTable post parameters to the HTTP request body in the Postdata action method of the WEB API project. This can be done by creating an instance of StringContent and passing the serialized DataTableAjaxPostModel object in the constructor, as shown in your code.

Send the HTTP request to the external Web API using the HttpClient class in the Postdata action method. In the code, you have used the PostAsync method to send the request and await the response.

In the external Web API project, create an action method to receive the HTTP request with the jQuery DataTable post parameters. In the Getdata action method, you can retrieve the post parameters from the HTTP request body by using the [FromBody] attribute, as shown in your code.

Process the post parameters in the Getdata action method and retrieve the necessary data from the database. Then, create a JSON object with the required data and return it as an HTTP response to the calling jQuery DataTable.

Regarding your questions:

Yes, the datatable parameters will bind automatically to the DataTableAjaxPostModel object because you have used the [FromForm] attribute in the Postdata action method.

The code looks fine, but you can improve it by handling exceptions and returning appropriate HTTP response codes.

The code for the Getdata action method looks correct, and the JSON data is being returned in the correct format.

The jQuery DataTable script also looks correct, but you should replace "sAjaxSource": "Plots/Postdata" with "ajax": "Plots/Postdata" as the former is deprecated. Additionally, you should handle exceptions and display appropriate error messages to the user if the data cannot be retrieved or if there is an error in the server response.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900