A practical guide to building an Asp.Net 8 MVC application that uses jQuery component DataTables.net. This is a continuation of article Part3.
1 ASP.NET8 using jQuery DataTables.net
I was evaluating the jQuery DataTables.net component [1] for usage in ASP.NET8 projects and created several prototype (proof-of-concept) applications that are presented in these articles.
1.1 Articles in this series
Articles in this series are:
- ASP.NET8 using DataTables.net – Part1 – Foundation
- ASP.NET8 using DataTables.net – Part2 – Action buttons
- ASP.NET8 using DataTables.net – Part3 – State saving
- ASP.NET8 using DataTables.net – Part4 – Multilingual
- ASP.NET8 using DataTables.net – Part5 – Passing additional parameters in AJAX
- ASP.NET8 using DataTables.net – Part6 – Returning additional parameters in AJAX
- ASP.NET8 using DataTables.net – Part7 – Buttons regular
- ASP.NET8 using DataTables.net – Part8 – Select rows
- ASP.NET8 using DataTables.net – Part9 – Advanced Filters
2 Final result
The goal of this article is to create a proof-of-concept application that demos DataTables.net component in ASP.NET multi-language application. Let us present the result of this article.
Here is the English version:
Here is the German version:
So, DataTables.net component can be used in multilingual applications. Please note that we need to set up translations on two levels:
- Translations for DataTables.net component itself
- Translations for Strings used by DataTables.net component
It is a bit tricky to set up it all properly, but it is doable.
3 Multi-language setup
If you are not familiar with the multi-language setup for ASP.NET8, please read my articles [2]-[5]. I am not going to copy-paste the same text again here, I will just use the same code from those examples here. As explained in those articles, the main trick is to set up AspNetCore.Culture cookie properly for the particular language. All is explained in detail in those articles [2]-[5].
Here is the controller code that is doing that:
public IActionResult ChangeLanguage(ChangeLanguageViewModel model)
{
if (model.IsSubmit)
{
HttpContext myContext = this.HttpContext;
ChangeLanguage_SetCookie(myContext, model.SelectedLanguage);
return LocalRedirect("/Home/ChangeLanguage");
}
ChangeLanguage_PreparePresentation(model);
return View(model);
}
private void ChangeLanguage_PreparePresentation(ChangeLanguageViewModel model)
{
model.ListOfLanguages = new List<SelectListItem>
{
new SelectListItem
{
Text = "English",
Value = "en"
},
new SelectListItem
{
Text = "German",
Value = "de",
},
new SelectListItem
{
Text = "French",
Value = "fr"
},
new SelectListItem
{
Text = "Italian",
Value = "it"
}
};
}
private void ChangeLanguage_SetCookie(HttpContext myContext, string? culture)
{
if (culture == null) { throw new Exception("culture == null"); };
CookieOptions cookieOptions = new CookieOptions();
cookieOptions.Expires = DateTimeOffset.UtcNow.AddMonths(1);
cookieOptions.IsEssential = true;
myContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
cookieOptions
);
}
Here is the footer in the view that I use for debugging purposes
@**@
@using Microsoft.AspNetCore.Localization;
@{
string text = String.Empty;
try
{
var myContext = Context;
string? cultureCookieValue = null;
myContext.Request.Cookies.TryGetValue(
CookieRequestCultureProvider.DefaultCookieName, out cultureCookieValue);
string? text1 = "Request Cookie was (Refresh might be needed if changing language) " +
CookieRequestCultureProvider.DefaultCookieName + "[" + cultureCookieValue + "]";
text = text1;
}
catch (Exception ex)
{
text = ex.Message;
}
<span>
@text
</span>
}
Here are translations for DataTables.net component itself
Here are translations for strings in the application
4 Client-side DataTables.net component
Here I will just show what the ASP.NET view using DataTables component looks like.
<!--
<partial name="_LoadingDatatablesJsAndCss" />
@{
<div class="text-center">
<h3 class="display-4">Employees table</h3>
</div>
<!-- Here is our table HTML element defined. JavaScript library Datatables
will do all the magic to turn it into interactive component -->
<table id="EmployeesTable01" class="table table-striped table-bordered ">
</table>
}
@{
<!-- Method to tell DatTables.net component which
language file to load -->
string GetUrlForDatatablesLanguageFile()
{
string urlResult = String.Empty;
try
{
string culture = Thread.CurrentThread.CurrentUICulture.ToString();
if (culture.Length > 2)
{
culture = culture.Substring(0, 2).ToLower();
}
string baseUrl = Url.Content("~/lib/datatables/i18n/");
switch (culture)
{
case "de":
urlResult = baseUrl + "de-DE.json";
break;
case "fr":
urlResult = baseUrl + "fr-FR.json";
break;
case "it":
urlResult = baseUrl + "it-IT.json";
break;
default:
urlResult = String.Empty;
break;
}
}
catch
{
urlResult = String.Empty;
}
return urlResult;
}
}
<script>
document.addEventListener("DOMContentLoaded", InitializeDatatable);
function InitializeDatatable() {
$("#EmployeesTable01").dataTable({
processing: true,
paging: true,
info: true,
ordering: true,
searching: true,
search: {
return: true
},
autoWidth: true,
lengthMenu: [10, 15, 25, 50, 100],
pageLength: 10,
order: [[1, 'asc']],
serverSide: true,
stateSave: true,
stateDuration: -1,
language: {
url: '@GetUrlForDatatablesLanguageFile()'
},
ajax: {
"url": "@Url.Action("EmployeesDT", "Home")",
"type": "POST",
"datatype": "json"
},
columns: [
{
name: 'id',
data: 'id',
title: "@Example04.Resources.SharedResource.EmployeeId",
orderable: true,
searchable: false,
type: 'num',
visible: true
},
{
name: 'givenName',
data: "givenName",
title: "@Example04.Resources.SharedResource.GivenName",
orderable: true,
searchable: true,
type: 'string',
visible: true
},
{
name: 'familyName',
data: "familyName",
title: "@Example04.Resources.SharedResource.FamilyName",
orderable: true,
searchable: true,
type: 'string',
visible: true
},
{
name: 'town',
data: "town",
title: "@Example04.Resources.SharedResource.Town",
orderable: true,
searchable: true,
type: 'string',
visible: true
},
{
name: 'country',
data: "country",
title: "@Example04.Resources.SharedResource.Country",
orderable: true,
searchable: true,
type: 'string',
visible: true,
width: "150px",
className: 'text-center '
},
{
name: 'email',
data: "email",
title: "@Example04.Resources.SharedResource.Email",
orderable: true,
searchable: true,
type: 'string',
visible: true
},
{
name: 'phoneNo',
data: "phoneNo",
title: "@Example04.Resources.SharedResource.PhoneNumber",
orderable: false,
searchable: true,
type: 'string',
visible: true
},
{
name: 'actions',
data: "actions",
title: "@Example04.Resources.SharedResource.Actions",
orderable: false,
searchable: false,
type: 'string',
visible: true,
render: renderActions
},
{
name: 'urlForEdit',
data: "urlForEdit",
title: "urlForEdit",
orderable: false,
searchable: false,
type: 'string',
visible: false
}
]
});
function renderActions(data, type, row, meta) {
let html1 =
'<a class="btn btn-info" href="' +
row.urlForEdit +
'"> @Example04.Resources.SharedResource.Edit</a>';
let editUrl = "@Url.Action("EmployeeInfo", "Home")" +
"?EmployeeId=" + row.id;
let html2 =
'<a class="btn btn-info" style="margin-left: 10px" href="' +
editUrl + '"> @Example04.Resources.SharedResource.Info</a>';
return html1 + html2;
}
}
</script>
Please note that we need to set up translations on two levels:
- Translations for DataTables.net component itself
- Translations for Strings used by DataTables.net component
For 1), we use the method GetUrlForDatatablesLanguageFile() to tell DatTables.net component which language file to load.
For 2) we use Resource Manager, as explained in [5].
5 Conclusion
The full example code project can be downloaded.
6 References
[1] https://datatables.net/
[2] https://www.codeproject.com/Articles/5378651/ASP-NET-8-Multilingual-Application-with-Single-Res
[3] https://www.codeproject.com/Articles/5378997/ASP-NET-8-Multilingual-Application-with-Single-R-2
[4] https://www.codeproject.com/Articles/5379125/ASP-NET-8-Multilingual-Application-with-Single-R-3
[5] https://www.codeproject.com/Articles/5379436/ASP-NET-8-Multilingual-Application-with-Single-R-4
Mark Pelf is the pen name of just another Software Engineer from Belgrade, Serbia.
My Blog https://markpelf.com/