October 2017 : Online course in ASP.NET MVC / Core. Conducted by Bipin Joshi. Read more...
Registration for October 2017 batch of ASP.NET MVC / Core online course has already started. Conducted by Bipin Joshi. Book your seat today ! Click here for more details.

AngularJS Directive That Invokes ASP.NET MVC Action

Recently one of the readers asked whether an AngularJS directive can invoke ASP.NET MVC actions. This article shows how a simple AngularJS directive can be created that invokes an ASP.NET MVC action using Ajax.

Usually an AngularJS directive is used to perform some UI centric operation. However, nothing prevents an AngularJS directive from invoking some server side code (say an action method) to get some job done. There are two approaches to developing such a directive:

  • The directive can directly talk to the server using $http service.
  • The directive can talk to a custom service that in turn makes an Ajax call using $http.

If the directive is quite simple you may go by the first approach. However, this will mix the UI related concerns and the server communication related concerns in the directive code. So, for real-world application isolating server communication in a service and then consuming that service from a directive would be more appropriate. This article shows you both the approaches.

Let's assume that you wish to create a custom AngularJS directive that displays server side date and time stamp in the browser. You wish to use the custom directive in your markup as follows:

<server-time-stamp></server-time-stamp>

Once the page is loaded, the directive code gets executed and server side date and time stamp is displayed inside the above markup element.

Begin by creating a new ASP.NET MVC application using Visual Studio. Add HomeController and Index view to the application as usual. Then add the following action to the Home controller.

public ActionResult GetServerTimeStamp()
{
    return Json(DateTime.Now.ToString(
           "yyyy-MM-dd hh:mm:ss"), 
           JsonRequestBehavior.AllowGet);
}

The GetServerTimeStamp() action is quite straightforward. It simply returns current date and time in ISO format. Notice the use of Json() method to convert the date-time stamp into JSON format.

The custom directive will invoke this action through Ajax. Then add a <script> reference to the AngularJS in the Index view and also add an empty <script> block.

<script src="~/Scripts/angular-1.5.js"></script>

<script>

<script>

Then define a new module using AngularJS module API as shown below:

 var app = angular.module("MyApp", []);

The above line of code creates a module named MyApp. Then create a custom directive inside the MyApp module. This is done as follows:

app.directive("serverTimeStamp", function ($http) {
    var obj = {};
    obj.restrict = "E";
    obj.link = function ($scope, element, attrs) {
        var promise = $http.get("/home/getservertimestamp")
        .success(function (timestamp) 
          { element.append("<h1>" + timestamp + "</h1>"); })
        .error(function () { alert('Error'); });
    };
    return obj;
});

The above code creates a directive named serverTimeStamp. Note that the serverTimeStamp is used in the markup as <server-time-stamp>. The serverTimeStamp directive receives the $http service for making Ajax calls.

An empty object - obj - is then created to store the directive's definition. The restrict property indicates that the directive can be used only as an Element (E).

The link property points to a function that gets invoked during the link phase. This function is responsible for making an Ajax call to the GetServerTimeStamp() action you created earlier. The link function calls the get() method on $http to make a GET request to the /home/GetServerTimeStamp action. The success callback function receives the server side date-time stamp as its parameter and appends it to the directive element (<server-time-stamp>). Note that element parameter of the link function gives the reference of the DOM element representing the directive. The error callback simply displays the error message (if any) in an alert dialog.

The object containing the directive's definition is then returned from the directive function.

Now, add the following markup to the Index view.

<html ng-app="MyApp">
...
...
<body>
    <server-time-stamp></server-time-stamp>
</body>
</html>

The <html> tag has ng-app attribute that specifies the module's name - MyApp. The body of the document contains the directive's markup as discussed earlier.

If you run the application, you should see a timestamp in the browser as shown below:

If you observe the DOM using F12 tools you will see something like this:

 Ok. Now let's move ahead and isolate the Ajax communication in a service. Our custom directive will then invoke this service.

Add the MyService in the <script> block as shown below.

app.service("MyService", function ($http) {
    this.GetTimeStamp = function (callback) {
        var promise = $http.get(
                      "/home/getservertimestamp")
                      .success(function (timestamp) 
                       { callback(timestamp); })
                      .error(function () 
                       { alert('Error'); });
    };
});

The above code creates a service named MyService. The service receives $http service to make Ajax calls. Inside, the MyService defines a single function - GetTimeStamp() - that will be called by the clients (directive in this case). The GetTimeStamp() function accepts a callback function. This callback is invoked upon successfully receiving the server side date-time. The code then invokes /home/GetServerTimeStamp action as before. This time the success callback simply invokes the callback received as the parameter.

Next, modify the serverTimeStamp directive as shown below:

app.directive("serverTimeStamp", function (MyService) {
    var obj = {};
    obj.restrict = "E";
    obj.link = function ($scope, element, attrs) {
        MyService.GetTimeStamp(
          function (timestamp) 
          { 
           element.append("<h1>" + timestamp + "</h1>"); 
          });
    };
    return obj;
});

Notice that the serverTimeStamp directive no longer accepts $http parameter. Instead, it accepts MyService as the parameter. Inside, the link function now invokes the GetTimeStamp() method on the MyService. The callback function appends the server date-time stamp to the directive element as before.

If you run the application you should get similar results as in the previous case.

Keep coding !!


Bipin Joshi is a software consultant, an author and a yoga mentor having 22+ years of experience in software development. He also conducts online courses in ASP.NET MVC / Core and Design Patterns. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Meditation and Mindfulness to interested individuals. To know more about him click here.

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 14 March 2016


Tags : ASP.NET C# JavaScript