What .Net Developers Should Know about MS SQL and IIS

Summary

In this post, I’m going to explain a couple techniques and tools that every developer should know.  If you are just graduating from college and you are looking for a .Net job, learn these simple techniques and advance your career.  If you’re a mid-level to advanced .Net developer and you don’t know these tools and techniques yet, learn them.  These tools and techniques will save you time and give you the edge to building better software.

SQL Profiler

Let’s assume you have built this outstanding program.  It’s a work of art.  It uses .Net Core 2.0 with IOC containers, Entity Framework Core 2.0 and other advanced technologies.  You’re testing your web-based software and you notice a pause when you click on a button or a page is loading.  The first thing that pops into my mind is: What is causing the slowdown?  Is it the database or the IIS server?  Finally, what can I do about it?

Let’s eliminate or confirm the database.  If you have installed the profiler tool in SQL (I’m going to assume you did, otherwise you’ll need to start the installer and install this tool), then go to the Tools menu and select SQL Server Profiler.  A new window will open and you’ll need to connect to your database instance as though you are opening the management studio itself.  Once you open the profiler, it’s time to execute that page that you are having issues with.  You can click on the stop button and use the eraser to clean up any records that have shown in the window already.  Get to the point where you are about to click the button to your web page.  Then hit the run button in the profiler and hit the web page.  Once the page loads, then hit the stop button in your profiler so nothing else will record.  Now you have records to analyze.  You’ll be surprised at the number of database calls EF will perform.

I used this project as a demo for the screenshot coming up:

https://github.com/fdecaire/MVCWithAutoFacIOC

Download the project, run the database create script (store_product_database_setup.sql) and run the application.  You should see something like this:

As you can see there is one call to the database and you can see the “select” command.  Click on the “BatchStarting” line and notice the detail in the window at the bottom:

Now you can scrape that query and paste it into the Server Management Studio and test the exact query that your Entity Framework is sending to SQL:

This will indicate if you are querying for too many fields, or the total records queried are crazy.  If you discover that your query result was a million records and your interface only shows the top 10 records, then you need to tweak your LINQ query to only ask for 10 records.  In this tiny example we have three records.  Let’s make it ask for 2 records.  Here’s my original LINQ query:

(from s in _db.Stores select s).ToList();

I changed it to:

(from s in _db.Stores select s).Take(2).ToList();

Re-run the program, capture the data in profiler and this is what I get:

Notice the “Top(2)” difference in the query.  This is the kind of performance tuning you should be aware of.  It’s very easy to create C# code and LINQ queries, only to never understand what is really going on behind the scenes.  Entity Framework takes your LINQ query and turns it into a string that represents a SELECT query and transmits that to MS SQL.  Then MS SQL queries the database, returns the results so that EF can turn it back into a list of objects.  With SQL profiler, you can get into the nuts and bolts of what is really going on and I would recommend you run profiler at least once after you have built your software and think it is ready for prime-time.  If you see a query pause, copy the profile SQL query into management studio and see if you can speed up the query and get the query results that you need.

Another tool you can use is the estimated execution plan tool.  The toolbar button looks like this:

This tool will break your query down into the pieces that will be executed to form the results.  In the case of my previous query, there is only one piece:

That piece of the query costs 100% of the execution time.  If your query included a union and maybe some sub-queries, this tool is very useful in determining which part of the query is costing you the most processing cycles.  Use this tool to decide which part of your query you want to focus your energy on.  Don’t waste time trying to optimize the portion of your query that only takes 2% of the execution time.  Maybe you can get that to go twice as fast, but the overall query will only be about 1% faster than before.  If you focus your energy on a section that takes 98% of your execution time, then you’ll be able to boost the performance in a noticeable manner.

Web Server Troubleshooting

If you’re using IIS, some day you’ll run into a problem where you don’t get any logs and your website or API crashes immediately (usually a 500 error).  This is always a difficult problem to troubleshoot, until you realize that there are only a hand-full of problems that cause this.  The most common problem is an issue with the XML formatting in your web.config file.  I can’t tell you how many times I have been bit by this problem!  The easiest way to test and troubleshoot this error is to open the IIS manager control panel, select your website and then click on one of the icons that displays a section of your web.config file, like “Modules”:

If there is an error, then the line number in the web.config file will be shown.  You’ll be able to look at the xml in the web.config and see your missing tag, extra quote or other symbol (sometimes it’s an “&”, “>” or “<” symbol inside your database connection string password or something).  Fix the web.config issue and go back to modules again.  If there is another error, then fix it and return again, until it works.

On .Net Core, there is an error log that can report startup errors.  This logging happens before your log program starts and is very handy for situations where you don’t get any logging.  When you publish your site to a folder in .Net Core (or Core 2.0), you’ll end up with a bunch of dlls, some config files and a web.config file.  The web.config file is mostly empty and might look like this:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
 <system.webServer>
 <handlers>
 <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
 </handlers>
 <aspNetCore processPath="dotnet" arguments=".\Website.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" />
 </system.webServer>
</configuration>

Change your “stdoutLogFile” parameter to point to a file location that you can find.  I usually set mine to “C:\logs\myapplication_logging_error.txt” or something like that.  Then I run the program until it crashes and check in the c:\logs directory to see if the file exists.  If it does, it usually contains information about the crash that can be used to troubleshoot what is going on.  I’m assuming at this point in your troubleshooting, the website or API works from Visual Studio and you are having issues with the deployed application.  If you are having issues with executing your application in Visual Studio, you should be able to zero in on the error in VS using breakpoints and other tools.

