Creating Javascript Proxy to Call ASP.NET MVC Controller Action

One of the most used routine when developing a WEB application is calling an action using jQuery AJAX. This post will show you how to make this task easier and more natural in the format SomeController.SomeAction(parameters).

First let´s create a BaseController that will have an Action called ActionScript, this action will return a Javascript object with all controller methods, each method will make an AJAX to an action using jQuery. This method is a little extensive but will done all the job for you, inslusive if an action has HttpPost attribute the AJAX will make using POST type by default.

public abstract class BaseController : Controller
{
    public ActionResult ActionScript()
    {
        var sb = new StringBuilder();
        var reflectedController = new ReflectedControllerDescriptor(this.GetType());

        sb.Append("var " + reflectedController.ControllerName + "Controller = {\n");

        var actions = reflectedController.GetCanonicalActions();

        for (var i = 0; i < actions.Length; i++)
        {
            if (i > 0)
                sb.AppendLine(",");

            sb.AppendFormat("\t{0}: function(", actions[i].ActionName);

            var parameters = actions[i].GetParameters();

            for (var j = 0; j < parameters.Length; j++)
            {
                if (j > 0)
                    sb.Append(", ");
                sb.Append(parameters[j].ParameterName);
            }

            sb.AppendLine((parameters.Length > 0 ? ", " : String.Empty) + "ajaxOptions) {");

            sb.AppendLine("\t\tvar aOptions = {};");
            sb.AppendLine("\t\tif(ajaxOptions == undefined) {");
            sb.AppendLine("\t\t\tajaxOptions = {};");
            sb.AppendLine("\t\t}");

            sb.AppendLine("\t\tvar data = { };");

            for (var j = 0; j < parameters.Length; j++)
            {
                sb.AppendLine("\t\tif(typeof " + parameters[j].ParameterName + " == \"object\") {");
                sb.AppendLine("\t\t\t$.each(" + parameters[j].ParameterName + ", function(k, v) {");
                sb.AppendLine("\t\t\t\tdata[k] = v;");
                sb.AppendLine("\t\t\t});");
                sb.AppendLine("\t\t} else {");
                sb.AppendLine("\t\t\tdata." + parameters[j].ParameterName + " = " + parameters[j].ParameterName + ";");
                sb.AppendLine("\t\t}");
            }

            sb.AppendLine("\t\taOptions.type = \"" + (actions[i].GetCustomAttributes(typeof(HttpPostAttribute), false).Length > 0 ? "POST" : "GET") + "\";");
            sb.AppendLine("\t\taOptions.cache = false;");
            sb.AppendLine("\t\taOptions.data = data;");
            sb.AppendLine("\t\taOptions.url = \"" + Url.Action(actions[i].ActionName, reflectedController.ControllerName) + "\";");
            sb.AppendLine("\t\taOptions.success = function(result) { };");
            sb.AppendLine("\t\taOptions.error = function(xhr) { };");
            sb.AppendLine("\t\tvar ajaxSettings = $.extend({}, aOptions, ajaxOptions);");
            sb.AppendLine("\t\t$.ajax(ajaxSettings);");

            sb.Append("\t}");
        }

        sb.AppendLine();
        sb.Append("};");

        return File(ASCIIEncoding.ASCII.GetBytes(sb.ToString()), "text/javascript");
    }
}

Now let´s create a controller and use the BaseController as the base class.

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

    public ActionResult Ajax1()
    {
        return Json(new { text = "Hello World" }, JsonRequestBehavior.AllowGet);
    }

    public ActionResult Ajax2(string text)
    {
        return Json(new { text = "Hello World " + text }, JsonRequestBehavior.AllowGet);
    }

    [HttpPost]
    public ActionResult Ajax3(string text1, int number)
    {
        return Json(new { text = "Post data " + text1 + " " + number });
    }

    public ActionResult Ajax4(SomeClass someClass)
    {
        return Json(new { text = "Name " + someClass.Name + " " + someClass.Age }, JsonRequestBehavior.AllowGet);
    }
}

And below how to call each method of the controller using the proxy. Don´t forget to add the jQuery file reference and another script referencing the ActionScript action.

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title - My ASP.NET Application</title>
    <script src="~/Scripts/jquery.min.js"></script>
    <script type="text/javascript" src="@Url.Action("ActionScript")"></script>
    <script type="text/javascript">
        HomeController.Ajax1({
            success: function (result) {
                alert(result.text);
            }
        });

        HomeController.Ajax2("Murilo", {
            success: function (result) {
                alert(result.text);
            }
        });

        HomeController.Ajax3("Murilo", 27, {
            success: function (result) {
                alert(result.text);
            }
        });

        HomeController.Ajax4({ name: "Murilo", age: 27 }, {
            success: function (result) {
                alert(result.text);
            }
        })
    </script>
</head>
<body>
</body>
</html>

As you can see, all actions are called using HomeController.ActionName([parameter1, parameter2, …], ajaxOptions). The ajax options, in our case we used just the success, can be any jQuery allowed option, if you want to handle error and make the AJAX synchronous you could done like below.

HomeController.Ajax2("Murilo", {
    success: function (result) {
        alert(result.text);
    },
    async: false,
    error: function (xhr) {

    }
});

The action Ajax3 has a complex object parameter with two properties Name and Age, in this case the complex parameter is passed using an object { name: “Murilo”, age: 27 }. If the action has more parameters after or before the complex one, just separate each one with comma HomeController.SomeAjax(“Parametro1”, 35, { name: “Murilo”, age: 27 }, 40).

If you want to reference another controller proxy, in the line

<script type="text/javascript" src="@Url.Action("ActionScript")"></script>

set the controller you want

<script type="text/javascript" src="@Url.Action("ActionScript", "Home")"></script>

In this post we saw how to increase productivity creating controller Javascript object proxy to use in AJAX call.

Anúncios
Creating Javascript Proxy to Call ASP.NET MVC Controller Action

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s