MVC–Displaying Content from Ajax calls
This article illustrates two approaches to retrieving content from a service using an Ajax query in the MVC framework. The first calls a method on a controller to paint a partial view. The second retrieves html markup from a Web API controller.
Real World Scenario
For a project I worked on recently a majority of the content needed to be branded depending on the customer who was currently logged in. The solution was to retrieve branded content from Azure storage. For example, terms and conditions or contact us pages. For most of the requirements I used an Web API controller to retrieve the content and I used a partial view when the html contained content updated by a model.
Sample Project
This sample starts with the ASP.NET MVC 4 Web Application template (Internet Application):
http://spikesoftware.azurewebsites.net/wp-content/uploads/2014/01/image_thumb.png
The template provides a simple website having two links: About and Contact.
http://spikesoftware.azurewebsites.net/wp-content/uploads/2014/01/image_thumb1.png
The plan is to retrieve the content of the About via a Web API controller and the Contact via a partial view.
Ajax Web API controller
The project currently does not contain any apicontroller classes so we will add on into the project. To make this sample a little more realistic, the purpose of the controller is to pull static html markup from a repository. The first step is to create a Resources web API controller:
http://spikesoftware.azurewebsites.net/wp-content/uploads/2014/01/image_thumb2.png
By convention, I create these in an Api folder but the folder name is not important
After removing the sample methods provided, I created the following method:
[System.Web.Mvc.OutputCache(Duration = int.MaxValue, VaryByParam = "id")]public HttpResponseMessage Get(string id){ var resource = GetResourceById(id); HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); result.Content = new StringContent(resource); result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("text/html"); return result;}
Because we are not sending a JSON result back we need to return a HttpResponseMessage with the content and the content type. The GetResourceById() method simulates a call to some form of storage. In this example it is just coded to return an html string:
private string GetResourceById(string id){ return "<article><p>Use this area to provide additional information.</p><p>Use this area to provide additional information.</p><p>Use this area to provide additional information.</p></article>"}
The next step is to alter the About view so the content can be placed in a div when the result comes back:
<div id="aboutDiv"></div><img id="aboutImg" src="~/Images/ajax-loader.gif" />
Using jQuery the api controller is retrieved and the result is displayed:
<script type="text/javascript">(function (spike, $) {$.get('/Api/Resources/about',function (data) {$('#aboutDiv').html(data);$('#aboutImg').hide();});}(this.spike = this.spike || {}, jQuery));</script>
Ajax MVC Partial View
To make the Contact example a little more interesting, let's create a new controller, partial view and model for the response. The interesting thing to note is the HomeController will still return the main view but the contact details will be returned from the new controller. Our new controller will be ContactController and will simply return a Contact model with the partial view:
public class ContactController : Controller{ public ActionResult Index() { var model = new Contact { Name = "John Smith", Email = "jsmith@spike.com" }; return PartialView(model); }}
The view itself if simple and uses Razor to apply the model to the markup:
@model Spike.Blog140131.Models.Contact <section class="contact"> <header> <h3>Email @Model.Name</h3> </header> <p> <span class="label">Support:</span> <span><a href="mailto:@Model.Email">@Model.Email</a></span> </p></section>
The javascript uses a similar structure and calls the Contact controller directly to get the partial view result:
<script type="text/javascript"> (function (spike, $) { $.get('/Contact/Index', function (data) { $('#contactDiv').html(data); $('#aboutImg').hide(); }); }(this.spike = this.spike || {}, jQuery));</script>
The complete project is here: Spike.Blog140131