The next feature I wanted to handle moving my contacts application from ASP.NET 4 to ASP.NET 5 was not doing a full page refresh when applying a filter. For my implementation in ASP.NET 4 check out the Partial View and Partial View with AJAX posts.
For the partial view there is currently no menu choice but it is easy enough to create the view manually. In fact my _ContactList.cshtml looks exactly as it did in ASP.NET 4.
Rendering a partial view has changed slightly to use an async using await. The following is what replaced the contact list display in the contact index page.
<div id="contactList"> @{ await Html.RenderPartialAsync("_ContactList"); } </div>
At this point I was ready to add in AJAX to refresh my partial view when the user changes filters. In ASP.NET 4 there was the Ajax.BeginForm helper for making Ajax requests, but this does not currently exist in ASP.NET 5.
After a lot of searching I came across the jquery-ajax-unobtrusive github repo. This is the same library that was being used by Ajax.BeginForm ASP.NET 4 and it is available using Bower which ASP.NET 5 and Visual Studio 2015 have great support for.
Just by adding the following line to the dependencies section of my project’s bower.json the needed files were automatically download. The great thing about making edits in bower.json is that intellisense works!
"jquery-ajax-unobtrusive": "3.2.3"
The next step was to add the following line to the copy task in my project’s gulpfile.js.
"jquery-validation-unobtrusive": "jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"
I spent a good bit of time getting the gulp task to work. This is my first usage of gulp and at this point I still don’t know if there is an indicator that the copy failed other than the file the file not being at the specified location. My problem ended up being a typo of a dot instead of a dash.
With jquery-ajax-unobtrusive.js file in place the script needs to be include in _Layout.cshtml found in the Views\Shared folder. In _Layout.cshtml you will notice sections have been added for different environments. For the time being I have only change the scripts Development section with the following.
<script src="~/lib/jquery-ajax-unobtrusive/jquery.unobtrusive-ajax.js"></script>
The Staging and Production environment share the same set of script sources by default but can be separated if needed. The default setup also uses a CDN to pull scripts from by default with fallbacks to the local version. Before an actual deployment make sure to include jquery-ajax-unobtrusive.js in the Staging and Production environments.
Back in Contacts\Index.cshtml the filter form needs to change to the following.
@using (Html.BeginForm("Index", "Contacts", FormMethod.Post, new { id = "filterButton", data_ajax = "true", data_ajax_method = "POST", data_ajax_mode = "replace", data_ajax_update = "#contactList" })) { <p> @Html.TextBox("Filter") <input type="submit" value="Filter"/> </p> }
This is the standard Html.BeginForm with some added HTML attributes to support the Ajax call. The data_ajax* work because of jquery-ajax-unobtrusive. To get the values needed I ran the ASP.NET 4 version of my application and used view source to determine what values I needed. If you take the approach you will notice in the view source from the browser the data attributes will contain dashes which need to be changed to underscores for use in a razor view.
The last bit that needs to change is the index action of the contacts controller.
public IActionResult Index(string filter) { var contacts = from c in _db.Contacts select c; if (!string.IsNullOrEmpty(filter)) { contacts = contacts.Where(c => c.Name.Contains(filter) || c.Address.Contains(filter) || c.City.Contains(filter) || c.Email.Contains(filter) || c.Phone.Contains(filter) || c.State.Contains(filter) || c.ZipCode.Contains(filter)); } if (Request?.Headers != null && Request.Headers["X-Requested-With"] == "XMLHttpRequest") { return PartialView("_ContactList",contacts); } return View(contacts); }
The only gotcha here when moving from ASP.NET 4 is that the request object does not currently contain an IsAjaxRequest extension. Checking the X-Requested-With key of the request headers for XMLHttpRequest indicates an ajax request and triggers the return of the _ContactList partial view.
You should now have a working ajax request. It took me a while to get this all worked out I hope it saves you some time. Information on ASP.NET 5 can be sparce, but this will improve over time.
AJAX with ASP.NET 5: I am using the Html.BeginForm and have it working to return the data, however, I am using datatables to format my table to be updated, and I do not get the page to display the formatting for the table after execution. In prior versions the UpdateTargetId was a div used to load the partial view; however, in ASP.NET 5, I have to supply the data_ajax_update value with the id for the table. I am using “datatables.net”: “1.10.10”. If help would be greatly appreciated.
Kathy can you post the actual code for your Html.BeginForm and the associated sections of the HTML?
Thanks for responding. I was able to find the correct ajax command to help me. Here is what I am doing that now works to correctly display the DataTable:
1) Create dialog success function will destroy datatable
success: function (result) {
if (result.success) {
$(‘#btnSubmit’).submit();
$(“#create-dialog”).html(result).dialog(‘close’);
oTable.destroy();
}
else {
$(“#create-dialog”).html(result).dialog(‘open’);
}
2) Loading partial view will call function on completion to reset the datatable on the id for the table in the partial view
@using (Html.BeginForm(“StatusTypePost”, “Administration”, FormMethod.Post, new
{
id = “MySolutoin.ViewModels.Administration.StatusTypeViewModel”,
data_ajax = “true”,
data_ajax_method = “Post”,
data_ajax_mode = “replace”,
data_ajax_update = “#statustype”,
data_ajax_complete = “dataTableReset”
}))
{
@Html.AntiForgeryToken()
}
Corrected code for partial view load
@using (Html.BeginForm(“StatusTypePost”, “Administration”, FormMethod.Post, new
{
id = “MySolutoin.ViewModels.Administration.StatusTypeViewModel”,
data_ajax = “true”,
data_ajax_method = “Post”,
data_ajax_mode = “replace”,
data_ajax_update = “#statustype”,
data_ajax_complete = “dataTableReset”
}))
{
@Html.AntiForgeryToken()
}
input value=”Submit” id=”btnSubmit” type=”submit” class=”hideme” /
Glad to hear you found the answer. Thank you for taking the time to share it!
Man this blog post is a lifesaver for me :)
I was just thinking about converting my MVC 6 RC1 project back to MVC 5.
Great to hear Anzhe!