Updated IVS example

Added SqlServer Rest API library, incremental pagination on server side
processing page.
This commit is contained in:
Jovan Popovic
2016-12-18 23:20:47 +01:00
parent 8d3406277a
commit c39052a0e6
6 changed files with 158 additions and 122 deletions
@@ -1,123 +1,44 @@
using Belgrade.SqlClient;
using Microsoft.AspNetCore.Mvc;
using System.Collections;
using System.Collections.Generic;
using System.Data.SqlClient;
using SqlServerRestApi.Controller;
using SqlServerRestApi.SQL;
using System.Threading.Tasks;
// For more information on enabling Web API for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860
namespace Catalog.Controllers
namespace Register.Controllers
{
[Route("api/[controller]")]
public class PeopleController : Controller
{
IQueryPipe sqlQuery = null;
TableSpec tableSpec = new TableSpec("dbo.People", "name,surname,address,town");
public PeopleController(IQueryPipe sqlQueryService)
{
this.sqlQuery = sqlQueryService;
}
// GET api/Company
[HttpGet]
public async Task Get(int draw, int start, int length)
{
Hashtable search = new Hashtable();
int i = 0;
bool more = true;
while (more)
{
if(Request.Query[$"columns[{i}][search][value]"].Count != 0)
{
search.Add(
Request.Query[$"columns[{i}][data]"][0].ToString(),
Request.Query[$"columns[{i}][search][value]"][0].ToString());
i++;
} else
{
more = false;
}
}
string orderCol;
switch (Request.Query["order[0][column]"])
{
case "0": orderCol = "name"; break;
case "1": orderCol = "surname"; break;
case "2": orderCol = "address"; break;
case "3": orderCol = "town"; break;
default: orderCol = "name"; break;
}
var orderDir = Request.Query["order[0][dir]"]=="asc"?"asc":"desc";
var sql = this.GetSearchQuery(search, orderCol, orderDir, start, length);
var header = System.Text.Encoding.UTF8.GetBytes( @"{
""draw"":"+ draw + @",
""recordsTotal"": "+ (start+length+1) + @",
""recordsFiltered"": " + (start + length + 1) + @",
""data"":");
await Response.Body.WriteAsync(header,0,header.Length);
await sqlQuery.Stream(sql, Response.Body, "[]");
await Response.Body.WriteAsync(System.Text.Encoding.UTF8.GetBytes("}"),0,1);
}
class SearchEntry
{
public string Column;
public string Data;
public override string ToString()
{
return Column + " LIKE @" + Column;
}
}
private SqlCommand GetSearchQuery(Hashtable search, string orderCol, string orderDir, int start, int length)
{
SqlCommand res = new SqlCommand();
string sql = "select name, surname, address, town from people";
IList<SearchEntry> l = new List<SearchEntry>(search.Count);
foreach (DictionaryEntry entry in search)
{
if (!string.IsNullOrEmpty(entry.Value.ToString()))
{
l.Add(new SearchEntry { Column = entry.Key.ToString(),
Data = entry.Value.ToString()
});
res.Parameters.AddWithValue(entry.Key.ToString(), "%" + entry.Value.ToString() + "%");
}
}
if (l.Count > 0) {
var predicate = string.Join(" and ", l as IEnumerable<SearchEntry>);
sql += " where " + predicate;
}
if (!string.IsNullOrEmpty(orderCol))
{
sql += " order by " + orderCol + " " + orderDir;
}
else
{
sql += " order by name ";
}
sql += string.Format(" OFFSET {0} ROWS FETCH NEXT {1} ROWS ONLY ", start, length);
res.CommandText = sql + " for json path";
return res;
}
// GET api/Company
[HttpGet("Load")]
public async Task Load()
/// <summary>
/// Method that returns all data that will be processed by JQuery DataTables in client-side processing mode.
/// </summary>
/// <returns></returns>
// GET api/People/All
[HttpGet("All")]
public async Task GetAll()
{
await sqlQuery.Stream("select name, surname, address, town from people for json path, root('data')", Response.Body, @"{""data"":[]");
}
/// <summary>
/// Method that process server-side processing JQuery DataTables HTTP request
/// and returns data that should be shown.
/// </summary>
/// <returns></returns>
// GET api/People
[HttpGet]
public async Task Get()
{
await this.ProcessJQueryDataTablesRequest(tableSpec, sqlQuery);
}
}
}
+3 -13
View File
@@ -1,11 +1,9 @@
using Belgrade.SqlClient;
using Belgrade.SqlClient.SqlDb;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Data.SqlClient;
using SqlServerRestApi;
namespace Catalog
{
@@ -26,15 +24,7 @@ namespace Catalog
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
string ConnString = Configuration["ConnectionStrings:IVSDemo"];
// Adding data access services/components.
services.AddTransient<IQueryPipe>(
sp => new QueryPipe(new SqlConnection(ConnString)));
services.AddTransient<ICommand>(
sp => new Command(new SqlConnection(ConnString)));
services.AddSqlClient(Configuration["ConnectionStrings:IVSDemo"]);
// Add framework services.
services.AddMvc();
}
@@ -4,6 +4,7 @@
"version": "1.0.0",
"type": "platform"
},
"Belgrade.Sql.Client": "0.6.1",
"Microsoft.AspNetCore.Mvc": "1.0.0",
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
@@ -15,7 +16,7 @@
"Microsoft.Extensions.Logging.Console": "1.0.0",
"Microsoft.Extensions.Logging.Debug": "1.0.0",
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
"Belgrade.Sql.Client": "0.6.0"
"Sql-Server-Rest-Api": "0.1.4"
},
"tools": {
@@ -15,7 +15,8 @@
<script src="media/js/lib/Bootstrap.js"></script>
<script src="media/js/lib/jquery.dataTables.js"></script>
<script src="media/js/lib/jquery.dataTables.Bootstrap.js"></script>
<script src="media/js/lib/jquery.dataTables.incremental_pagination.js"></script>
<script type="text/javascript" class="init">
$(document).ready(function() {
@@ -28,15 +29,21 @@ $(document).ready(function() {
var table = $('#example').DataTable(
{
"ajax": "/api/People/Load",
"ajax": "/api/People/All",
"columns": [
{ "data": "name", "width": "10%" },
{ "data": "surname", "width": "10%" },
{ "data": "address", "width": "50%" },
{ "data": "town", "width": "10%" }
],
"sDom": "lrtp",
"pagingType": "simple"
"pagingType": "simple_numbers",
"language": {
"lengthMenu": "Display _MENU_ per page",
"zeroRecords": "Nothing found - sorry",
"info": "Page _PAGE_",
"infoEmpty": "No records available",
"infoFiltered": ""
}
});
// Apply the search
@@ -0,0 +1,110 @@
$.fn.dataTableExt.oPagination.incremental = {
/*
* Function: oPagination.incremental.fnInit
* Purpose: Initalise dom elements required for pagination with a list of the pages
* Returns: -
* Inputs: object:oSettings - dataTables settings object
* node:nPaging - the DIV which contains this pagination control
* function:fnCallbackDraw - draw function which must be called on update
*/
"fnInit": function (oSettings, nPaging, fnCallbackDraw) {
$(nPaging).prepend($("<ul class=\"pagination\"></ul>"));
var ul = $("ul", $(nPaging));
nFirst = document.createElement('li');
nPrevious = document.createElement('li');
nNext = document.createElement('li');
$(nPrevious).append($('<span>' + (oSettings.oLanguage.oPaginate.sPrevious) + '</span>'));
$(nFirst).append($('<span>1</span>'));
$(nNext).append($('<span>' + (oSettings.oLanguage.oPaginate.sNext) + '</span>'));
nFirst.className = "paginate_button first active";
nPrevious.className = "paginate_button previous";
nNext.className = "paginate_button next";
ul.append(nPrevious);
ul.append(nFirst);
ul.append(nNext);
$(nFirst).click(function () {
oSettings.oApi._fnPageChange(oSettings, "first");
fnCallbackDraw(oSettings);
});
$(nPrevious).click(function () {
if (!(oSettings._iDisplayStart === 0)) {
oSettings.oApi._fnPageChange(oSettings, "previous");
fnCallbackDraw(oSettings);
}
});
$(nNext).click(function () {
if (!(oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay()
||
oSettings.aiDisplay.length < oSettings._iDisplayLength)) {
oSettings.oApi._fnPageChange(oSettings, "next");
fnCallbackDraw(oSettings);
}
});
/* Disallow text selection */
$(nFirst).bind('selectstart', function () { return false; });
$(nPrevious).bind('selectstart', function () { return false; });
$(nNext).bind('selectstart', function () { return false; });
// Reset dynamically generated pages on length/filter change.
$(oSettings.nTable).DataTable().on('length.dt', function (e, settings, len) {
$("li.dynamic_page_item", nPaging).remove();
});
$(oSettings.nTable).DataTable().on('search.dt', function (e, settings, len) {
$("li.dynamic_page_item", nPaging).remove();
});
},
/*
* Function: oPagination.incremental.fnUpdate
* Purpose: Update the list of page buttons shows
* Returns: -
* Inputs: object:oSettings - dataTables settings object
* function:fnCallbackDraw - draw function which must be called on update
*/
"fnUpdate": function (oSettings, fnCallbackDraw) {
if (!oSettings.aanFeatures.p) {
return;
}
/* Loop over each instance of the pager */
var an = oSettings.aanFeatures.p;
for (var i = 0, iLen = an.length ; i < iLen ; i++) {
var buttons = an[i].getElementsByTagName('li');
$(buttons).removeClass("active");
if (oSettings._iDisplayStart === 0) {
buttons[0].className = "paginate_buttons disabled previous";
buttons[buttons.length - 1].className = "paginate_button enabled next";
} else {
buttons[0].className = "paginate_buttons enabled previous";
}
var page = Math.round(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
if (page == buttons.length-1 && oSettings.aiDisplay.length > 0) {
$new = $('<li class="dynamic_page_item active"><span>' + page + "</span></li>");
$(buttons[buttons.length - 1]).before($new);
$new.click(function () {
$(oSettings.nTable).DataTable().page(page-1);
fnCallbackDraw(oSettings);
});
} else
$(buttons[page]).addClass("active");
if (oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay()
||
oSettings.aiDisplay.length < oSettings._iDisplayLength) {
buttons[buttons.length - 1].className = "paginate_button disabled next";
}
}
}
};
@@ -17,6 +17,7 @@
<script src="media/js/lib/Bootstrap.js"></script>
<script src="media/js/lib/jquery.dataTables.js"></script>
<script src="media/js/lib/jquery.dataTables.Bootstrap.js"></script>
<script src="media/js/lib/jquery.dataTables.incremental_pagination.js"></script>
<script type="text/javascript" class="init">
@@ -32,15 +33,21 @@ $(document).ready(function() {
var table = $('#example').DataTable({
"serverSide": true,
"processing": true,
"sDom": "lrtp",
"pagingType": "simple",
"pagingType": "incremental",
"ajax": "/api/People",
"columns": [
{ "data": "name", "width": "10%" },
{ "data": "surname", "width": "10%" },
{ "data": "address", "width": "50%" },
{ "data": "town", "width": "10%" }
]
],
"language": {
"lengthMenu": "Display _MENU_ per page",
"zeroRecords": "Nothing found - sorry",
"info": "Page _PAGE_",
"infoEmpty": "No records available",
"infoFiltered": ""
}
});
// Apply the search