API Controllers

Introduction

For those who follow my blog, you’ll remember that I have been working on a project using the Visual Studio MVC 4 framework.  I spent a considerable amount of time researching how the pieces of this framework fits together and I’ve discovered some nuances.  Many of these tricks I learned after starting the real project and attempt to get some real (as in, not research) work done.  So this post will cover the API Controller.


Getting Started

To begin this test example, we’ll need a new MVC 4 empty project.  You can refer to my previous post on how to create this.  Once you have an empty project, create an empty MVC controller in the “Controllers” directory (right-click on the “Controllers” directory and select “Add -> Controller”, then name it “HomeController” (make sure it’s an empty MVC controller type).  Then right-click on the View() method and “add view”.  Just leave it named “Index”.

OK, now we’re going to delete everything in the Index.cshtml file and make it look like this (you can just paste this into it):

<!doctype html>
<html>
  <head>
    <title></title>
    <script src=”~/scripts/jquery-2.0.3.js“></script>
    <script src=”~/scripts/homescript.js“></script>
  </head>
  <body>
      <div>
        <input type=”submitvalue=”Test 1id=”TestController1“/><br/>
        <input type=”submitvalue=”Test 2id=”TestController2“/><br/>
        <input type=”submitvalue=”Test 3id=”TestController3“/><br/>
        <input type=”submitvalue=”Test 4id=”TestController4“/><br/>
      </div>
  </body>
</html>



Now you’ll need a javascript file and you’ll need JQuery.  Download the JQuery JS file from JQuery.com.  I’m using version 2 for this demo, I’m pretty sure you can use either version.  We’re only going to use it for the AJAX capabilities.  Create a “scripts” directory and copy the JQuery.js file into that directory and also create an empty js file called “homescript.js” in the “scripts” directory:


Now, our JS file will start with this code:

$(document).ready(function() {

$(“#TestController1“).click(function() {

});

$(“#TestController2“).click(function() {

});

$(“#TestController3“).click(function() {

});

$(“#TestController4“).click(function() {

});

});

Next, we’ll need to add an API Controller, then we can get started.  Right-click on the “Controllers” directory and select “Add -> Controller”, then select an empty API Controller type.  Name it “DemoController”.  I’ll be adding two classes that I’ll just use as containers of information to pass back and forth using JSON.  Your API controller should look like this (I left out the usings for clarity):

namespace MvcApiControllerBlogSample.Controllers
{
    public class PersonnelType
    {
        public string First;
        public string Last;
    }

    public class TestType
    {
        public int Number;
    }

    public class DemoController : ApiController
    {

    }

}

Now it’s time to get down to business.  My first test will be very simple and should work out of the box.  First, I’m going to add some code to the homescript.js file (inside the first click function:

$(“#TestController1“).click(function() {
    $.ajax({
        type: “GET“,
        url: “api/Demo?account=TEST“,
        success: function() {

        },
        error: function(error) {
            alert(error.responseText);
        }
    });

});

Next, I’ll add a small method in the API Controller code:

public class DemoController : ApiController
{
    [HttpGet]
    public void PostOne(string account)
    {
        string result = account;
    }
}

Put a breakpoint on the line in your controller where the string “result” is assigned “account”.  Then run the application and click the first button.  You should see your program run to the breakpoint.  Now examine the text inside “account”.  It should be “TEST”.

When referring to a controller, you use the first part of the controller name (i.e. this one is called “DemoController”, but we call it “Demo” in the URL string above).  You also need to use “api” in the path name.  If you open the WebApiConfig.cs file, you’ll see a route that specifies this route:

api/{controller}/{id}

Notice the first part of the path is “api” with no braces around it.  That specifies that the first part of the path must start the word “api”.  The second parameter is the controller name, and the third parameter is an id (used by a post operation), which could also be setup as a URL parameter like I did in the above example (for post operations, a get operation always uses the URL convention like that listed above).

So now we constructed a simple “get” operation involving a parameter.  You can add more parameters just like you would add to a URL anchor link (separating with and symbols).  

Now let’s try our hand at a POST operation.  Add this code to your second controller in the homescript.js file:

$(“#TestController2“).click(function() {
    var temp = { First: ‘Joe‘, Last: ‘Smith‘ };

    $.ajax({
type: “POST“,
  url: “api/Demo/SavePersonnel/test“,
  contentType: “application/json“,
  data: JSON.stringify(temp),
success: function() {

},
error: function(error) {
            alert(error.responseText);
}
    });
});

And in the API controller:

public class DemoController : ApiController
{
    [HttpGet]
    public void PostOne(string account)
    {
        string result = account;
    }

