Basic ASP.NET Core API Test with Postman

I had a reader email me about using Postman with ASP.NET Core API base on this post from a couple of years ago. Rather than working through that their specific issues are with that code, I thought it might be more helpful to write a post on creating a super basic ASP.NET Core API and use Postman to test it.

API Creation

We are going to use the .NET CLI to create and run API project so no Visual Studio or other IDE will be needed. The first step is to open a command prompt and navigate to (or create) the directory where you want the API project to live. Run the following command to create the API project.

dotnet new webapi

The webapi template creates a ValuesController with a Get action that returns an array with two values in it which we will be using as our test endpoint.

After the process finished we can now run the project using the following command.

dotnet run

After the run command, you should see something like the following.

Hosting environment: Production
Content root path: C:\YourProjectPath\ApiTest
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

The key bit in the above you need to look for is the Now listening on line as that is the URL we will need to use in Postman to test.

Testing with Postman

Postman is a great tool that to use when developing an API. It allows me to exercise all the functions of the API before any clients have been built. You can do some of the same things using a browser, but Postman was built for this type of usage and it shows. Postman is free and you can grab it here.

Run Postman and you will see something similar to the following screenshot.

For our simple test we want to do a Get request, which is the default, so all we need to do is past the URL from above into the address box and add in the route to the controller we are trying to test. For our sample to test the Get action on the ValuesController our URL ends up being http://localhost:5000/api/values.

Click the Send button and the results will show the lower area Postman (the large red box in the screenshot).

Wrapping Up

This is the simplest setup I could think of to get up and going with Postman and ASP.NET Core. Postman has so many more functions than I showed in this post so I hope this will be a good jumping off point for you all to learn more about this great tool.

Add and Delete from an API

A few weeks ago I covered creating a basic API to retrieve contacts. In this post I am going to expand on that example by adding the ability to create and delete contacts. Before starting it would be a good idea to review my post on API basics as well as make sure you have a tool such as Postman to exercise your API.

First is the function for the creation of a new contact which will be an http post that accepts a contact, does some validation and inserts the contact to the database.

[HttpPost]
public async Task Create([FromBody] ContactModel contact)
{
    if (contact == null)
    {
        return HttpBadRequest();
    }

    if (!ModelState.IsValid)
    {
        return new BadRequestObjectResult(ModelState);
    }

    _dbContext.Add(contact);
    await _dbContext.SaveChangesAsync();

    return CreatedAtRoute("GetById", 
                          new {controller = "Contacts",
                               id = contact.Id}, 
                          contact);
}

First thing to notice is the HttpPost attribute that says this function only handles HTTP posts. Next notice the FromBody attribute on the contact parameter of the function call. This tells ASP to bind the contact object to the data provided by the request body so that the function has a hydrated contact object to work with.

Both if statements are doing validation. The first is making sure that contact has a value. The second if is a bit of magic provided by ASP. ModelState contains information about the state of the model, a contact in this case, after it is bound to the values from the HTTP request. The contact model has data annotations which will cause ModelState.IsValid to return false if the model fails to validate against any of the data annotations. Both set of variations return a HttpBadRequest, but the ModelState version passes back the ModelState to the client since it contains details of all failed validation.

If all validation passed then the new contact is added to the controller’s dbContext and the dbContext saves changes inserts the new contact into the database.

Finally a route to the newly inserted contact is returned to the client. CreatedAtRoute takes a route name, route values and a value. In this case it is saying run the “GetById” route for the contacts controller with the ID of the new contact.

In order to get CreatedAtRoute to work the Get overload that takes an ID needed a name which is provided as part of the HttpGet attribute.

[HttpGet("{id}", Name = "GetById")]
public async Task Get(int id)

Now to add a contact with the API using Postman. First click Get which will drop down a list of HTTP verb to choose from. For adding a new contact we need to use Post.

postmanHttpVerb

After selecting post the body tab will be enabled. On the body tab select raw from the radio buttons. Next click the drop down that says text and select JSON (application/json) since the data for the contact will be sent to the API as JSON.

postmanBodyTypeFinally enter the appropriate JSON and click send. All that is required to create a new contact with my API is a name so the follow JSON is what I used to test.

{"Name" : "John McTest"}

At this point if all went well you will find John McTest in database. If all went well Postman will give the option to view the response which would include the Id which was set when dbContext.SaveChangesAsync was called.

