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.
From the add new item under DNX selected Web API Controller Class, entered a name and clicked add.
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.
Basic Web API with ASP.NET 5 Read More »





