    [HttpPost]
    [ActionName(“SavePersonnel“)]
    public HttpResponseMessage ThisMethodNameDoesntMatter(string id, PersonnelType record)
    {
        return Request.CreateResponse(HttpStatusCode.OK, record);
    }

}

The first thing you might notice is the “ActionName” attribute added to the “ThisMethodNameDoesntMatter” method.  This will be used to specify that this post action will be executed by the ajax call in the javascript when specifically cited (see the “SavePersonnel” inside the “URL” specification in the javascript above).  If you execute this code as it is, it will fail.  That’s because we need to add a route to the WebApiConfig.cs file, which should now look like this:

namespace MvcApiControllerBlogSample
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: “DefaultApi“,
                routeTemplate: “api/{controller}/{id}“,
                defaults: new { id = RouteParameter.Optional }
            );

            // Controllers with Actions
            // To handle routes like `/api/VTRouting/route`
            config.Routes.MapHttpRoute(
                name: “ControllerAndAction“,
                routeTemplate: “api/{controller}/{action}/{id}
            );
        }
    }

}

Now you can run this application and click on the second button.  If you put a breakpoint inside the “ThisMethodNameDoesntMatter” method, you’ll see that the program stops at that point and the record will contain the first and last name hard-coded in the javascript.  For a real-world application, you can feed your text fields into these javascript variables before calling the ajax command.  You’ll also notice that the id has been filled in with “test”.  This is an optional configuration.  You do not have to setup your controller to accept an id or any url parameters when a post is issued.  I’ll show you that next.

On to the third example.  Let’s add code to the javascript file for “TestController3”:

$(“#TestController3“).click(function() {
    var temp = { Number: ‘5‘ };

    $.ajax({
type: “POST“,
url: “api/Demo/SaveTestType/Ignore“,
contentType: “application/json“,
data: JSON.stringify(temp),
success: function() {

},
error: function(error) {
           alert(error.responseText);
}
    });
});

And for the controller add this method after the last one:

[HttpPost]
[ActionName(“SaveTestType“)]
public HttpResponseMessage doesntmatter(TestType testrec)
{
    return Request.CreateResponse(HttpStatusCode.OK, testrec);

}

Now run this program with a breakpoint inside the “doesntmatter” method and you’ll see that “testrec” will contain the number “5”.  Also, you’ll notice that there is no id passed, but you’ll still need to specify an id (I called it “Ignore”) in the javascript.  This is to ensure a proper pattern match with the routing that has been defined in the WebApiConfig.cs file.  One last example, to demonstrate that you can have two controller methods with the same parameters but called from different ajax calls.  Create this code for your “TestController4” javascript:

$(“#TestController4“).click(function() {
    var temp = { Number: ‘9‘ };

    $.ajax({
type: “POST“,
url: “api/Demo/SaveTestType2/Ignore“,
contentType: “application/json”,
data: JSON.stringify(temp),
success: function() {

},
error: function(error) {
           alert(error.responseText);
}
    });
});

And finally for the controller:

[HttpPost]
[ActionName(“SaveTestType2“)]
public HttpResponseMessage doesntmatter2(TestType testrec)
{
    return Request.CreateResponse(HttpStatusCode.OK, testrec);

}

Now, if you put a breakpoint inside each C# controller method, you can click on each button (Test 1 through Test 4) and see your program stop at the correct controller.  You can also see that the “doesntmatter2” method contains a “9” instead of a “5”.  So we know that the correct parameter is being passed.

One other thing to notice (if you haven’t noticed already), is that the method names in the controller don’t mean anything.  You can give them descriptive names for your own identifying purposes.  The name in the “ActionName” attribute is what controls which method is called from the post.  Without this attribute, you will need to create post methods with different parameters so the controller knows which one to match.  Also, I’m betting it’s possible to manipulate the routing to set up a pattern where you don’t need the “Ignore” parameter in your ajax call.  I have yet to dig deeper into the routes.  When I get that nailed down, I’ll do another blog post and report what I’ve discovered.  There are also other types of controllers, like a DELETE and a PUT controller, which I did not include in this blog post.

Summary

The four sample API controllers that I have presented are a test project that I set up to reverse engineer what I needed in order to make my application run.  Sometimes you have to create a small test with just the bare essentials to see how things interact with each other.  Otherwise, you can waste a lot of time trying to get something simple to work because it is buried in a lot of other program clutter (which could be conflicting with your code).  Now that I’ve figured out the very basics, I’ll keep this little program handy for further testing.  I hope this helps you get rolling without going through all the pain I did when I attempted to make this work.









 

Leave a Reply