For NLog there is an error log for the error log.  This is where the errors go when there is an error detected in the NLog code.  Usually caused by a configuration error.  At the top of your nlog.config file should be something like this:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 autoReload="true"
 internalLogLevel="Warn"
 internalLogFile="C:\logs\myapplication_nlog.txt">

As you can see, there is an “internalLogFile” parameter.  Set this to a location and filename that you can find.  Then execute your program and see if that log file appears.  If it does, then open it up and examine the contents.  Usually it’s an exception error involving the NLog logger.

Application Pools

The application pool type must match the .Net version that you are using.  For .Net Core and Core 2.0, you’ll need to use “no managed code”.  For .Net, you’ll set your pool to “.Net Framework v4.0”.  If you are unfortunate enough to be using really obsolete legacy code, you can set it to “.Net Framework v2.0”.

When you deploy your Core 2.0 application, you may need to cycle the application pool.  You’ll run into a problem where you deploy new code and the “bug fix” or “new feature” does not show up.  Cycle the app pool and see if it fixes your problem.  The application pool might be using a copy of the previous program in memory.

Sites

Inside your site settings, there is an ASP settings section:

You can turn on debugging flags inside here.  For your local development system, turn it all on:

Leave these settings off for any production system.  You do not want to advertise the line numbers of your code (and your code) when you have a crash.  For development purposes, you want to know all the data you can get from an exception.  If these settings are on, you’ll get the full dump of the exception message in your browser and then you can return to Visual Studio to find the exact line of code where the error occurred.

I hope this saves you some time when a frustrating deployment problem occurs.  The trick is to learn the most common causes of deployment problems so you don’t spend all day troubleshooting a tiny error instead of working on that next big chunk of code.

 

 

 

 

The Cloud

This post is going to be a bit different from the usual.  I’m going to talk a little about cloud computing.  Specifically about Amazon’s cloud and what you should consider if you are thinking about using a cloud-based system.  This article will be geared more toward the business end of cloud computing, though I’m going to describe some technical details up front.

Some History

When the cloud was first offered, I was a bit skeptical about using it.  At the time I was working for a company that hosted their own equipment.  Internet connection bandwidth was not like it is today (I think we had a 5 megabit connection back then).  The cloud was new and virtualization was new and expensive.  There were a lot of questions about how to do it.  If I were to startup a new system for a company like that today, I’d recommend the cloud.

Any IT person who installs equipment for a data center today knows about cloud computing.  I have now worked for two companies that have hosted their equipment at a major data center, using virtual hosts.  The advantages of hosting equipment at a data center verses providing your own facility are numerous.  Off the top of my head are: Cooling, backup power, data bandwidth to the internet, and physical security to the site.  The cloud provides additional benefits: Pay for equipment as you need it, avoid delay required to order new equipment.

Amazon Web Services (AWS)

I examined a few different cloud services and I’ll blog about other services as I get time to gain some experience.  The reason I started with AWS is due to the fact that they have a 1 year trial for free.  That is marketing genius right there!  First, they encourage software developers to sign up and learn their system.  That allows them to get their foot in the door of companies that might start using cloud computing and abandon their physical data centers.  All because they have developers on staff that already know the technology.  Second, a year is a lot of time to experiment.  A person can get really good at understanding the services or they can attempt to build a new product using their service to see how it operates.

I signed up and it does require a credit card to complete the sign up.  That sends off a few alarms in the back of my head because technically, they could charge my card without me knowing it.  So the first thing I did was find out where I can review any charges.  I also noticed that there are warning messages that tell me when I’m attempting to setup a service that does not apply to the free tier (which means that I’ll get charged).  The great unknown is what happens if I accidentally get a flood of traffic for a test application that I’ve posted?  I guess I’ll find out, or hopefully not.

Anyway, here’s what the billing screen looks like:


This is accessible from the drop-down menu above with your name on the account (“Frank DeCaire” for my account).

There are a lot of services on AWS and their control panel is rather large:

Where to start?  I started with Elastic Beanstalk.  Amazon uses the word “Elastic” in all kinds of services.  At first, I thought it was just a cute word they used to describe their product the way that Microsoft uses the word “Azure”.  I began to read some documents on their services and the word “Elastic” refers to the fact that you can program your cloud to provision new servers or tear-down servers according to trigger points.  So you can cause more servers to be put on line if your load becomes too high.  Conversely you can automatically tear-down servers if the load gets too low (so you don’t have to pay for servers you don’t need during low volume times).  This is where the term “Elastic” comes in.  The number of servers you apply to your product is elastic.  

Back to Beanstalk.  The Elastic Beanstalk application has a web server and an optional database server.  So I clicked into the Beanstalk app and created an IIS server (there are several web server types to choose from).  Then I added a SQL Server Express database under RDS.  The database server required an id and password.  Once that was created there is a configuration details screen and it contains a url under the section named Endpoint,  This is the connection url that can be used by SQL Server Management Studio.  Once connected, I was able to manipulate SQL Server the same as a local instance.  I created tables and inserted data to make sure it worked.


IIS

The IIS server control panel looks like this:



You can click on the blue link to pop-up the website url that points to this web server (or server farm).  I have intentionally obscured the id by replacing it with “abcdefgh”, so the id above will not work.  You’ll need to create your own account and a random id will be generated for your own server.

Next, you need to download the tool kit for Visual Studio (click here).  I installed it on VS 2015, so I know it works on the newest version of Visual Studio.  I also tested on VS 2013.  There are a few gotchas that I ran into.  First, I ran into an error when attempting to deploy to AWS.  The error I received was that the URL validation failed (“Error during URL validation; check URL and try again”).  This turned out to be a false error.  What I discovered was that there was a permissions problem with access to IIS.  This can be found in the Identity and Access Management console (IAM).  I had a user created, but I did not assign a group to the user.  The IAM console is rather complex and requires some head-scratching.  Stack overflow is where I found the best answer to troubleshooting this issue:

