Reputation: 43
I have an asp.net dashboard page that shows some tables and statistics, along with a filter panel with some checkboxes and a date range picker. I wrote jQuery to fire whenever a checkbox is clicked. The jQuery uses an Ajax POST to send the filter settings to the controller, which then queries the DB, applies the filter settings, creates a new page model, and sends it to the view. At this point I would like the razor view to be newly created and the browser to show a newly rendered page, but nothing changes and I get a 500 error in the console, probably because the controller isn't sending an appropriate response. Is there a better way to achieve what I'm trying to do?
The data is reaching the controller successfully and the new page model is being created correctly. I'm at a loss for what to do after this point.
javascript:
function sendFilterData() {
var checks = getFilterSettings(); //stringified JSON
$.ajax({
method: 'POST',
url: '@Url.Action("ApplyDashboardFilter", "Home")',
data: {
checks: checks, start: globalstart.format("YYYY-MM-DD HH:mm:ss"), end: globalend.format("YYYY-MM-DD HH:mm:ss") },
success: function (response) {
//???
},
failure: function (response) {
console.log(response);
}
});
}
C#
public IActionResult ApplyDashBoardFilter(string checks, DateTime start, DateTime end)
{
var filters = JsonConvert.DeserializeObject<List<FilterItem>>(checks);
ViewModel vm = new ViewModel();
foreach(var f in filters)
{
vm.AddFilter(f);
}
vm.StartDate = start;
vm.EndDate = end;
return Dashboard(vm);
}
public IActionResult Dashboard(ViewModel model)
{
//Get data and apply filters
return View(model);
}
Upvotes: 3
Views: 1078
Reputation: 86
In MVC, when the POST-back is "skipped" with a "manual" AJAX call there is no process initiated to refresh/update the HTML on the page. When a manual AJAX request is made, it does not return a view, it returns a response to the AJAX request (as you can see in your code sample). It this response that receives the data needed to update the page without having a full post-back/page refresh. Because this is a manual AJAX request, a manual update using JavaScript must be made to the page’s HTML using the JSON data returned in the response.
It is very similar to using an WebAPI controller action (you send the request, and it sends a response).
Since this is a post action it is best to add the [HttpPost] annotation to the Controller Action. Your data object should be returned to your AJAX request as a JSON object.
[HttpPost]
public IActionResult ApplyDashBoardFilter(string checks, DateTime start, DateTime end)
{
var filters = JsonConvert.DeserializeObject<List<FilterItem>>(checks);
ViewModel vm = new ViewModel();
foreach(var f in filters)
{
vm.AddFilter(f);
}
vm.StartDate = start;
vm.EndDate = end;
return Dashboard(vm);
}
Note that the AJAX request "success" function receives a repsonse argument. This argument should receive the JSON data created by the controller. Use this JSON data along with the necessary JavaScript to update your page's HTML.
function sendFilterData() {
var checks = getFilterSettings(); //stringified JSON
$.ajax({
method: 'POST',
url: '@Url.Action("ApplyDashboardFilter", "Home")',
data: {
checks: checks, start: globalstart.format("YYYY-MM-DD HH:mm:ss"), end: globalend.format("YYYY-MM-DD HH:mm:ss") },
success: function (response) {
//place JavaScript to update your page's HTML here
console.log(response) //use this to test your JSON
},
failure: function (response) {
console.log(response);
}
});
}
Upvotes: 2
Reputation: 75
I think the best approach will be to can use Partial View for rendering the view after applying filter.
Add div with id in you main view:
Create Partial View of that part of Dashboard and return it from the controller. So instead of
public IActionResult ApplyDashBoardFilter(string checks, DateTime start,
DateTime end)
{
var filters = JsonConvert.DeserializeObject<List<FilterItem>>(checks);
ViewModel vm = new ViewModel();
foreach(var f in filters)
{
vm.AddFilter(f);
}
vm.StartDate = start;
vm.EndDate = end;
return Dashboard(vm);
}
You can write
public IActionResult ApplyDashBoardFilter(string checks, DateTime start, DateTime end)
{
var filters = JsonConvert.DeserializeObject<List<FilterItem>>(checks);
ViewModel vm = new ViewModel();
foreach(var f in filters)
{
vm.AddFilter(f);
}
vm.StartDate = start;
vm.EndDate = end;
return PartialView("_DashboardPartial", vm);
}
In success method of ajax, add the partial view to div in main view:
function sendFilterData() {
var checks = getFilterSettings(); //stringified JSON
$.ajax({
method: 'POST',
url: '@Url.Action("ApplyDashboardFilter", "Home")',
data: {
checks: checks, start: globalstart.format("YYYY-MM-DD HH:mm:ss"), end: globalend.format("YYYY-MM-DD HH:mm:ss") },
success: function (response) {
$("#DashboardFilter").html(response)
},
failure: function (response) {
console.log(response);
}
});
}
Tip: You can show loader in DashboardPartial div till the ajax method is not completed.
Upvotes: 0