return Page() in ASP.NET Core Razor Pages doesn't render the page after calling by RedirectToPage - asp.net-core

I'm new to ASP.NET Core Razor Pages.
In the index page I get the customers data and show them in a jQuery data table by ajax from the CustomerController. In the last column there are delete buttons. By these buttons I call delete method in the CustomerController.
JS Ajax file
$(document).ready(function() {
$("#customerDataTable").dataTable({
"processing": true,
"serverSide": true,
"filter": true,
"ajax": {
"url": "/api/customer",
"type": "post",
"datatype": "json"
},
"columnDefs":[
{
"targets": [0],
"visible": false,
"searchable": false
}],
"columns":[
{ "data": "id", "name": "Id", "autoWidth": true },
{ "data": "firstName", "name": "First Name", "autoWidth": true },
{ "data": "lastName", "name": "Last Name", "autoWidth": true },
{ "data": "contact", "name": "Contact", "autoWidth": true },
{ "data": "email", "name": "Email", "autoWidth": true },
{ "data": "dateOfBirth", "name": "Date Of Birth", "autoWidth": true },
{
"render": function(data,type, row) {
return "<a href='#' class='btn btn-danger' onclick=deleteCustomer('" + row.id + "');
>Delete</a>"; }
}]
});
});
function deleteCustomer(id) {
$.ajax({
url: "/api/customer",
type: "GET",
data: id
});
}
In the CustomerContoller I want to redirect to DeleteCustomer razor page with a parameter.
[HttpGet]
public IActionResult DeleteCustomer()
{
var id = Request.Query.Keys.ToList()[0];
return RedirectToPage("/DeleteCustomer", new{id});
}
In the DeleteCustomer Page there is a simple get method.
[BindProperty]
public int CustomerId { get; set; }
public IActionResult OnGet(string id)
{
CustomerId = int.Parse(id);
return Page();
}
When I debug the app line by line CustomerControll redirect to DeleteCustomer page properly, and the OnGet method in the page return the Page() method, but browser doesn't render the HTML part of the page without any errors. Just Index page still showed with the table of data.
If I call DeleteCustomer page in address bar DeleteCustomer page will rendered.
Why return Page() doesn't render and show the page after calling by RedirectToPage in the browser?

Why return Page() doesn't render and show the page after calling by RedirectToPage in the browser?
You make Ajax request from your client side, which does not automatically reload/refresh page. To display returned page content, you can try to dynamically write it in success callback function, like below.
$.ajax({
url: "/api/customer",
type: "GET",
data: id,
success: function (res) {
//console.log(res);
document.write(res);
}
});
Besides, you can also try to modify the approach to make your API action DeleteCustomer return an id, then do redirection on client side, like below.
[HttpGet]
public IActionResult DeleteCustomer()
{
//your code logic here
//var id = Request.Query["id"];
//return RedirectToPage("/DeleteCustomer", new { id });
return Ok(new { id });
}
On client side
success: function (res) {
console.log(res.id[0]);
window.location.assign("/DeleteCustomer?id=" + res.id[0]);
//document.write(res);
}

Related

Mimic the ( Show All ) link in datatables.net

I have a situation where I want to get the full (data) from the backend as a CSV file. I have already prepared the backend for that, but normally the front-end state => (filters) is not in contact with the backend unless I send a request, so I managed to solve the problem by mimicking the process of showing all data but by a custom button and a GET request ( not an ajax request ). knowing that I am using serverSide: true in datatables.
I prepared the backend to receive a request like ( Show All ) but I want that link to be sent by custom button ( Export All ) not by the show process itself as by the picture down because showing all data is not practical at all.
This is the code for the custom button
{
text: "Export All",
action: function (e, dt, node, config) {
// get the backend file here
},
},
So, How could I send a request like the same request sent by ( Show All ) by a custom button, I prepared the server to respond by the CSV file. but I need a way to get the same link to send a get request ( not by ajax ) by the same link that Show All sends?
If you are using serverSide: true that should mean you have too much data to use the default (serverSide: false) - because the browser/DataTables cannot handle the volume. For this reason I would say you should also not try to use the browser to generate a full export - it's going to be too much data (otherwise, why did you choose to use serverSide: true?).
Instead, use a server-side export utility - not DataTables.
But if you still want to pursuse this approach, you can build a custom button which downloads the entire data set to the DataTables (in your browser) and then exports that complete data to Excel.
Full Disclosure:
The following approach is inspired by the following DataTables forum post:
Customizing the data from export buttons
The following approach requires you to have a separate REST endpoint which delivers the entire data set as a JSON response (by contrast, the standard response should only be one page of data for the actual table data display and pagination.)
How you set up this endpoint is up to you (in Laravel, in your case).
Step 1: Create a custom button:
I tested with Excel, but you can do CSV, if you prefer.
buttons: [
{
extend: 'excelHtml5', // or 'csvHtml5'
text: 'All Data to Excel', // or CSV if you prefer
exportOptions: {
customizeData: function (d) {
var exportBody = getDataToExport();
d.body.length = 0;
d.body.push.apply(d.body, exportBody);
}
}
}
],
Step 2: The export function, used by the above button:
function GetDataToExport() {
var jsonResult = $.ajax({
url: '[your_GET_EVERYTHING_url_goes_here]',
success: function (result) {},
async: false
});
var exportBody = jsonResult.responseJSON.data;
return exportBody.map(function (el) {
return Object.keys(el).map(function (key) {
return el[key]
});
});
}
In the above code, my assumption is that the JSON response has the standard DataTables object structure - so, something like:
{
"data": [
{
"id": "1",
"name": "Tiger Nixon",
"position": "System Architect",
"salary": "$320,800",
"start_date": "2011/04/25",
"office": "Edinburgh",
"extn": "5421"
},
{
"id": "2",
"name": "Garrett Winters",
"position": "Accountant",
"salary": "$170,750",
"start_date": "2011/07/25",
"office": "Tokyo",
"extn": "8422"
},
{
"id": "3",
"name": "Ashton Cox",
"position": "Junior Technical Author",
"salary": "$86,000",
"start_date": "2009/01/12",
"office": "San Francisco",
"extn": "1562"
}
]
}
So, it's an object, containing a data array.
The DataTables customizeData function is what controls writing this complete JSON to the Excel file.
Overall, your DataTables code will look something like this:
$(document).ready(function() {
$('#example').DataTable( {
serverSide: true,
dom: 'Brftip',
buttons: [
{
extend: 'excelHtml5',
text: 'All Data to Excel',
exportOptions: {
customizeData: function (d) {
var exportBody = GetDataToExport();
d.body.length = 0;
d.body.push.apply(d.body, exportBody);
}
}
}
],
ajax: {
url: "[your_SINGLE_PAGE_url_goes_here]"
},
"columns": [
{ "title": "ID", "data": "id" },
{ "title": "Name", "data": "name" },
{ "title": "Position", "data": "position" },
{ "title": "Salary", "data": "salary" },
{ "title": "Start Date", "data": "start_date" },
{ "title": "Office", "data": "office" },
{ "title": "Extn.", "data": "extn" }
]
} );
} );
function GetDataToExport() {
var jsonResult = $.ajax({
url: '[your_GET_EVERYTHING_url_goes_here]',
success: function (result) {},
async: false
});
var exportBody = jsonResult.responseJSON.data;
return exportBody.map(function (el) {
return Object.keys(el).map(function (key) {
return el[key]
});
});
}
Just to repeat my initial warning: This is probably a bad idea, if you really needed to use serverSide: true because of the volume of data you have.
Use a server-side export tool instead - I'm sure Laravel/PHP has good support for generating Excel files.

Datatable returns all the data when server side is set to true

I have the following code where I want to use server side to lazy load my data. My goal is to display 10 records per page. The rest of the data should be loaded as and when the user clicks on a particular page.
What's happening now is that the datatable displays all the records at once. Can someone help me fix this issue?
var table = $("#members").DataTable({
"processing": true,
"serverSide": true,
paging: true,
"pagingType": "full_numbers",
"iDisplayLength": "10",
"length": "10",
ajax: {
url: "/api/members",
dataSrc: "",
},
columns: [
{
data: "cardNumber"
},
{
data: "registrationDate",
},
{
data: "fullName",
},
{
data: "address"
},
{
data: "phoneNumber"
},
{
data: "email"
}
]
});
Here's the API code:
// GET /api/members
public IEnumerable<MemberDto> GetMembers(string query = null)
{
var membersQuery = _context.Members.ToList();
if (!String.IsNullOrWhiteSpace(query))
membersQuery = membersQuery.Where(c => c.FullName.Contains(query.ToUpper())).ToList();
var memberDtos = membersQuery.ToList()
.Select(Mapper.Map<Member, MemberDto>);
return memberDtos;
}

edit jquery dt response before render

I have serverside pagination datatable with defination below, it works fine but the thing is;one of the field contains too long so I need to set a details button instead of it, when its clicked pop up showns up and view the data of descripotion.
I tried add success:function(aaData){..} to ajax but it brokes the datatable any suggestion? and I dont want to edit tho model in controller I have data in browser so I want to handle this here..
$(document).ready(function () {
var table = $('#dtBooks').DataTable({
"processing": true,
"serverSide": true,
"filter": false,
"orderMulti": false,
"ajax": {
"url": "#Url.Action("GetBooks", "Home")",
"type": "POST",
"datatype": "json"
},
"columns": [
{ "data": "Title", "name": "Title", "autoWidth": true },
{ "data": "Publisher", "name": "Publisher", "autoWidth": true },
{ "data": "Description", "name": "Description", "autoWidth": true },
{ "data": "Authors", "name": "Authors", "autoWidth": true },
]
});
});
here is the model defination contorller response list of this model to datatable.
public class Book
{
public string Title { get; set; }
public string Publisher { get; set; }
public string Description { get; set; }
public string[] Authors { get; set; }
}
You can use ajax.dataSrc option to manipulate the data returned from the server.
For example:
$('#example').DataTable( {
"ajax": {
"url": "data.json",
"dataSrc": function ( json ) {
for ( var i=0, ien=json.data.length ; i<ien ; i++ ) {
json.data[i][0] = '<a href="/message/'+json.data[i][0]+'>View message</a>';
}
return json.data;
}
}
});

ASP.NET 5 Controller method can't receive JSON POST, ASP.NET 4 controller method does

I have been tearing my hair out over this one. I have two projects one running ASP.NET 4 and the other ASP.NET 5 RC1
The ASP.NET 5 project controller received POST method input parameters are all default and not the values as sent from the webpage.
To narrow down the problem I simplified the controllers POST methods in both projects
[HttpPost]
public JsonResult DataHandler(int Draw)
{
//above Draw variable not set
}
and put a break point on the method to catch the variable Draw. The webpage sends a JSON post with a value of 1 for the Draw parameter. However in ASP.NET 5 that values is 0 (default) and other parameters I send are null instead of having values. In 'ASP.NET 4' it is correct.
I am using jquery datatables and the same code as used in this ASP.NET 4 project
var oTable = $('#datatab').DataTable({
"serverSide": true,
"ajax": {
"type": "POST",
"url": '/Home/DataHandler',
"contentType": 'application/json; charset=utf-8',
'data': function (data) { return data = JSON.stringify(data); }
},
"dom": 'frtiS',
"scrollY": 500,
"scrollX": true,
"scrollCollapse": true,
"scroller": {
loadingIndicator: false
},
"processing": true,
"paging": true,
"deferRender": true,
"columns": [
{ "data": "Name" },
{ "data": "City" },
{ "data": "Postal" },
{ "data": "Email" },
{ "data": "Company" },
{ "data": "Account" },
{ "data": "CreditCard" }
],
"order": [0, "asc"]
});
I used Fiddler and compared the JSON sent by both project to the controller and the JSON content posted to the /Home/DataHandler for both are the exact same i.e. Draw=1.
{"draw":1,"columns":[{"data":"Name","name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":"City","name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":"Postal","name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":"Email","name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":"Company","name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":"Account","name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}},{"data":"CreditCard","name":"","searchable":true,"orderable":true,"search":{"value":"","regex":false}}],"order":[{"column":0,"dir":"asc"}],"start":0,"length":126,"search":{"value":"","regex":false}}
Things I tried.
I used the same html table contents and above code .js file between projects
Set my controller input parameter to lowercase e.g. draw
Compare the JSON POST data in fiddler is the same
Put a breakpoint on the POST method input variable to catch the value as soon as it is posted
Add dataType: 'json' to the ajax call
Replace return data = JSON.stringify(data) with the following:
return data.Draw = JSON.stringify(data)

DataTables ajax requires explicit json collection name for the returned datasource?

I recently ran into a problem when implementing the ajax functionality of jquery DataTables. Until I actually gave my json object collection an explicit name I couldn't get anything to display. Shouldn't there be a default data source if nothing named is returned?
Client Side control setup (includes hidden field that supplies data to dynamic anchor:
$('#accountRequestStatus').dataTable(
{
"destroy": true, // within a method that will be called multiple times with new/different data
"processing": true,
"ajax":
{
"type": "GET",
"url": "#Url.Action("SomeServerMethod", "SomeController")",
"data": { methodParam1: 12341, methodParam2: 123423, requestType: 4123421 }
}
, "paging": false
, "columns": [
{ "data": "DataElement1" },
{ "data": "DataElement2", "title": "Col1" },
{ "data": "DataElement3", "title": "Col2" },
{ "data": "DataElement4", "title": "Col3" },
{ "data": "DataElement5", "title": "Col4" },
]
, "columnDefs": [
{
"targets": 0, // hiding first column, userId
"visible": false,
"searchable": false,
"sortable": false
},
{
"targets": 5, // creates action link using the hidden data for that row in column [userId]
"render": function (data, type, row) {
return "<a href='#Url.Action("ServerMethod", "Controller")?someParam=" + row["DataElement1"] + "'>Details</a>"
},
"searchable": false,
"sortable": false
}
]
});
Here's a snippet of my server side code that returns the json collection.
tableRows is a collection of models containing the data to be displayed.
var json = this.Json(new { data = tableRows });
json.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return json;
As I said before, the ajax call returned data but wouldn't display until I gave the collection a name. Maybe I missed this required step in the documentation, but wouldn't it make sense for the control to wire up to a single returned collection as the default data source and not require the name? Figuring out the name thing equated to about 2+ hours of messin' around trying different things. That's all I'm saying.
Maybe this'll help someone else too...
dataTables does actually have a dataSrc property! dataTables will look for either a data or an aaData section in the JSON. Thats why you finally got it to work with new { data=tableRows }. That is, if dataSrc is not specified! If your JSON differs from that concept you must specify dataSrc :
If you return a not named array / collection [{...},{...}] :
ajax: {
url: "#Url.Action("SomeServerMethod", "SomeController")",
dataSrc: ""
}
If you return a JSON array named different from data or aaData, like customers :
ajax: {
url: "#Url.Action("SomeServerMethod", "SomeController")",
dataSrc: "customers"
}
If the content is nested like { a : { b : [{...},{...}] }}
ajax: {
url: "#Url.Action("SomeServerMethod", "SomeController")",
dataSrc: "a.b"
}
If you have really complex JSON or need to manipulate the JSON in any way, like cherry picking from the content - dataSrc can also be a function :
ajax: {
url: "#Url.Action("SomeServerMethod", "SomeController")",
dataSrc: function(json) {
//do what ever you want
//return an array containing JSON / object literals
}
}
Hope the above clears things up!