API Controllers (More Stuff!)

My last post demonstrated a few details that I learned about API controllers.  There was one other detail I forgot to mention.  Serialization.  I ran into an issue involving an API controller that worked OK, and then it quit sending JSON data completely.  I traced it down to the fact that I moved an object to another project (containing most of my business layer code) and I also added some methods to the object.  I discovered that I needed to add the [Serializable] attribute to the objects that I used to pass JSON data.  Like this:

[Serializable]
public class PersonnelType
{
    public string First;
    public string Last;
}


[Serializable]
public class TestType
{
    public int Number;
}

Also, the first sample I used in my previous article used a GET API controller and I named it “PostOne”.  That was a typo on my part, but it does demonstrate that the name of the method doesn’t really matter.

Working With Entity Framework

OK, this week I’m going to try to build something a bit more complex.  I’m going to add an Entity Framework database to the mix and show how you can shuttle data between an AJAX call and an MVC API controller.

First, we need a blank MVC4 project.  Next, add a controller using the technique I demonstrated in the previous article.  Name it HomeController.cs, then add a view to it.  Just use the default name.  Now you can run your program and you should get a basic web page.  Now create a scripts folder and add a personnel.js text file to it.  Put this code in your javascript file:

$(document).ready(function() {
 $.ajax({
  type: “GET“,
  url: “api/Personnel/ReadData“,
  contentType: “json“,
  success: function(personnelData) {
   data = jQuery.parseJSON(personnelData);
   $(‘#resultText‘).val(data[0].first + ‘ ‘ + data[0].last);
  },
  error: function(error) {
   alert(error.responseText);
  }
 });

});

Also, download and add JQuery 2 into your scripts directory.  Then modify your view.cshtml file to this:

<!doctype html>
<html>
    <head>
        <title></title>
        <script src=”~/scripts/jquery-2.1.0.js“></script>
        <script src=”~/scripts/Personnel.js“></script>
    </head>
    <body>
        <div>Test Page</div><br />
        <div><input type=”textid=”resultTextvalue=”” /></div>
    </body>
</html>

Now add another controller.  This time create an API controller and name it PersonnelController.cs.  Leave it blank for now. 

The Database Project

Create a new project in your solution.  Just create a class project and name it “Database” for now.  Right click on your new project and select “add -> New Item”, then select “Data” on the left treeview control and an “ADO.NET Entity Data Model” to your project.  Go through the standard steps of creating a connection and adding a table.  I’m using the person table that I created in an earlier blog box.  I’m also connecting to a SQL database, but you can use whatever database you’re comfortable with.  Once you have added the table and saved your edmx stuff, then you’ll need to copy your app.config settings to the web.config file of your other project.  You’ll have to add all of the config stuff from the app.config file to your web.config file.

Let’s add a PersonData class to the database project and put this code in it:

namespace Database
{
    public class PersonData
    {
        public List<person> ReadData()
        {
            using (var db = new sampledataEntities())
            {
                return (from p in db.people select p).ToList();
            }
        }
    }
}

The purpose of this code is to provide a business object to handle the querying of data and maybe some business computations.  I’m just going to grab all the records in the table and return them as a list. 

Now you need to add the database project to your MVC project.  You can right-click on the References directory in your MVC project and “Add Reference”.  Then select “Projects” on the left and check the database project in the list (it should be the only one there).  Now you can add a “using Database” to your API controller (PersonnelController.cs file) and reference anything in the database project that is public.

Now add a method to your API controller (in the PersonnelController.cs file) using this code:

[HttpGet]
public string ReadData()
{
    PersonData p = new PersonData();
    List<person> data = p.ReadData();

    var json = JsonConvert.SerializeObject(data);
    return json;
}

 
You’ll have to add two usings to the top to make this code compile:

using Database;
using Newtonsoft.Json;

If your code compiles, then run it and see what happens.  You should see the name of one person from your database (assuming you have records in your person table).

You can troubleshoot this app by first putting a cursor in your controller “ReadData()” method and running the app.  This should get called when the JQuery AJAX call is made.  If it doesn’t get there, then you have a problem with your html or your javascript.  It does get there, then it’s time to step through the data read and see if that works.  If you make it to the serializeObject line, then your data should be in the list called “data” (put your cursor of this variable and you can see how many items there are in the list).  Next, you should be able to get through the C# API controller and the program resumes execution at the JQuery AJAX call under the “success” function.  There you can put a breakpoint on the deserializing of the data and you should be able to see a list of items that match the format of the table that was passed from the C# code.  I peeled off the first record (record zero) and used the first and last name.  The names are not trimmed, but this is just for demonstration purposes.

Extending the Data Sent

Let’s pretend we are going to build a CRUD interface now and we need to have an “Edit” and a “Delete” Boolean variable to handle human interaction between the html interface and the C# controller.  Also, let’s assume that some sort of framework like AngularJS is used (though I’m not going to get into that in this article) and it becomes more convenient to have Booleans for each record to track what the user is doing.

So how can we add these in a manner that is easy to troubleshoot and understand?  We could just add the fields to the person table and ignore the data in the database.  That would be a waste of space on the server and we don’t really want to actually store this data because it just tells the controller that the user wants to modify or delete a record (I’m purposely leaving out the “add” operation, just to keep this short, but in reality, you’ll need that function as well). 

There are probably a dozen other “not so cool” methods to get around this problem, such as modifying the JSon text as it is passed between the JQuery and C# controller.  But the method I’m going to demonstrate is easy and clean.  First, add a class to your Database project and name it “PersonExtended.cs”.  Inside this class, you can “append” to the existing person class that is defined in the “person.cs” file (auto-generated by the EF-6 framework when you added the table to your edmx file).  If you open up the “person.cs” file you’ll see that the person class is actually a “partial” class.  Which means that you can declare another “partial” person class anywhere else in your project.  So that’s what I’m going to do.  Here’s the code I used inside the PersonExtended.cs file:

namespace Database
{
    public partial class person
    {
        public bool Edit { get; set; }
        public bool Delete { get; set; }
    }
}


What this code does is add two Boolean properties to the complete class.  These properties are not used by EF, but they can be used by your JQuery, or HTML to exchange user interactions with the API controller.  Once you add the code above, re-compile your project and put a breakpoint in your AJAX return call and examine a record of the data that arrives.  You’ll see the two extra fields inside that data.  You can initialize these variables in the query if you’d like, or you can initialize them in the person object.  Like this:

namespace Database
{
    public partial class person
    {
        public bool Edit { get; set; }
        public bool Delete { get; set; }

        public person() : base()
        {
            Edit = false;
            Delete = false;
        }
    }
}

To confirm these results, run the program with Edit and Delete set to false and check what arrives at the “success” point of your AJAX call.  Then change Edit to true in your initialization code and check what arrives a “success” this time.  You’ll see the values you expect. 

The reason that EF uses partial classes is so you can extend the class to include additional methods and properties without modifying the auto-generated files under the edmx file.  If you were forced to modify the generated class directly, then you would need to modify the T4 script file to insert your changes into the class generation (T4 script files end with tt file types and can be modified to change the way EF generates code). 

You can download the entire project here: MVC4 EF Test Project.

Summary

This project shows how to create an MVC API controller project using JQuery to communicate between a browser and a C# controller.  I also demonstrated how to setup another project to contain an Entity Framework 6 database.  I further showed how to include that project in your MVC project and extend an ORM table object in such a way that it will remain intact if you update your EF edmx file.

I’m currently working on a couple of projects for this blog.  One project includes a sample of AngularJS and the other project has unit testing for API controllers.  These projects will add onto what has been learned in this lesson and the previous lesson.


 

 

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.