aws-error-error-during-url-validation-check-url-and-try-again

My next problem gave an error “The type initializer for ‘Microsoft.Web.Deployment.DeploymentManager’ threw an exception.” which was just as cryptic.  As it turned out there are registry entries that SQL Server doesn’t remove when uninstalling older versions of SQL Server that interfere with the deployment software in Visual Studio.  The keys are:

HKLMSoftwareMicrosoftIIS Extensionsmsdeploy3extensibility
HKLMSoftwareWow6432NodeMicrosoftIIS Extensionsmsdeploy3extensibility


They both should be removed.  I also found that information from stack overflow:

Web deployment task failed. (The type initializer for ‘Microsoft.Web.Deployment.DeploymentManager’ threw an exception.)

At that point I was able to deploy my application and get a “Hello World” program running.  Once this capability is in place you can focus on the development process and not deal with configuration details until you need more capabilities.


Real World Application

Now that I have the basics down, I still need to test some of the other features of AWS (like their EC2 virtual servers).  However, I have enough knowledge to actually use AWS for a production system.  If you’re analyzing this service as a migration of an existing system, then there are a lot of things you still need to consider.  The first thing you’ll need to do is find out how much it’ll cost to store the amount of data that you already use.  How much web traffic are you using?  How many servers do you currently use?  These are going to go into an equation of cost.  When you compute those costs it should be lower than what you are currently paying for your equipment, data connection and facility.  If not, then you should not move your system.

If you are contemplating a start-up, you’ll have other factors to consider.  First and foremost, assuming you haven’t created your software yet, you’ll need to decide which web platform and database engine you’ll use.  If you’re not experienced with working at a company that has a large database system, you might not realize how much licenses can cost when you need to scale out.  In the early stages of development priority might be placed on how easy it is to get the site up and running.  This will haunt you in the long run if your user base grows.  I would seriously consider using free or open-source software where you can.  AWS has MySql and Apache with Java, Python or PHP.  Ruby is another option.  If you lock yourself into IIS and SQL Server, you’ll need to pay the extra licensing fees when your application outgrows the Express edition.  Once you have created thousands of stored procedures in SQL, you’re locked in, with a re-development cost that is astronomical or license fees that are almost as bad.

Another factor to contemplate in a start-up is the cost of getting your business going.  If you have seed capital, then you’re probably set for a fixed period of time.  If you are doing this on your own, then you’re probably worried about how much it will cost until you get enough customers to cover your fees.  You’ll need to compute this information ahead of time.  You need to ask yourself: “How many paying customers do I need in order to break even.”  If you are providing a two-tier website that has a free component (which is a great way to hook people) and a paid component that has powerful features, you’ll need to figure out what the ratio of paid vs. free customers there will be.  If you’re conservative with your figures, you’ll come out ahead.  I would start with a 5%/95% and compute what you need.  That means you’ll need to pay for 100% of your customer’s data and bandwidth usage, but you’ll only collect money from the 5% that are paying.  If you plan to sell advertisements, you’ll need to compute that.

Now you’re probably thinking “how do I know what these numbers are going to be?”  Well, that’s where this free AWS service is handy.  If you’re clever, you’ll get your application up and running before you sign up for AWS, or if your application is expected to be small and easy to build, you can build it directly on AWS.  When you’re ready to do some usage testing, you can put it on line and get it into the search engines.  At first you’ll end up with 100% free users.  Your traffic should increase.  You’ll have to take an educated guess at what to charge for the advanced features.  Too much, and nobody will see the value.  Too cheap and you’ll go broke.  The ideal price point would be something that seems cheap for what the customer receives, but enough to cover costs and earn a profit.  What that price point is, depends on what your application does.

AWS has a system for taking credit care information and keeping track of accounting information.  You’ll need this type of system in order to keep track of who has paid and how much they have paid for.  This service is called DevPay.  The goal is to automate the process of collecting payment information, activating accounts and deactivating accounts.  That’s a task that can overwhelm a person in no time if your product becomes successful.  Here’s the basic information on DevPay:

What is Amazon DevPay?


Other Considerations

Once you launch your application and it becomes established, you’ll need to consider your growth rate.  If your income is large enough, you can plan for new versions of your software according to how many developers you can keep on staff or contract.  In the cloud scenario, there is no need to pay for office space.  Technically, you can run the entire operation from your home.  Avoid adding the cost of an expensive facility until you really need it.  

Keep your eyes open on other cloud providers.  Google or Microsoft (and others) can provide equivalent services.  If their pricing structure makes your product cheaper to operate, consider porting to their cloud.  If you keep this in mind when you’re small, you can keep your application in a format that can be re-deployed quickly.  If you build in too many Amazon specific features you might be stuck until you can redesign a feature (Yes, I mentioned this fact after I talked about DevPay in the previous paragraph).  Another option is to use a cloud provider specific feature long enough to design your own non-cloud provider specific feature.  In other words, use DevPay for your application until you can hire developers or put in the development time to write your own (or possibly use another 3rd party product).  Always keep your application capable of being moved.  Otherwise, you’ll be hostage to a provider that someday may become hostile to your business.

Deployment tools are another feature you should get familiar with.  Automate your deployment as much as possible.  AWS has deployment tools that allow the developer to clone a production web server in isolation and to deploy a development version of your application for testing purposes.  If you need to do a lot of manual steps to get your application tested and deployed, you’ll be wasting valuable developer time.  Time that is very expensive.

Get familiar with the security features.  If you hire outside contractors to perform maintenance or development tasks, you’ll need to be able to shut off their accounts quickly if something goes wrong.  Make sure you understand what capabilities you are giving to another person.  Don’t allow a rogue programmer to put in back-doors and open holes to the internet that you don’t know exist.  Always monitor what is going on with your system.

I could go on all day, but at this point you should go to the AWS site and sign up for free usage.  Get some experience.  Click here.  When you get a “Hello World” program deployed and working, try some new features.  I would also recommend seeking out other cloud products from other vendors.  Google and Microsoft come to mind but there are others like AT&T, EMC, IBM, etc.

  

 

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



 

Creating a COM Object for Classic ASP

Summary

This blog post will show you how to create a COM (Component Object Model) object in C# that you can use in your classic ASP code.  Why would anybody do that?  Amazing as it might seem, there is a lot of classic ASP code out there in the form of legacy applications.  It’s monstrously difficulty to replace this code due to the fact that classic ASP isn’t compatible with anything and it doesn’t play nice with any other language.  So I’m going to show the basic mechanics of how to create a COM object in C# and how to incorporate it in your ASP code.

Writing Your First COM Program

First, let’s write the simplest program possible: Hello World.  I am going to follow a similar path as this article (which is where I learned some of this from):

Creating a COM object from scratch with C# 

There are a couple of changes I’m going to make because VS 2012 and above have a built-in GUID generator and I want to show how you can build something with no parameters, just to keep it ultra-simple.

Step 1 – Create your C# program

Create a new C# class library project.  You’ll need to add a using statement for the interop services library to the top of your code:

using System.Runtime.InteropServices;

Step 2: Construct the Class

For my example, I’m going to make this just a simple class with one method:

public class Launcher
{
    public string Hello()
    {
        return Hello world“;
    }
}

I’m leaving out the constructor, since it’s not used anyway.

Step 3: Presenting our Class Through an Interface

In order to access any methods or classes inside the COM module, we need to provide an interface.

public interface ILauncher
{
    string Hello();
}

You’ll also need to add the interface name as the base class for the Launcher object.


Step 4: Making the Connection

We need to add an attribute to our class to make sure it doesn’t automatically generate another interface (we want to use the interface we typed up manually):

[ClassInterface(ClassInterfaceType.None)]
public class Launcher : ILauncher
{
    public string Hello()
    {
        return Hello world“;
    }
}


Next, I’m going to deviate from the original article and allow early and late binding by adding the InterfaceIsDual attribute:

