Web APIs with CORS

Summary

I’ve done a lot of .Net Web APIs.  APIs are the future of web programming.  APIs allow you to break your system into smaller systems to give you flexibility and most importantly scalability.  It can also be used to break an application into front-end and back-end systems giving you the flexibility to write multiple front-ends for one back-end.  Most commonly this is used in a situation where your web application supports browsers and mobile device applications.

Web API

I’m going to create a very simple API to support one GET Method type of controller.  My purpose is to show how to add Cross Origin Resource Sharing CORS support and how to connect all the pieces together.  I’ll be using a straight HTML web page with a JQuery page to perform the AJAX command.  I’ll also use JSON for the protocol.  I will not be covering JSONP in this article.  My final purpose in writing this article is to demonstrate how to troubleshoot problems with APIs and what tools you can use.

I’m using Visual Studio 2015 Community edition.  The free version.  This should all work on version 2012 and beyond, though I’ve had difficulty with 2012 and CORS in the past (specifically with conflicts with Newtonsoft JSON).

You’ll need to create a new Web API application.  Create an empty application and select “Web API” in the check box.  

Then add a new controller and select “Web API 2 Controller – Empty”.

Now you’ll need two NuGet packages and you can copy these two lines and paste them into your “Package Manager Console” window and execute them directly:

Install-Package Newtonsoft.Json
Install-Package Microsoft.AspNet.WebApi.Cors

For my API Controller, I named it “HomeController” which means that the path will be:

myweburl/api/Home/methodname

How do I know that?  It’s in the WebApiConfig.cs file.  Which can be found inside the App_Start directory.  Here’s what is default:

config.Routes.MapHttpRoute(
    name: “DefaultApi“,
    routeTemplate: “api/{controller}/{id}“,
    defaults: new { id = RouteParameter.Optional }
);

The word “api” is in all path names to your Web API applications, but you can change that to any word you want.  If you had two different sets of APIs, you can use two routes with different patterns.  I’m not going to get any deeper here.  I just wanted to mention that the “routeTemplate” will control the url pattern that you will need in order to connect to your API.

If you create an HTML web page and drop it inside the same URL as your API, it’ll work.  However, what I’m going to do is run my HTML file from my desktop and I’m going to make up a URL for my API.  This will require CORS support, otherwise the API will not respond to any requests.

At this point, the CORS support is installed from the above NuGet package.  All we need is to add the following using to the WebApiConfig.cs file:

using System.Web.Http.Cors;

Then add the following code to the top of the “Register” method:

var cors = new EnableCorsAttribute(“*“, “*“, “*“);
config.EnableCors(cors);


I’m demonstrating support for all origins, headers and methods.  However, you should narrow this down after you have completed your APIs and are going to deploy your application to a production system.  This will prevent hackers from accessing your APIs.

Next, is the code for the controller that you created earlier:

using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebApiCorsDemo.Models;
using Newtonsoft.Json;
using System.Text;

namespace WebApiCorsDemo.Controllers
{
    public class HomeController : ApiController
    {
        [HttpGet]
        public HttpResponseMessage MyMessage()
        {
            var result = new MessageResults
            {
                Message = “It worked!
            };

            var jsonData = JsonConvert.SerializeObject(result);
            var resp = new HttpResponseMessage(HttpStatusCode.OK);
            resp.Content = new StringContent(jsonData, Encoding.UTF8, “application/json“);
            return resp;
        }
    }
}
 
