Implementing a CRUD ASP.NET web API

In this recipe, we will see how to create an ASP.NET web API that supports CRUD operations, which stands for Create Read Update and Delete . These map to the standard database operations that correspond to the following HTTP verbs:

  • GET: The GET method retrieves whatever information is identified by the requesting URI
  • PUT: The PUT method requests that the enclosed entity is to be stored under the supplied requesting URI
  • POST: The POST method requests that the enclosed entity is to be a subordinate of the resource identified by the requesting URI
  • DELETE: The DELETE method requests that the resource identified by the requesting URI should be deleted

In this recipe, we will see how to implement these CRUD features on the previously created service, with the HTTP verbs, and the ASP.NET web API.

Getting ready

In order to use this recipe, you should have Visual Studio 2012 and ASP.NET MVC 4 installed (the latter one includes the ASP.NET web API). You should also have the project resulting from our previous recipe.

How to do it...

Here we are going to implement the CRUD verbs into the web API that we created in our previous section:

  1. Copy our previous recipe project into a new folder and name it WebAPICRUD.
  2. Create a class with the name of IRepository.cs with the following code:
    public interface IRepository<T> where T : class
    {
        IEnumerable<T> GetAll();
        T GetById(int id);
        void Insert(T entity);
        void Update(T entity);
        void Delete(T entity);
    }
  3. Add a class named BooksRepository.cs containing the following code:
    public class BooksRepository : IRepository<BookModel>
    {
        ObservableCollection<BookModel> ocBooks = null;
        public BooksRepository()
        {
            ocBooks = GenerateBooks();
        }
        private ObservableCollection<BookModel> GenerateBooks()
        {
            ObservableCollection<BookModel> Books = new ObservableCollection<BookModel>() { 
                new BookModel(){
                        Id=1,
                        Title = ".NET 4.5 First Look",
                        Description = "A book to quickly and practically get into .NET 4.5"
                },
                new BookModel(){
                        Id=2,
                        Title = "The lost book of Agatha Christie",
                        Description = "A book everybody wants to read..."
                }
            };
            return Books;
        }
        public IEnumerable<BookModel> GetAll() {
            return ocBooks;
        }
        public BookModel GetById(int id) {
            var book = (from b in ocBooks
                        where b.Id == id
                        select b).FirstOrDefault();
            return book;
        }
        public void Insert(BookModel book) {
            book.Id = GetLatestIdPlusOne();
            ocBooks.Add(book);
        }
        private int GetLatestIdPlusOne()
        {
            int BiggestId = 0;
            foreach (BookModel book in ocBooks)
            {
                if (BiggestId < book.Id) {
                    BiggestId = book.Id;
                }
            }
            return (BiggestId + 1);
        }
        public void Update(BookModel book) {
            this.Delete(book);
            ocBooks.Add(book);
        }
        public void Delete(BookModel book) {
            BookModel bookToRemove = GetById(book.Id);
            ocBooks.Remove(bookToRemove);
        }
    }
  4. And substitute the following code for our BooksController.cs content:
    public class BooksController : ApiController
    {
        static readonly IRepository<BookModel> BooksRep = 
            new BooksRepository();
        public IEnumerable<BookModel> Get()
        {
            return BooksRep.GetAll();
        }
        public HttpResponseMessage Get(int id)
        {
            BookModel bm = BooksRep.GetById(id);
            if (bm != null)
            {
                return Request.CreateResponse<BookModel>(HttpStatusCode.OK, bm);
            }
            else {
                return Request.CreateResponse<BookModel>(HttpStatusCode.NotFound, null);
            }
        }
        public void Put(BookModel bm) {
            BooksRep.Update(bm);
            HttpResponseMessage hrm = Request.CreateResponse<BookModel>(HttpStatusCode.Created, bm);
        }
        public HttpResponseMessage Post(BookModel bm)
        {
            BooksRep.Insert(bm);
            HttpResponseMessage hrm = Request.CreateResponse<BookModel>(HttpStatusCode.Created, bm);
            hrm.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = bm.Id }));
            return hrm;
        }
        public HttpResponseMessage Delete(BookModel bm)
        {
            BooksRep.Delete(bm);
            return new HttpResponseMessage(HttpStatusCode.NoContent);
        }
    }
  5. And that's it! We now have a ready to go (albeit very basic) web API that implements the main HTTP verbs.

How it works...

We started from a copy of our past web API project so we could re-use the basics.

Next we implemented the repository pattern, with the IRepository interface and the BooksRepository class. This is a good practice to increase readability and testability, even if our actual implementation is working upon an observable collection in memory. If we wanted to improve this example to use a database, for example, we would just need to slightly change the BooksRepository implementation of the IRepository interface.

On this repository, we implemented an initialization of our database, the GetAll() and Get(int id) functions and Insert(BookModel book) with a helper function GetLatestIdPlusOne() to get the largest book ID and add one to it.

We also implemented the Update() and Delete() methods.

To follow, we built the BooksController class, which we started from scratch. First, we added a static member of the type IRepository<BookModel>, associating it with a new BooksRepository:

static readonly IRepository<BookModel> BooksRep = 
       new BooksRepository();

With this singleton in place, we can use it wherever we want from our BooksController class, making it global to all the instances of the BooksController class.

We implemented the GET verbs first, in a very similar way to what we had done previously. However, in the current implementation, they are now more decoupled and the responsibility of getting the element now resides with the repository.

The PUT, POST, and DELETE verbs were also very straightforward to implement, by calling the method directly.

Additionally, you will observe that we have been returning an adequate HttpResponseMessage with each of these verbs, perfectly matching what the protocol is expecting.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset