Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

.NET Core Web API: The Least You Need To Know (Part 1 of 2)

4.95/5 (16 votes)
20 May 2020CPOL15 min read 15.3K   162  
A quick article to walk you through building your .NET Web API and posting to it via AJAX (using JSON)
Have you ever wanted to gen up a quick Web API to run some server side functionality? Follow this article and you'll have a working Web API and understand how to use vanilla JavaScript to post your JSON to it via XMLHttpRequest (AJAX).

Background

Recently, while easing into using a .NET Core Web API, I discovered that I wasn't sure of the correct way to post data to a Web API via the XMLHttpRequest (XHR) object.

I wasn't sure about:

  1. how to add the data to the XHR object so that it would show up in the post body.
  2. how to ensure the Web API would automatically transform the posted JSON into my target domain object.

I was getting all kinds of errors and I couldn't tell if I had the client side wrong or the Web API side wrong, or both. I discovered that both were wrong, but I also discovered that it is quite difficult to find a definitive answer to this even though you'd think it was a common pairing (plain JavaScript XHR posting to Web API).

What this Article Covers

  1. Creating a .NET Core Web API project (via command-line) - I use Visual Studio Code running on Ubuntu Linux
  2. Adding a Web API method which can be posted to
  3. Altering the Web API application so it will serve an index.htm file (for testing our Web API)
  4. Setting up a simple index.htm and main.js file that we use to post to the Web API
  5. Configuring an XMLHttpRequest (XHR) to post JSON to the Web API

Introduction

I'm assuming you already have the latest copy of Visual Studio or Visual Studio Code on your machine.

Of course, you'll also need to ensure you have the latest version of .NET Core installed too. If you need that, you can go to https://dotnet.microsoft.com/download^.

I'm running Visual Studio Code on Ubuntu Linux so I do everything from the command-line but if you're running on Windows and using Visual Studio, you can create the .NET Core Web API using a wizard. The command-line really isn't difficult with .NET Core though and you'll probably find it quite satisfying.

Create the New Project

To get started, take the following steps:

  1. Open a Console (or terminal).
  2. Navigate to a directory where you want to create a new project.
  3. Type the following command: dotnet new webapi --name MainWebAPI

A New Folder Will Be Created

When you type that command and hit <ENTER>, it will create a new subfolder named MainWebAPI and add all of the project files into the directory.

If it was successful, you will see something like the following:

create .net web api project

If you get some kind of error that the command is not recognized, then you probably do not have the .NET Core SDK installed. To determine the version of the .NET you have installed, you can try the following command:

dotnet --version

Mine replies with 3.1.202.

If all of that went well, then you have a very basic Web API that runs on top of .NET Core.

Run the Web API Project

Let's make sure that the project will compile and run. It's very easy.

First of all, just change directory into the newly created project directory: cd MainWebAPI

Next, type: dotnet run

.NET will build and start the Web API.

It'll look something like the following:

get dotnet version

Just Build the Project

By the way, if you had just wanted to build the project, you could've typed: dotnet build

See the Web API in Action