You can see that I serialized the MessageResults object into a JSON message and returned it in the response content with a type of application/json.  I always use a serializer to create my JSON if possible.  You can generate the same output using a string and just building the JSON manually.  It works and it’s really easy on something this tiny.  However, I would discourage this practice because it becomes a programming nightmare when a program grows in size and complexity.  Once you become familiar with APIs and start to build a full-scale application, you’ll be returning large complex data types and it is so easy to miss a “{” bracket and spend hours trying to fix something that you should not be wasting time on.

The code for the MessageResults class is in the Models folder called MessageResults.cs:

public class MessageResults
{
    public string Message { get; set; }
}

Now we’ll need a JQuery file that will call this API, and then we’ll need to setup IIS.

For the HTML file, I created a Home.html file and populated it with this:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset=”utf-8” />
    <script src=”jquery-2.1.4.min.js“></script>
    <script src=”Home.js“></script>
</head>
<body>
    Loading…
</body>
</html>

You’ll need to download JQuery, I used version 2.1.4 in this example, but I would recommend going to the JQuery website and download the latest version and just change the script url above to reflect the version of JQuery that you’re using.  You can also see that I named my js file “Home.js” to match my “Home.html” file.  Inside my js file is this:

$(document).ready(function () {
    GetMessage();
});

function GetMessage() {
    var url = “http://www.franksmessageapi.com/api/Home/MyMessage“;

    $.ajax({
        crossDomain: true,
        type: “GET“,
        url: url,
        dataType: ‘json‘,
        contentType: ‘application/json‘,
        success: function (data, textStatus, jqXHR) {
            alert(data.Message);
        },
        error: function (jqXHR, textStatus, errorThrown) {
            alert(formatErrorMessage(jqXHR, textStatus));
        }
    });
}

There is an additional “formatErrorMessage()” function that is not shown above, you can copy that from the full code I posted on GitHub, or just remove it from your error return.  I use this function for troubleshooting AJAX calls.  At this point, if you typed in all the code from above, you won’t get any results.  Primarily because you don’t have a URL named “www.franksmessageapi.com” and it doesn’t exist on the internet (unless someone goes out and claims it).  You have to setup your IIS with a dummy URL for testing purposes.

So open the IIS control panel, right-click on “Sites” and “Add Website”:


For test sites, I always name my website the exact same URL that I’m going to bind to it.  That makes it easy to find the correct website.  Especially if I have 50 test sites setup.  You’ll need to point the physical path to the root path of your project, not solution.  This will be the subdirectory that contains the web.config file.

Next, you’ll need to make sure that your web project directory has permissions for IIS to access.  Once you create the website you can click on the website node and on the right side are a bunch of links to do “stuff”.  You’ll see one link named “Edit Permissions”, click on it.  Then click on the “Security” tab of the small window that popped up.  Make sure the following users have full permissions:

IUSR
IIS_IUSRS (yourpcnameIIS_IUSRS)

If both do not exist, then add them and give them full rights.  Close your IIS window.

One more step before your application will work.  You’ll need to redirect the URL name to your localhost so that IIS will listen for HTTP requests.

Open your hosts file located in C:WindowsSystem32driversetchosts.  This is a text file and you can add as many entries into this file that you would like.  At the bottom of the hosts file, I added this line:

127.0.0.1        www.franksmessageapi.com

You can use the same name, or make up your own URL.  Try not to use a URL that exists on the web or you will find that you cannot get to the real address anymore.  The hosts file will override DNS and reroute your request to 127.0.0.1 which is your own PC.

Now, let’s do some incremental testing to make sure each piece of the puzzle is working.  First, let’s make sure the hosts table is working correctly.  Open up a command window.  You might have to run as administrator if you are using Windows 10.  You can type “CMD” in the run box and start the window up.  Then execute the following command:

ping www.franksmessageapi.com

You should get the following:


If you don’t get a response back, then you might need to reboot your PC, or clear your DNS cache.  Start with the DNS cache by typing in this command:

ipconfig /flushdns

Try to ping again.  If it doesn’t work, reboot and then try again.  After that, you’ll need to select a different URL name to get it to work.  Beyond that, it’s time to google.  Don’t go any further until you get this problem fixed.

This is a GET method, so let’s open a browser and go directly to the path that we think our API is located.  Before we do that, Rebuild the API application and make sure it builds without errors.  Then open the js file and copy the URL that we’ll call and paste it into the browser URL.  You should see this:


If you get an error of any type, you can use a tool called Fiddler to analyze what is happening.  Download and install Fiddler.  You might need to change Firefox’s configuration for handling proxies (Firefox will block Fiddler, as if we needed another problem to troubleshoot).  For the version of Firefox as of this writing (42.0), go to the Options, Advanced, Network, then click the “Settings” button to the right of the Connection section.  Select “Use system proxy settings”.

OK, now you should be able to refresh the browser with your test URL in it and see something pop up in your Fiddler screen.  Obviously, if you have a 404 error, you’ll see it long before you notice it on Fiddler (it should report 404 on the web page). This just means your URL is wrong.

If you get a “No HTTP resource was found that matches the request URI” message in your browser, you might have your controller named wrong in the URL.  This is a 404 sent back from the program that it couldn’t route correctly.  This error will also return something like “No type was found that matches the controller named [Home2]” where “Home2” was in the URL, but your controller is named “HomeController” (which means your URL should use “Home”).

Time to test CORS.  In your test browser setup, CORS will not refuse the connection.  That’s because you are requesting your API from the website that the API is hosted on.  However, we want to run this from an HTML page that might be hosted someplace else.  In our test we will run it from the desktop.  So navigate to where you created “Home.html” and double-click on that page.  If CORS is not working you’ll get an error.  You’ll need Fiddler to figure this out.  In Fiddler you’ll see a 405 error.  If you go to the bottom right window (this represents the response), you can switch to “raw” and see a message like this:

HTTP/1.1 405 Method Not Allowed
Cache-Control: no-cache
Pragma: no-cache
Allow: GET
Content-Type: application/xml; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sun, 15 Nov 2015 00:53:34 GMT
Content-Length: 96

<Error><Message>The requested resource does not support http method ‘OPTIONS’.</Message></Error>

The first request from a cross origin request is the OPTIONS request.  This occurs before the GET.  The purpose of the OPTIONS is to determine if the end point will accept a request from your browser.  For the example code, if the CORS section is working inside the WebApiConfig.cs file, then you’ll see two requests in Fiddler, one OPTIONS request followed by a GET request.  Here’s the OPTIONS response:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/10.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: content-type
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sun, 15 Nov 2015 00:58:23 GMT
Content-Length: 0


And the raw GET response:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 24
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
Access-Control-Allow-Origin: *
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Sun, 15 Nov 2015 01:10:59 GMT

{“Message”:”It worked!”}

If you switch your response to JSON for the GET response, you should see something like this:


One more thing to notice.  If you open a browser and paste the URL into it and then change the name of MyMessage action, you’ll notice that it still performs a GET operation from the controller, returning the “It worked!” message.  If you create two or more GET methods in the same controller one action will become the default action for all GET operations, no matter which action you specify.  Modify your route inside your WebApiConfig.cs file.  Add an “{action}” to the route like this:

config.Routes.MapHttpRoute(
    name: “DefaultApi“,
    routeTemplate: “api/{controller}/{action}/{id}“,
    defaults: new { id = RouteParameter.Optional }
);


Now you should see an error in your browser if the the action name in your URL does not exist in your controller:


Finally, you can create two or more GET actions and they will be distinguished by the name of the action in the URL.  Add the following action to your controller inside “HomeController.cs”:

[HttpGet]
public HttpResponseMessage MyMessageTest()
{
    string result = “This is the second controller“;

    var jsonData = JsonConvert.SerializeObject(result);
    var resp = new HttpResponseMessage(HttpStatusCode.OK);
    resp.Content = new StringContent(jsonData, Encoding.UTF8, “application/json“);
    return resp;
}

Rebuild, and test from your browser directly.  First use the URL containing “MyMessage”:

Then try MyMessagetest:

Notice how the MyMessageTest action returns a JSON string and the MyMessage returns a JSON message object.



Where to Find the Source Code

You can download the full Visual Studio source code at my GitHub account by clicking here



 

Webpage Source Code Layout

Summary

In this blog post I’m going to talk about the wrong and right way to layout your front side assets.  By this, I mean the html, js, images and css files.

Legacy Code

In the “good ole’ days” of legacy code such as ASP, and .Net using front-side and code-behind, many programmers would mix Javascript with HTML and CSS code.  Along came JQuery and the need to embed event handlers inside of HTML came to an end.  Yet, somehow the entire developer community didn’t get the memo on how much easier it is to provide full separation of Javascript and CSS from HTML.

Another method used in legacy applications is to print the HTML, Javascript and CSS from the code-behind.  Don’t do this!  Avoid this technique like the plague.  Visual Studio can keep track of JQuery functions and printing some functions and calling them from front-side code will cause warnings and errors (because Visual Studio can’t find the function that will only appear when the program is running).

What’s the Big Deal?

There are several reasons for separating Javascript from HTML and your code-behind code (i.e. C# or VB.Net).

1. It reduces confusion between languages.  The JQuery or Javascript is in the js file while the html is in the cshtml or aspx file.

2. Assets can be bundled.  MVC and the newer .Net websites can perform automatic bundling of js and css files.

3. Assets can be minified.  MVC and the newer .Net websites can perform automatic minification.  This will cause web pages to load faster.

4. You can upload your js and css files to a CDN for faster distribution, reducing the load on your web servers.

How to Convert Your Code

Many programmers prefer to generate their javascript because they can print code-behind variables in the output.  This can be handled using hidden input html tags.

Front-side HTML code:
<input type=’hidden’ id=’myVariable’ value='<%=variabledata %>’ />

Js file:
var myVariable = $(‘#myVariable’).val;

Or, if you’re using Razor, you can use the viewbag instead of the ugly “<% %>” tags.

Another method is to use a javascript section in your front-side code to set the variables in one block.  This will be done before you include your js files (inside the page header):

<script>
var myVariable = ‘<%=variabledata %>’;
var MyOtherVar = ‘<%=variabledata %>’;
</script>

This will not be minimized or bundled, but it is usually a small amount of javascript code.

Your next step is to remove all event handlers from HTML.  Make sure there are no “onclick” events or any other javascript in-line code.  Use JQuery handlers instead:

$(‘#idName‘).click(function(){
   // jquery function code here
});

This will eliminate a lot of clutter inside your HTML code.  You’ll need to make sure that your HTML has the proper id tags so you can attach event handlers to your code.

Remove all your in-line style codes.  Move these to a style sheet.  One of the benefits of containing all of your css in style sheets, is that you can use a css pre-processor like “less”.  Less is a language that can extend the power of css, making it more dynamic.  For more information about less go here.

You can also change your website theme by switching css files.  If you created a lot of in-line css, you’re stuck.  This code is embedded with your HTML and would need to be altered using variables (like color and background-color for example).  The css pages for each theme can be stored along with the images that match the theme.  Then the path names provided at the top of a web page can be setup as variables controlled by the code-behind or controller.


Content Delivery Networks

If your Javascript and css code is contained in their own files, you can upload these as static files into a CDN.  This will provide the end user with a lower latency time when they visit your website.  If you are dynamically generating your Javascript, then it will need to be transmitted from your web servers directly.  This puts a load on your web servers and it prevents you from using a CDN for this content.  To reduce the load on your web servers you would want to load all static files such as images, Javascript and css files onto the CDN (as well as any static HTML files).

When you use CDN’s you’ll need to pre-minify your JS and CSS files, instead of doing this automatically.  There are a lot of programs available that will minify these types of files and you can include this in your deployment process.






 

JQuery Stuff

I was the “bug person” the other day, (which means that I get to fix bugs for the day) when I came across a bug involving a check box.  Basically, the check box didn’t work.  Clicking on the check box caused the page to refresh and remain unchecked.  As I dug into the JQuery code that was attached to the check box click event, I found something rather interesting.  There are a lot of ways to check a check box to see if it is checked or not.  The code that was used was by the section of code I was fixing was incorrect.

First, the HTML code:

<input type=”checkboxid=”MyCheckBox” />My Check Box

Next, the JQuery:

$(document).ready(function () {
  $(‘#MyCheckBox‘).click(function () {

    var test1 = $(‘#MyCheckBox‘).prop(‘checked’);
    var test2 = $(‘#MyCheckBox‘).attr(‘checked’);
    var test3 = $(‘#MyCheckBox‘).checked;

  });

});

The question here is what are the results of “test1”, “test2” and “test3” when the check box is checked?  As it turns out, test1 is the only valid output (returning true).  The other two will return an “undefined” output.

The problem with test2 is that there is no “checked” attribute defined in the html.  So let’s define it:

<input type=”checkbox” id=”MyCheckBoxchecked=”checked” />My Check Box

Now the results have changed.  First, the check box is already checked (due to the fact that the html tells it to be checked).  Second, test2 now returns “checked” instead of undefined.  Check1 returns false, as expected and test3 still returns “undefined”.

At this point, you can see where the attr is returning the attribute of checked (which is normally equal to “checked” or “”).  If you perform a true/false comparison with this value, you will get some iffy results.  To guarantee a true false, use the following code:

if ($(“#MyCheckBox“).is(“:checked“)) {
  alert(‘checked‘);
}
else {
  alert(‘unchecked‘);

}

This will give the correct true/false results.

Of course, using the property method also guarantees a true/false result:

if ($(“#MyCheckBox“).prop(“checked“)) {
  alert(‘checked‘);
}
else {
  alert(‘unchecked‘);

}

Test3 does not work under any of these samples.  I would avoid using it.  I personally use the “prop” or property to check for true/false, because I don’t have to worry about the colon that is required when using the “is” statement.  it’s very clean and simple.  I also leave the checked=”checked” off the check box, unless I need to initialize it to true to start with.

The bug I was fixing used the attr inside an if statement and assumed that true/false was the result.  I changed it to use the property instead, and now there is one less bug.  😉

 

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.









 

MVC 4 API controllers

If you’ve read my previous posts you’ll know that I’m in the research phase of deciding which framework to use with my company’s new project.  At this point I’m leaning toward MVC 4 with a few add ons: AngularJS, Bootstrap, Less, EF-6 and some others.  MVC is starting to grow on me and I wanted to show how to pass data back and forth between jquery (using AJAX) and an API controller (just to get warmed up).

Let’s Get Started
 
To get this started I created a blank MVC 4 application and a controller called “HomeController.cs” in the “Controllers” directory.  Once this file was created, I opened the file and it already contained this code (automagically):


I apologize for using images for the code in this post, I’ll include a link to the whole project at the end so you can download the source code.  Or you can just follow along with my descriptions and create this project on your own (giving you the chance to learn the tricks as you do it).

If you right click on the “View” method, you’ll see an option called “Add View…”.  Select that and a new dialog box will appear to create a view.  Leave the view name “Index” and just click the “Add” button.  A new cshtml file will be created in the “Views” directory.  This is where you’ll put some html code for the startup page.  Before modifying that file, let’s create a script directory and a javascript file.

Right-click on the project and click “Add -> Add New Folder”.  Name the folder “scripts”.  Then right-click on the scripts folder and select “Add -> New Item”.  Then navigate to create a js file:


You can name the file anything you like.  I named mine “javastuff.js”.

Next, you’ll need JQuery.  I would recommend going to the JQuery website and downloading the latest version available.  The reason I like to do it this way is because it only needs one file.  If you use the NuGet facility, you’ll probably get a bunch of stuff you don’t need.  

Go to “jquery.com” and click on the download button.  I chose version 2.0.3 for this example.  Once you have downloaded the js file that is needed for jquery, drag it into the scripts folder.

Now it’s time to include the javascript into the html index.cshtml file created earlier.  First double-click on the index.cshtml file to edit the contents.  Then drag each js file into the code just above the <h2> tags.  Like this:


Of course, you can also hand type the script tags in if you like.  Make sure the jquery reference is on top.  You should be able to run your application and it will do pretty much nothing at this time (except print the text “Index” at the top of the browser).

All right, back to the C# stuff.  Create another controller in the “Controllers” directory, but this time make sure it is an empty API Controller (Right-click on the “Controllers” directory and select “Add -> Controller…”).  Name it “PersonnelController”:


One more file to create.  Right-click on the “Models” directory and create a C# file.  Name it “PersonnelModel.cs”.  Your models should contain the code that queries your database, but I’m going to skip using a database in this sample to keep it as simple as possible.  What I’m going to do is create a class that will represent one database record.  Then I’ll use lists of this class to represent data queried from the database.  The “PersonnelModel.cs” file should look like this:


Now we can use a list of this class inside of the api controller file (open your “PersonnelController.cs” file and enter this code):


I had to add a using statement to bring in the model for this example.  This “Get()” API controller will communicate with the JQuery that we are about to create.  Edit the “javastuff.js” file and make an ajax call like this:


Now you can put a breakpoint on the line where the variable temp is assigned to data.  When you run your application you’ll break at that point and you can see that data contains a list of records that match what was added to result in the C# controller above:



Here’s the source code for the entire project:
MVC Blog Post Controller Demo Project (Zip File)

In my next post I’m going to show how to add AngularJS to the project and connect a grid control to the API Controller and automatically display rows of data in the index.cshtml file.