[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface ILauncher
{
    string Hello();
}

Step 5: Making them Unique

This is where I’m really going to deviate from the original article.  You’ll need to generate GUID’s for both the interface and the class. Now go to the “Tools” menu and select “Create GUID”:

Choose #5, and click on the “Copy” button.  Then paste it into your code:

[Guid(“6216B529-3E4A-4FE8-8F7A-BE99C33DB1F1“),
 InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface ILauncher
{
    string Hello();
}

[Guid(41027763-2E19-415A-8525-F48F604EE810),
 ClassInterface(ClassInterfaceType.None)]
public class Launcher : ILauncher
{
    public string Hello()
    {
        return Hello world“;
    }
}


You might have to remove the square brackets to make the syntax correct (as shown above).


Step 6: Going Underground with Cryptography

This is where you’ll have to drag out the “sn” utility and give your assembly a strong name.  You’ll have to search your hard drive for the sn utility and there are probably more than one version.  I found mine at this path:

“C:Program Files (x86)Microsoft SDKsWindowsv8.1AbinNETFX 4.5.1 Toolssn”

I chose the latest version that was installed on my PC.  You’ll need to open a console window (go to your start menu and type “command” in the search box.  Then navigate to the project directory of your application.  Then execute the sn utility with the “-k key.snk” parameter:

“C:Program Files (x86)Microsoft SDKsWindowsv8.1AbinNETFX 4.5.1 Toolssn” -k key.snk

You’ll need to keep the path name quoted since it has spaces in it.  Once you execute this command there will be a file generated in your project directory named “key.snk”.  Now you need to add this file to your project as a link.  So right-click on your project and select “Add -> Existing Item”.  Don’t hit the “add” button, on the add button there is a down-arrow that allows you to select a different option:

Select “Add As Link”.  To use this file, we need to go to the project properties (right-click on your project and select “Properties”).  Then select the “Signing” tab.  Now click on the “Sign the assembly” check box and choose the “key.snk” file from the drop-down list:


Save your changes.


Step 7: Wrapping it All Up

Before building your solution we need to modify some settings.  In Deutschzuid’s article that I cited at the beginning of this blog post, you are directed to change your target build version at this point.  I’m going to leave it at “any” (the default).    Go back to your project properties and select the “Application” tab.  Click on the “Assembly Information” button.  Check the “Make Assembly COM-Visible” check box.

Now switch to the “Build” tab and check the “Register for COM interop” check box.


Step 8: Compiling it and Taking it for a Walk

Now you can build the solution.

First, let’s try this in ASP.  Make sure you have IIS installed and running on your PC.  Create a sub-directory in your C:inetpub directory named “aspcom”.  You can startup the IIS control panel (go to your start menu and type “iis” in the search box) and create a new application under your default website.  Name your application “aspcom” and point the directory to the new directory you just created.  You’ll need to click on “Edit permissions” and the directory properties window will pop-up.  Click on the “Security” tab.  Click “Edit” then “Add”, then type in “IUSR” and click “Check Names”.  Then click “OK”, then check the “allow full control” check box.  Then “OK”, 

Then repeat: “Edit”, “Add”, type “IIS_IUSRS” and click “Check Names”.  You might need to change your domain to the local PC domain for this to check right.  Then “OK”, then “allow full access”, then “OK” and last “OK” to close the properties window.

Now you’ll need to add those same two rights to the directory that contains your COM object project.  Just navigate to your project directory and right-click on it.  Then repeat the steps above to give full rights to “IUSR” and IIS_IUSRS”.

Restart IIS.

Now create a text file inside the C:inetpubaspcom directory named “home.asp” and type (or copy) this in:

<%
Dim MyComObject
Dim MyText

Set MyComObject = Server.CreateObject(“Launcher.Launcher”)

MyText = MyComObject.Hello()

%>
<html>
<head></head>
<body>
    <%=MyText %>
</body>
</html>

In the IIS control panel is a link called “browse” with a url on it.  You can click this link to get to the ASP directory, but you’ll have to add home.asp to the end of the path.  Then you should see “hello world” printed on your browser.

Next, create a text file on your desktop and name it “test.html”.  Now type or copy this into it:

<HTML>
<HEAD>
<SCRIPT language=”javascript”>
function Test() {
var objTest = new ActiveXObject(“Launcher.Launcher”);
alert(objTest.Hello());
}
</SCRIPT>
</HEAD>
<BODY>
<INPUT Type=”button” onClick=”Test()” Value=”Click here to test!”>
</BODY>
</HTML>


Now save it and double-click on the html file.  You’ll have to allow blocked content then click the button.  Then answer yes to the active-x control warning and you’ll see a text box displaying “hello world” in it.


Step 9: Deploying the dll on Another Machine

If you want to deploy the dll on another machine, you’ll have to add your dll to the registry by using the regasm utility.  First, copy your dll to the target machine (just the dll).  Then you need to find the regasm program on your pc, just like you did with the sn utility above.  Choose the latest version.  Navigate to your dll’s location and use this command:

regasm ComClassExample.dll /codebase /tlb /nologo

For testing purposes, you don’t need to use regasm.


Troubleshooting Tricks

OK, now there is an issue if you are attempting to change your COM program after you have executed it from an ASP program.  That issue is that IIS has the DLL locked and you can’t re-compile.  So you’ll need to reset your IIS before you re-build your application.  Then you can run your ASP program again.

Next, you are going to want to know what is going on while you are troubleshooting this project.  Especially if it doesn’t work the first time.  So in the IIS console, click on your application (aspcom), double-click on the ASP icon:


Expand your “Debugging Properties” section and change “Enable Client-side Debugging” to true and also change “Enable Server-side Debugging” to true.  Click on “apply”.  

Now, if something blows up, you can attach a debugger and see where it breaks in Visual Studio.  You can also get a good error message, like “permission denied”.

Don’t forget about the IIS log files.  They are located in the C:inetpublogs directory.  These are usually pretty cryptic, but sometimes they can shine some light on what’s wrong.

You can also open your home.asp page in Visual Studio and put a break-point on it.  Then choose “Debug -> Attach to Process…”, then select w3wp.exe and click the “attach” button.  Refresh the web page and the breakpoint should be hit.  You cannot get tool tip help in asp, but you can put a variable in your watch list and see what is contained in the variable.

One other annoying thing you might run into.  If you click the “Restart” button in the IIS control panel and your IIS does’t restart (it just sits there scanning, like it’s waiting for something) that means that there is a w3wp.exe process holding it up.  Just CTRL-ALT-Delete and start task manager.  Then find all w3wp.exe processes and “end process”.  You’ll notice that your IIS control panel will suddenly respond.


Download the Source

You can download the source code from my GitHub account by clicking here.

 

Web Sessions

Summary

I’m going to create a series about how Microsoft handles sessions for VB.Net and C# web applications.  The purpose of these posts will be to provide a clearing-house of all the information needed to get a common session system going between multiple languages.

The Problem

Web sites typically use session data to keep track of who is logged in and what state they are in.  I’m not going to go into details on why sessions are used or how to use them to build a website.  Instead, I’m going to assume you are already familiar with this technique and you’re saddled with a large amount of legacy code that cannot be converted in one shot.  Let’s say you have a website in PHP and you’re attempting to migrate into a C# environment.  How do you go from one web page in PHP running on a Unix server into a C# program running on an IIS server?

There are many solutions, such as cookies, tokens passed in the URL, a GUID stored in a hidden field, etc.  The smoothest solution would be to somehow share the session data between different languages so that one page at a time can be converted and the URL from the old page can be redirected to the new page with a smooth and secure transition.  The first thing to recognize is that we’re going to have to store the session data in a database that is shared by all web sites that will be connected into one web application.  Microsoft provides this capability through their own session management.  

Using MS SQL Server to Store Session Data

For Dot Net applications, you can setup a SQL server to store the session data.  The following link is probably your best article for getting SQL setup with the ASPState database and redirecting your application to point to the new database:

Configuring ASP session state on SQL server 

Once you have set this up, you’ll need to make sure your user rights are setup in the ASPState and the tempdb database.  The session data is actually stored in the tempdb database in two tables: ASPStateTempApplications and ASPStateTempSessions.  The ASPStateTempApplications table contains the name of the application and the unique app id used by the session cookie (I’m going to assume you’re using the cookie mode in iis, since it is the default).  The ASPStateTempSessions table contains one record per session created.  All of the session data is encoded and stored in a binary field in this table called SessionItemShort (or if it’s larger than 7k, then it’ll be in SessionItemLong which is an image data type).


The Session Cookie

When your application creates a session, a cookie is created with the application id and a unique session id.  The default cookie name is “ASP.NET_SessionId”.  If you look at the session id the tempdb.ASPStateTempSessions table, you’ll discover that it is a large alphanumeric string.  That string represents two parts: The session GUID and the application ID.  The application ID is in hex in the ASPStateTempSessions table and it is in decimal in the ASPStateTempApplication.appid field.  If you are going to read the session data from the tempdb database ASPStateTempSessions table, then you’ll need to add the application ID to the end the cookie value.  Take your application name and read the application id from the ASPStateTempApplications table.  Convert this to hex, then append to the cookie value.  This will be the primary key of the ASPStateTempSessions table for your session data.

If your googling skills are savvy enough, you will have discovered most of this information from this article: Session State Providers.  

The next thing to note about this session setup is that the cookie is a non-persistent cookie.  There is no expire date and this type of cookie will remain until you close your browser.

If you dig into your SQL server and you look at your SQL Server Agent jobs, you’ll see a new one called ASPState_Job_DeleteExpiredSessions.  This job will execute the stored procedure: DeleteExpiredSessions once per minute.  The sole purpose of this stored procedure is to delete all cookies where the expires field is beyond the current date/time.  This will cause the session to expire.  If you look at this date/time in the
ASPStateTempSessions table, then refresh your browser, you’ll notice that the time updates.  The time will always be 20 minutes into the future (if your session is set to expire in 20 minutes, which is the default).  If your web page goes idle for more than 20 minutes, then you’re toast.


Sharing Session Data Between VB.Net and C#

The easy method of sharing between two languages is to set the application name to the same name in the global.asax file for both programs:

Session State shares session across subdomain, VB.NET website C# MVC 4 Application


Session Data

The session data that is stored in the tempdb.ASPStateTempSessions table is an encoded version of all the session variables and data used by your program.  There is this code in C#, which can decode this data into a list of variables:

christian-blades-cb/ASPSessionDecoder 

This code does not handle objects, but it does demonstrate the complexity of how this is encoded.  Creating an encoder and decoder for this data for a multitude of languages would be very handy.  Especially if you wanted to use many languages in one large monolithic application.  I believe the reason that Microsoft encoded this data into one large field instead of using a sub-table of fields and data, is that they can store the session data for each session in one record.  This prevents a lot of table locking issues with deleting records and it also reduces the amount of time it takes to read and write to the database (assuming they had a database in mind when they designed this system.  If you look closely at the DeleteExpiredSessions stored procedure inside the ASPState database, you’ll see that a query of all the expired sessions is put into a temp table.  Then the temp table is looped through and each session record is re-checked as it is deleted, just in case it was updated or deleted while this operation was in progress.


Wrap up

For this blog post, that’s all I’m going to go into.  Armed with this information anybody can make a decision on how they want to pursue sessions with legacy code and new code.  For instance, you could design your own session system to mimic what Microsoft does and use child records to store your variables.  I am unsure how this will perform or what issues you’ll run into with this method.  You could write encoders and decoders for the session data and use the data that Microsoft stores (avoiding the need for converters and decoders from VB.Net and C# (i.e. you could write a codec for PHP, Classic ASP, Java).  By storing your session in the database, you can use different IIS applications for each language (or divide your systems into multiple applications).  You can also prevent your session from clearing when an IIS server is re-cycled, or if you have a server farm, you don’t need to worry about which server the web request returns to.  

 

Web API and API Data Retreiver

Summary

In this blog post I’m going to show how to create a Web API in Visual Studio.  Then I’m going to show how to setup IIS 7 to run the API on your PC (or a server).  I’m also going to create a retriever and show how to connect to the Web API and read data.  I’ll be using JSON instead of XML so I’ll also show what tricks you’ll need to know in order to implement your interface correctly.  Finally, I’ll demonstrate how to troubleshoot your API using fiddler.


This is a very long post.  I had toyed with the idea of breaking this into multiple parts, but this subject turned out to be too difficult to break-up in a clean manner.  If you are having trouble getting this to work properly or you think I missed something leave a message in the comments and I’ll correct or add to this article to make it more robust.

Web API Retriever

I’m going to build the retriever first and show how this can be tested without an API.  Then I’ll cover the API and how to incorporate IIS 7 into the whole process.  I’ll be designing the API to use the POST method.  The reason I want to use a POST instead of GET is that I want to be able to pass a lot of variables to request information from the API.  My demo will be a simulation of a chain of stores that consolidate their inventory data into a central location.  Headquarters or an on-line store application (i.e. website) can send a request to this API to find out what inventory a particular store has on hand.  

The retriever will be a simple console application that will use an object to represent the request data.  This object will be serialized into a JSON packet of information posted to the API.  The request object will look like this:

public class ApiRequest
{
  public int StoreId { get; set; }
  public List<int> ProductId { get; set; }
}


This same object will be used in the API to de-serialize the JSON data.  We can put the store id in this packet as well as a list of product ids.  The data received back from the API will be a list of inventory records using the following two objects:

public class InventoryRecord
{
  public int ProductId { get; set; }
  public string Name { get; set; }
  public int Quantity { get; set; }
}


public class ApiResponse
{
  public List<InventoryRecord> Records = new  

         List<InventoryRecord>();
}

As you can see, we will receive one record per product.  Each record will contain the product id, the name and the quantity at that store.  I’m going to dummy out the data in the API to keep this whole project as simple as possible.  Keep in mind, that normally this information will be queried from a large database of inventory.  Here’s the entire retriever:

public class WebApiRetriever
{
  private readonly string apiURLLocation =  

             ConfigurationManager.AppSettings[“ApiURLLocation“];
  private readonly string apiAuthorization =  

          ConfigurationManager.AppSettings[“ApiCredential“];

  public void Retreiver()
  {
    var serializer = new JsonSerializer();

    var apiRequest = new ApiRequest
    {
      StoreId = 1,
      ProductId = { 2, 3, 4 }
    };

    var request = 
        (HttpWebRequest)WebRequest.Create(apiURLLocation + “”);
    request.ContentType = “application/json; charset=utf-8“;
    request.Accept = “application/json“;
    request.Method = “POST“;
    request.Headers.Add(HttpRequestHeader.Authorization, 

         apiAuthorization);
    request.UserAgent = “ApiRequest“;

    //Writes the ApiRequest Json object to request
    using (var streamWriter = new 
           StreamWriter(request.GetRequestStream()))
    {             

      streamWriter.Write(
           JsonConvert.SerializeObject(apiRequest));
      streamWriter.Flush();
    }

    var httpResponse = (HttpWebResponse)request.GetResponse();

    using (var streamreader = new  
           StreamReader(httpResponse.GetResponseStream()))
    using (var reader = new JsonTextReader(streamreader))
    {
      var storeInventory = 

          serializer.Deserialize<ApiResponse>(reader);
    }
  }
}


Some of the code shown is optional. I put the URL location and credentials into variables that are stored in the app.config file.  You can add this to your app.config file:


<appSettings>
    <add key=”ApiURLLocationvalue=” 

       http://www.franksdomain.com/WebApiDemo/api/MyApi/“/>
    <add key=”ApiCredentialvalue=”ABCD“/>
</appSettings>

The URL will need to be changed to match the URL that you setup on your IIS server (later in this blog post).  For now you can setup a redirect in your “hosts” file to match the domain in the app setting shown above.

Navigate to C:WindowsSystem32driversetc and edit the “hosts” file with a text editor.  You’ll see some sample text showing the format of a URL.  Create a domain name on a new line like this:

127.0.0.1        www.franksdomain.com

You can make up your own URL and you can use a URL that is real (technically, franksdomain.com is a real URL and it’s not mine).  If you use a real URL your computer will no longer be able to access that URL on the internet, it will redirect that URL to your IIS server (so be aware of this problem and try to avoid using real URLs).  The IP address 127.0.0.1 is a pointer to your local machine.  So we’re telling your browser to override www.franksdomain.com and redirect the request to the local machine.

Now you should be able to test up to the request.GetResponse() line of code.  That’s where the retriever will bomb.  Before we do this, we need to download and install Fiddler (assuming you don’t already have fiddler installed).  Click here to download fiddler and install it.  Now start up fiddler and you’ll see something like this:


Now run the retriever application until it bombs.  Fiddler will have one line in the left pane that is in red.  Click on it.  In the right pane, click on the “Inspectors” tab and then click on “JSON” sub-tab.  You should see something like this:


In the right side top pane, you’ll see your JSON data.  If your data is shown as a tree-view control then it is formatted correctly as JSON and not just text.  If you serialized your object incorrectly, you will normally see an empty box.  Notice that the store is set to “1” and there are three product ids being requested.

The Web API

The web API will be an MVC 4 application with one ApiController.  The API controller will use a POST method. 

So let’s start with a class that defines what information can be posted to this API.  This is the exact same class used in the retriever:

public class ApiRequest
{
  public int StoreId { get; set; }
  public List<int> ProductId { get; set; }
}


Make sure this class is not decorated with the [Serializable] attribute.  We’re going to use a [FromBody] attribute on the API and the object variables will not bind if this object is setup as serializable (I discovered this fact the hard way).  As you can see by the list definition we can pass a long list of product ids for one store at a time.  We expect to receive a list of inventory back from the API.


The response back to the calling application will be a list of inventory records containing the product id (which will be the same number we passed in the request), the name of the product and the quantity.  These are also the same objects used in the retriever:


public class InventoryRecord
{
  public int ProductId { get; set; }
  public string Name { get; set; }
  public int Quantity { get; set; }
}


public class ApiResponse
{
  public List<InventoryRecord> Records = new  

         List<InventoryRecord>();
}



The entire API controller in the MVC application looks like this:


public class MyApiController : ApiController
{
  [HttpPost]
  [ActionName(“GetInventory“)]
  public HttpResponseMessage GetInventory([FromBody] ApiRequest request)
  {
    if (request == null)
    {
      return Request.CreateErrorResponse(HttpStatusCode.BadRequest, 

             “Request was null“);
    }
       
    // check authentication
    var auth = ControllerContext.Request.Headers.Authorization;
       
    // simple demonstration of user rights checking.
    if (auth.Scheme != “ABCD“)
    {
      return Request.CreateErrorResponse(HttpStatusCode.BadRequest, 

             “Invalid Credentials“);
    }
   
    ApiResponse apiResponse = new ApiResponse();

    // read data from a database
    apiResponse.Records = DummyDataRetriever.ReadData(request.ProductId);

    // convert the data into json
    var jsonData = JsonConvert.SerializeObject(apiResponse);

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


The controller is a post method controller that looks for an ApiRequest JSON object in the body of the posted information.  The first thing we want to check for is a null request.  That seems to occur most often when a bot crawls a website and hits an API.  If we’re lucky, then bots will not find their way in, but I always code for the worse case situation.  The next part will check the header for the authorization.  I didn’t cover this in the retriever, but I stuffed a string of letters in the authorization variable of the header.  This was setup to be “ABCD” but in a real application you’ll need to perform a database call to a table containing GUIDs.  These GUIDs can be assigned to another party to gain access to your API.  In this example the shopping website application will have its own GUID and each store will have a GUID that can be setup to restrict what each retriever can access.  For instance, the website GUID might have full access to every store to lookup information using this API, but a store might only have access to their own information, etc.  I’m only showing the basics of this method in this article.  I’ll cover this subject more thoroughly in a future blog post.

Next in the code is the dummy lookup for the information requested.  If you navigate to my sample dummy data retriever you’ll see that I just check to see which product is requested and stuff a record in the list.  Obviously, this is the place where you’ll code a database select and insert records into the list from the database.

Next, the list of inventory records are serialized into a JSON format and then attached to the content of the response message.  This is then returned.

Next, you’ll need to setup an IIS server to serve your API.

 

Setting up the IIS Server

I’m going to setup an application in IIS 7 to show how to get this API working from your PC.  Eventually, you’ll want to setup an IIS server on your destination server that you will be deploying this application to.

I’ll be using IIS 7 for this demo, if you’re using Windows 7 or earlier, you will probably need to download and install IIS 7 (the express version works too).  When you open IIS 7 you should see a treeview on the left side of the console:


Right-click on “Default Web Site” and “Add Application“.  Name it “WebApiDemo“.  You should now see this:


Now click on the “WebApiDemo” node and you’ll see a panel on the right side of the control panel named “actions“.  Click on the “Basic Settings” link.  Change the physical path to point to your project location for the API project (this is the MVC4 project that you created earlier or downloaded from my Github account).



You’ll notice that the application pool is set to “DefaultAppPool“.  We’ll need to change this to a .Net 4 pool.  So click on the “Application Pools” node and double-click on the “DefaultAppPool” line.  Change the .Net Framework Version to version 4:


At this point, if you try to access your API, you’ll discover that it doesn’t work.  That’s because we need to give IIS server access to your project directory.  So navigate to your project directory, right-click and go to properties, then click on the “Security” tab.  Click the “advanced” button and “Change Permissions” button.  Then click the “Add” button.  The first user you’ll need to add will be the IIS_IUSRS permission.  Click the “Check Names” button and it should add your machine name as the domain of this user (my machine name is “FRANK-PC”, yours will be different):


You’ll need to give IIS permissions.  I was able to make the API work with these permissions:

I would recommend doing more research before setting up your final API server.  I’m not going to cover this subject in this post.

Now click “OK”, “OK”, “OK”, etc.

Now run through those steps again: to add a user named IUSR, with the same permissions:




If you didn’t setup your URL in the hosts file, you’ll need to do that now. If you did this in the retriever section above, then you can skip this step.  

Navigate to C:WindowsSystem32driversetc and edit the “hosts” file with a text editor.  You’ll see some sample text showing the format of a URL.  Create a domain name on a new line like this:

127.0.0.1        www.franksdomain.com

Remember, you can makeup your own domain name.

Now, let’s test the site.  First, we need to determine what the URL will be when we access our API.  The easy method is to go into the IIS control panel and click on the “Browse urlname.com on *80 (http)” link:

Now you can copy the URL in the browser that popped up:

http://www.franksdomain.com/WebApiDemo


This URL is actually the URL to the MVC website in your application.  In order to access your API, your going to have to add to this URL:

http://www.franksdomain.com/WebApiDemo/api/MyApi

How did I get the “api/MyApi“?  If you go to your MVC application and navigate to the “App_Start/WebApiConfig.cs” file, you’ll see this default setup:

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



So the URL contains “api” and then the controller name.  Remember the previous code for the API controller:

public class MyApiController : ApiController

Ignore the “Controller” part of the class name and you’ll have the rest of your path.  Put this path string in the app.config file of your retriever application and compile both applications.  

Startup fiddler.  Run your retriever.  Your retriever should run through without any errors (unless you or I missed a step).  In fiddler, select JSON for the top right and bottom right panes. You should see something like this:

Notice that the retriever sent a request for product ids 2,3,4 and the API returned detailed product information for those three products (Spoon, Fork and Knife).  You might need to expand the tree-views in your JSON panels to see all the information like that shown in the screen-shot above.


Setting a Breakpoint in the API Application


Your API application doesn’t really run until it is accessed by IIS.  So we need to run the retriever once and then we can set our debugger to attach to the application process.  Once you run your retriever, go to your API application, in Visual Studio click on the “Debug” menu, then select “attach to process“.  Then make sure the “Show processes from all users” is checked at the bottom of the dialog box.  Then find the process named “w3wp.exe” and click on it. 



Click the “attach” button.  Then click the “attach” button in the pop-up dialog.  You’ll notice that your application is now “running” (you can tell by the red stop button in your tool bar):


Put a break-point in your code.  Run the retriever program and you see your API project pop-up with your break-point waiting for you.  Now you can step through your program and inspect variables (such as the request variables that were received, hint, hint) just like you ran this program using the F-5 key.



Summary

There are a lot of little things that must occur correctly for this API to work properly.  Here are a few things to look out for:

– Your firewall could also block requests, so be on the lookout for that problem.  
– If you don’t have the correct URL setup in your retriever, you will not get a connection.  
– The objects you use to serialize and de-serialize JSON data must match between your retriever and API applications.  
– The IIS server must have the correct rights to the API application directory.  
– You need to setup the correct .NET type in your IIS application pool.
– Verify that IIS is running on your PC.
– Verify your inputs on your API by attaching to the w3wp.exe process and breaking on the first line of code.
– Verify your output from your retriever using fiddler.

Getting the Sample Projects

You can download the two sample projects from my GitHub account:  
https://github.com/fdecaire/WebApiDemo