How do I use a controller action to update a model without navigation?
I have an MVC 5 website that displays the entries in a log file in a grid and provides a search facility. I have both search criteria and grid.mvc in the index page. When the user enters search criteria and clicks the submit button, I want the ProcessLogEntries method (below) to update the model and refresh the Index.cshtml page - don't go to the nonexistent ProcessLogEntries page!
Basically, I want this app to behave like a single page app ...
How do I set up the HomeController.ProcessLogEntries () method for this?
public class HomeController : Controller
{
public LogsResearchViewModel ViewModel { get; set; }
public HomeController()
{
ViewModel = new LogsResearchViewModel();
}
public ActionResult Index()
{
ViewBag.Message = "";
return View(ViewModel);
}
[HttpPost]
public ActionResult ProcessLogEntries(string txtSearchFor, string txtDateStart, string txtDateStop, string txtSource)
{
ViewBag.Message = "";
string searchFor = txtSearchFor.ToString();
DateTime start = DateTime.Parse(txtDateStart.ToString());
DateTime stop = DateTime.Parse(txtDateStop.ToString());
string source = txtSource.ToString();
ViewModel.GetProcessLogEntries(searchFor, start, stop);
ViewModel.GetErrorLogEntries(source, searchFor, start, stop);
return View(ViewModel);
}
}
source to share
If you want to refresh the page without reloading, you need AJAX. Here's a diagram to get you started.
Partial view
Create a main view that will act as a "frame". An empty div will serve as your placeholder for your grid.
<h2>Main View</h2>
<div id="grid"><!-- grid paceholder --></div>
<script>
// ajax script here
</script>
Now create a partial view to hold the mesh
_GridPartial
@model LogsResearchViewModel
@Html.Grid(Model)
<button id="btnTrigger">Process</button>
If you want, you can embed this so that the first time you load the Main view, you will have a filled grid.
<h2>Main View</h2>
<div id="grid">@{Html.RenderAction("LoadGrid")}</div>
With supportive action
public ActionResult LoadGrid()
{
var model = new LogsResearchViewModel() { ... };
return PartialView("_GridPartial", model);
}
Now set up AJAX to insert into placeholder.
<script>
$("#grid").on("click", "#btnTrigger", function(e) {
$.ajax({
url: "/ProcessLogEntries",
type: "post",
data: {
txtSearchFor: "// txtSearch.val()",
txtDateStart: "",
txtDateStop: "",
txtSource: ""
}
})
.done(function(result) {
$("#grid").html(result);
});
});
</script>
And the action returns a partial view
[HttpPost]
public ActionResult ProcessLogEntries(
string txtSearchFor, string txtDateStart,
string txtDateStop, string txtSource)
{
var model = new LogsResearchViewModel();
// ...
return PartialView("_GridPartial", model);
}
After running the post, the partial result replaces the content of the div grid.
Json
If your grid supports JSON, just return the model
[HttpPost]
public ActionResult ProcessLogEntries(...)
{
var model = new LogsResearchViewModel();
// ...
return Json(model);
}
Then process in javascript
...
.done(function(jsonResult) {
console.log(jsonResult); // should match LogsResearchViewModel
loadGrid(jsonResult); // pass off to grid javascript
});
source to share
You will need to return your model. You can store your view and retrieve the javascript model from the view, or you can have a JsonResult and only return the serialized string.
From the javascript side, activate this with a button or event of your desire.
var params = ["data","data", "data"];
$.ajax({
type: "POST",
url: /ProcessLogEntries,
data: params,
success: function(data, statusRespoonse, xhr){
//extract your model from data or return your model via jsonresult by changing the Controller return type.
yourModel = data;
},
dataType: "json"
});
source to share