To see the Web API do something, you can hold your CTRL button and click the link (https://localhost:5001) that is displayed in the console window. When you do, your default browser will open the link.

But it's not very amazing because you haven't made a call to any Web API method.

You'll just see a blank web page.

One Web API Method Via Get

However, there is one method that you can call via the GET. Try this URL: https://localhost:5001/WeatherForecast/^.

That calls the default Get method on the WeatherForecastController* class. That method just generates some random WeatherForecast* domain objects and then sends them to the client as JSON.

* I'll show you both of these classes in just a moment when we look at the code.

You'll see something like one of the following two images in your browser (depending upon how your browser renders the JSON).

web api json formatted

web api raw JSON

Now that you've seen the code run, let's take a look at the code and begin altering the WeatherForecastController so that we can post JSON to it and have it turn our JSON into a domain object automatically.

Visual Studio Code

I'm going to be using Visual Studio Code (VSC) throughout this article, but you can still use Visual Studio if you prefer.

Go ahead and start Visual Studio Code (VSC) and then we'll open the project.

Open a Folder

To load the project in VSC, you:

  1. go to the main menu
  2. choose the [File...]menu item
  3. choose the [Open Folder...]
  4. Navigate to the folder that was created when we created the project and select it

When you follow those steps, you'll see something like the following:

visual studio code

Highlighted Areas

I've highlighted a few areas in VSC so we can talk about them.

Toolbar

The first section is the toolbar which includes a few icons.

File View

The currently selected one is highlighted in white and indicates that File View is displayed. You can see that in the second section there is a list of files. However, if you choose one of the other icons, this section will change.

Debug View

During this article,we will also use the Debug item to show you how you can step through your Web API code using VSC. The Debug item is indicated by the debug icon.

However, to use the debugger in VSC you have to make sure that you have the C# Extensions plugin installed and running.

Plugins View

The plugins view is indicated by the plugins icon.

You can see that section 4 of the VSC overview image that I provided above is actually VSC warning me that the C# Extension plugin needs to be added to the project so we can debug the code. If you see that and click the [Yes] button, then it will add it to the project. However, you may not see that if the extension hasn't been added to your system.

Also, that pop-up tends to disappear quickly. That's okay though, because you can click the Plugins icon and add the plugin to your system and project any time.

Here's what it looks like once it is installed and activated:

plugin view with C# extensions

Main Editor Area

Finally, you can see that the main editor area (area 3 on the VSC image above) is currently displaying notes about the current version of VSC. This is the area where each file will display when you choose them from the File Viewer area.

Now that you are more familiarized with VSC, let's start looking at the WeatherForecastController.

Examining the WeatherForecastController

Opening a File in a SubDirectory

Make sure you are on File View. Next, in the File View, find the Controllers directory. It will have a down right-arrow (great-than sign) pointing at the Controllers name. That's indicating a folder that is currently collapsed. Click on the Controllers folder and select the WeatherForecaseController.cs that appears, and it will display in the editor area.

Controller: Application Logic Layer

I'm not going to explain every aspect of the Controller code. You can think of the controller in general as the application logic layer. Here's the basics of what happens.

A user requests an action (function or method) on a Controller by sending an HTTP Command (GET, POST, PUT, etc.^) to the named Controller (described by the URL) on the server.
Note: In this article, we will only deal with the POST command.

As developers, we can write code in the Controller method that runs application logic that provides specific functionality. It's really that simple.

The Get method that the project template included in the Controller looks like:

C#
[HttpGet]
 public IEnumerable<WeatherForecast> Get()
 {
     Console.WriteLine("in get...");
     var rng = new Random();
     return Enumerable.Range(1, 5).Select(index => new WeatherForecast
     {
         Date = DateTime.Now.AddDays(index),
         TemperatureC = rng.Next(-20, 55),
         Summary = Summaries[rng.Next(Summaries.Length)]
     })
     .ToArray();
 }

It's probably obvious, but the [HttpGet] method decorator tells the compiler to make this method available via HTTP Get.

This method simply generates an array of five WeatherForecast objects (domain objects) and returns them. They will be serialized to JSON automatically and that is what we saw in the browser earlier.

Our Main Challenge

The challenge here is how to post data to the WeatherForecast Controller so that it will be automatically deserialized into a WeatherForecast object.

First of all, let's add the most basic Post method to our controller.

C#
[HttpPost]
public String Post(){
    Console.WriteLine("in post...");
    return "It worked!";
}

First of all, notice that we changed the decorator to [HttpPost] so that this method will fire when the user posts to the URL http://localhost:5001/WeatherForecast.

Default Post Method

This internal method name is Post() but externally there is no action (method name) shown so that means when the user posts directly to the Controller, this is the default action (method that will run) which will occur.

There is a way to provide an external name that can then be supplied on the WeatherForecast controller URL and I will show you that in a moment.

Secondary Challenge: Client Side Post Creation

Now, we have the challenge of testing the Post() method on the WeatherForecast controller. Since we can no longer use the browser just to navigate to the URL (simple HTTP Get), we need some other way to invoke an HTTP Post from the client.

First Easiest Post Test

The first and probably easiest way to do a Post to the controller is to download PostMan and set it up. There are other tools, but PostMan is probably the easiest one and it is free.

Go to https://www.postman.com/downloads/^, get the free utility and install it for your system.

Once you do and you start it up, we can try posting to our controller.

Walkthru: PostMan Request

The PostMan User Interface is a bit jumbled but it's easy enough to create a new request and I will walk you through it.

Create a New Request

The first thing you want to do is create a new request. To do that, you can choose the [New] button and choose [Request] when the menu appears. Or, you can click the [Create a Request] option. Both of these are shown highlighted in red, in the next image.

postman main UI

Once you choose one of those options, you will see a new form. In the image, you can see that I've also dropped the list of HTTP Actions to show you that is where you can select which one you will use when submitting the request. First, we'll try the simple Get.

new postman request

PostMan: Configuration Change

However, before we make our first request, you need to make one change to the PostMan default settings. If you do not, then all of your requests will fail because PostMan does not support self-signed certificates.

If you do not change the setting, then you will see an error like the following (notice blue highlighted text for error).

HTTPS: Self-signed Certificates Not Supported

postman error on certificate

To fix that, you simply go to File...Settings... in PostMan and turn off the option highlighted in red (shown here still turned on) - SSL certificate verification.

turn off certificate verification

Once you do that and close the Settings window, you can proceed and it will work.

Go ahead and select the Get command from the drop list.

Next, add the following URL and then press <ENTER> or click the [Send] button.

Once you do that, you'll see similar results to what we saw before (in the browser), but just formatted in the way PostMan formats things.

postman get results

Keep in mind that was the result of calling the default Get() action on the WeatherForecast controller. I mention this as a way to remind you that we did not add any action name (specific) method on the URL.

Post to WeatherForecastController

Now, let's simply change the HTTP Verb to Post in PostMan and try again.

Here's the new and very basic result:

Post result via PostMan

That is all great, but what we want to do is post some JSON to the controller and have it automatically transform the JSON into our domain object (WeatherForecast).

Posting JSON: Attempt 1

The first thing we need to understand is what the target domain object looks like. What properties does it have?

We can take a look at the WeatherForecast class back in VSC.

WeatherForecast Class Analysis

It's a very simple class. Here's the entire code listing for that class.

C#
using System;
 
namespace MainWebAPI
{
    public class WeatherForecast
    {
        public DateTime Date { get; set; }
 
        public int TemperatureC { get; set; }
 
        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
 
        public string Summary { get; set; }
    }
}

It's really just made up of four properties (although one of them does run a function to get its value).

  1. Date
  2. TemperatureC // (temp in Celsius)
  3. TemperatureF // (calculated temp in Fahrenheit)
  4. Summary // text-based summary of the weather

JSON: Name / Value Pairs

Since we know that JSON (JavaScript Object Notation) is simply name value pairs which define an object, we can create our own WeatherForecast (with data) very easily. Here's the one we'll use for our tests.

JavaScript
{"Date":"2015-05-03", "TemperatureC":37,"Summary":"Our weather data"}

Notice that since the TemperatureF is calculated from the TemperatureC, I don't even include that property in our JSON.

Brackets: Think Object - Quick JSON Summary

Here's a quick way to think about what you see in the JSON. The curly brackets indicate the start and end of an object. Each value before a colon indicates a property name and each value after a colon indicates a property value. Each name/value pair are separated by commas. Each property name must match a property in our target class.

That's it, so let's try it out using PostMan.

Change WeatherForecastController Post Method

We have to make one change in our default Post() method in our WeatherForecastController. We have to make sure it is expecting to receive a WeatherForecast object.

Let's open up WeatherForecastController in VSC and make the change.

We'll also change the method to return an Int32 and we'll return the TemperatureF so that you can see that the value is generated. This also provides us with a somewhat usuable Web API method (though a bit contrived) because you can send in a WeatherForecast object where you know the Celsius temperature and the method will return the temperature in Fahrenheit.

Here's the altered default Post() method.

C#
[HttpPost]
public Int32 Post(WeatherForecast wf){
    Console.WriteLine("in post...");
    return wf.TemperatureF;
}

Make Changes and Run

Once you make those changes, then go back to your console and:

  1. close the program if it was already running (press CTRL-C to end the session)
  2. build and run the application again -- dotnet run will build and run the app again
  3. Copy the JSON we created above
  4. Go back to PostMan
  5. Click the [body] tab (see next image)
  6. Select the [raw] (next image) radio button
  7. Paste the JSON into the editor area.
  8. Click the [Send] button.

When you do all of those steps, you will see the following result (error).
Note: I used one image to show multiple steps and the result.

postman setup and error result

Error Explanation

It's a bit confusing, but that bottom portion is the result after posting our JSON to the Controller. We didn't get the expected response (TemperatureF), but instead we got some JSON that is describing the problem.
It's difficult to tell that an error even occurred and where the error occurred.

Console.WriteLine of Post() Method Doesn't Run

Keep in mind that our default WeatherForecastController has a Console.WriteLine() call that attempts to output a message. That should output some text to our console window where the application is running, but if you look, there is no output. That provides us with a clue that our method never ran.

Unsupported Media Type

The real clue to what happened is the Error 415 and the message "unsupported media type". It is still cryptic though and if you're just starting out, you'll really wonder what it all means. After much searching and reading, you'll find that it means that the server doesn't know what type of data we are posting to it and it doesn't like that.

Fix the Problem with an HTTP Header

We can tell the server the type of data we are sending by adding an HTTP Header to our Post action.

The server wants to know what type of data you are sending so it can properly use the data. Let's go add the proper HTTP Header to our PostMan Post action and try again.

HTTP Headers: Name / Value Pairs

HTTP Headers are metadata (data sent with the actual data to describe the data) which are sent along with the data. To add a name / value pair to the PostMan headers, we just need to:

  1. select the Headers tab (see next image)
  2. add a new header named : Content-Type (type this in the list under Key (same as Name))
  3. add a new value for the added Key: application/json

That Key and value are both predefined values that are described by the HTTP specification which the server will understand.

adding header to PostMan

Now, when you post again, the server will understand that incoming content is JSON and should be handled as JSON.

After you've made those changes, go ahead and click the [Send] button in PostMan again and this time, you will get a valid result. 98 Fahrenheit is the same temperature as 37 Celsius (the value we sent into the WeatherForecastController in our JSON).

TemperatureF returned successfully

You can also tell that the WeatherForecastController Post() method did indeed run because back in your console window, there is some output from the call to Console.WriteLine():

console output

Automatic Convert to Domain Object: Amazing!

Also, think about how amazing it is that underlying .NET Core Web API automatically converted our JSON into our domain object (WeatherForecast).

You can tell that it did that automatically because our default Post() method simply takes a parameter of type WeatherForecast and we referenced a property of the object in our return statement:

C#
return wf.TemperatureF;

Wrapping Up Part 1

I hope you found Part 1 of this article series instructional and that it revealed a few of the trickier elements (HTTP Headers, HTTP Post and using PostMan) in a clear way.

However, since this article is already so long, I've decided to put the rest of the article in Part 2.

Now that we understand that we need...

  1. JSON data added to the Post body
  2. Special Content-Type header added to the Post action

...that will make it much easier to understand how we are going to use AJAX (XMLHttpRequest object) via JavaScript to post data to our Web API controller.

Using the Code

  1. Download the zip file.
  2. Unzip to your Dev directory (there is an outer folder named MainWebAPI that contains all files and subfolders).
  3. Open console and change directory to \MainWebAPI.
  4. Run command /> dotnet run.
  5. The application will build and start the web server.

History

  • 20th May, 2020: Part 1 submitted

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)