The delete function is much simpler. It just needs the HttpDelete attribute and takes the ID of the contact to be deleted.

[HttpDelete("{id}")]
public async Task Delete(int id)
{
    var contact = await GetContacts()
                          .Where(c => c.Id == id).FirstOrDefaultAsync();

    if (contact == null) return;

    _dbContext.Remove(contact);
    await _dbContext.SaveChangesAsync();
}

Using the dbContext the contact is retrieved for the ID passed in. If the contact is not found the function just returns since the contact has already been removed from the database. If the contact is found then the remove function of the dbContext is used to mark the contact for delete and then save changes of dbContext is used to send the delete command to the database.

To test with Postman select delete from the list of HTTP verbs, this is the same drop down that was used to select post above. Next enter the ID to be deleted in the URL box and click send. In the screenshot below the API will be told to delete the contact with the ID of 108.

postmanDelete

Check out the ASP.NET 5 docs for a great API example that uses Fiddler instead of Postman.

Basic Web API with ASP.NET 5

I am going to create basic web API access to the contacts data I have been using in previous posts. To start with I added an API folder to my project to hold my API controller. Next I added a contacts controller to the API folder by right clicking on the folder and selecting add new item.

AddNewItem

From the add new item under DNX selected Web API Controller Class, entered a name and clicked add.

AddNewItemDialog

From the resulting code I removed all the actions except for two get functions.

[Route("api/[controller]")]
public class ContactsController : Controller
{
    private readonly ContactsDbContext _dbContext;

    public ContactsController(ContactsDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    // GET: api/values
    [HttpGet]
    public async Task<IEnumerable<ContactModel>> Get()
    {
        return await GetContacts().ToListAsync();
    }

    // GET api/values/5
    [HttpGet("{id}")]
    public async Task<ContactModel> Get(int id)
    {
        return await GetContacts()
                     .Where(c => c.Id == id).FirstOrDefaultAsync();
    }

    private IQueryable GetContacts()
    {
        var contacts = from c in _dbContext.ContactModels
                                 .Include(c => c.AddressModels)
                                 .Include(c => c.EmailAddressModels)
                                 .Include(c => c.PhoneModels)
                       select c;
        return contacts;
    }
}

The above code contains a lot of new concepts I am going to break it down more.

[Route("api/[controller]")]
public class ContactsController : Controller

The first thing to notice is the route attribute on the class declaration. The route attribute is how the routing engine determines where to send requests. Using [controller] tells the routing engine to use the class name minus the word controller. For example the above route handles api/contacts.

private readonly ContactsDbContext _dbContext;

public ContactsController(ContactsDbContext dbContext)
{
    _dbContext = dbContext;
}

The constructor takes the DbContext needed to access contacts. Note that the context is being automatically injected via the constructor thanks to the fact that ASP.NET 5 now comes with dependency injection out of the box.

// GET: api/values
[HttpGet]
public async Task<IEnumerable<ContactModel>> Get()
{
    return await GetContacts().ToListAsync();
}

// GET api/values/5
[HttpGet("{id}")]
public async Task<ContactModel> Get(int id)
{
    return await GetContacts()
                 .Where(c => c.Id == id).FirstOrDefaultAsync();
}

First get function returns all contacts and the second returns a specific contact based on the contact’s ID.

private IQueryable<ContactModel> GetContacts()
{
    var contacts = from c in _dbContext.ContactModels
                             .Include(c => c.AddressModels)
                             .Include(c => c.EmailAddressModels)
                             .Include(c => c.PhoneModels)
                   select c;
    return contacts;
}

Note that the query contains three includes and each of the included classes contain a navigation property back to the main contact. For example here is the email address model.

public class ContactEmailModel
{
    public int ContactId { get; set; }
    public int Id { get; set; }
    [EmailAddress]
    public string Address { get; set; }

    public ContactModel Contact {get; set;}
}

All of the above compiles and seems to run fine, but will not provide a response. The navigation property for contact creates a circular reference that the response serializer throws an exception trying to serialize.

Thankfully the framework has a configuration option to work around this problem. In the ConfigureServices function of the Startup class add the following.

services.ConfigureMvcJson(options =>
{
    options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.All;
});

The above options marks the Contact property as a reference and does not try to circularly serialize it.

Now by running the project and going to http://localhost:port/api/contacts/1 in the browser I get all the contact data related to the contact with an ID of 1. I recommend using something like Postman to make the result more readable if you don’t have a front end to display the data.