K.Eriksson
K.Eriksson

Reputation: 25

How to apply single page application functionality on parts of asp.NET MVC3 projects?

So I'm creating a asp.NET MVC3 application and want to apply single page application functionality to parts of the application. I think the easiest way to explain is with an example:

The app consists of an admin area and a public area and is built using ordinary link-structure. I want to convert the admin area to an single page application reusing view and models from the existing application. Is it possible to do this and in that case how?

Upvotes: 1

Views: 867

Answers (1)

OzB
OzB

Reputation: 2221

You have to face two main problems, which makes the difference between SPA and standard application:

  • Links: In standard application, each link redirects you to a different page.
  • Forms: When a form is been submitted, a request is been issued with the HTTP method you've specified in the post (usually POST) and it contains in the payload the data the user has entered.

In order to solve that problems, you have to take action both in client-side and server-side. For explaining propose, lets take the following code:

HomeController.cs:

public class HomeController : Controller {
    public ActionResult Index() {
        return View();
    }

    public ActionResult Contact() {
        return View(new ContactUsViewModel());
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Contact(ContactUsViewModel model) {
        if (ModelState.IsValid) {
            /* Send mail / Save in DB etc. */
            return Redirect("Index");
        }

        return View(model);
    }
}

Index.cshtml:

<p>This is a simple page.</p>
<p>@Html.ActionLink("Click here to contact us", "Contact")

Client-Side: We should fix up linking between pages, as well as forms submittions.

  • Links: You can wire up an event in JS (jQuery if you'd like) that'll observe for each link click in the areas you'd like to apply on SPA - then, instead of redirecting the user - you'll load the content via AJAX. For instance, take a look at this sample:

    $("a").click(function(e) {
        e.preventDefault(); // Disable standard redirecting
        var href = $(e.currentTarget).attr("href");
    
        $.get(href, function(responseText) {
            $("#main-content-wrapper").html(responseText);
        });
    });
    
  • Forms: Just like in the approch we've used for links, we can wire up an observer to the form submit event in JS and then transfer the data using AJAX. For instance:

    $("form").submit(function(e) {
        e.preventDefault(); // Disable standard submittion
        var data = $(e.currentTarget).serialize(); // Serializing the form data
        var method = $(e.currentTarget).attr("method");
        if (typeof (method) == "undefined") { method = "POST"; }
    
        $.ajax({
            method: $(e.currentTarget).attr("method"),
            parameters: data,
            statusCodes: {
                404: function() { /* Handle it somehow */ }
                403: function() { /* Handle it... */ }
                200: function(response) {
                    /* Since we've done a form submittion, usurally if we're getting standard OK (200) status code - we've transffered a data - such as JSON data - indicating if the request success or we got errors etc. The code you're writing here depends on how your current application works. */
                },
        });
    });
    

Server-Side: Since you don't wish to break your current application logic - you have to still be able to use standard ASP.NET MVC methods - such as View(), Redirect() and so on. In this case, I recommend to create your own custom base Controller class - which will override ASP.NET basic implementation.

For instance, this is a starting point:

public class MyController : System.Web.Mvc.Controller {
    public override View(string viewName) {
        if (Request.IsAjaxRequest()) {
            return PartialView(viewName); // If this is an AJAX request, we must return a PartialView.
        }
        return base.View(viewName);
    }
}

Few things you have to keep in mind:

  • You have to somehow distinguish between standard requests and AJAX requests - the way I've used with Request.IsAjaxRequest() is a great way to do so.
  • Many times when you're handling a form, In the form submittion action, after you finish with the form logic, you're using Redirect() to redirect the user to another page. As you may have guessed, you can't take this approch when developing SPA. However, I can think of few solutions for this problem:
    • You can create a status handler in the JS code so when redirecting is been issued by the server - you can load the content via AJAX / display a message and so on.
    • You can override Redirect() and add a specific logic to perform in case of redirection when the request was done by AJAX - for instance, you can request from ASP.NET to perform the action that you're going to be transfered into and then return its content etc.
    • You can decide that although its an SPA app - when a redirect was issued - you allows the server to perform this redirection.

As you can see - there're many approches you can take, and they depends on the way you've developed your site, how you wish it to work and what is the basic rules you're defining (e.g. "No redirection is permitted never - even after submitting a form", "After form submittion - always in case that the operation success - I'm displaying a message or performing other JS action. Because of that, I can override Redirect() and if this is an AJAX request I can return a JSON object." etc.)

Upvotes: 2

Related Questions