ASP.NET Web API is the framework for creating HTTP services or RESTful services in the Microsoft platform. It super-cedes the WCF framework. Browsers in desktops, tablets or mobiles can access the Web API.
Comment API
In this post, we create a Web API for Comments. Create a new MVC application. Create a controller called CommentController
. It is an API controller with CRUD methods and integrates with Entity Framework.
public class CommentController : ApiController { private BlogContext db = new BlogContext(); // GET api/Comment public IEnumerable<Comment> GetComments() { return db.Comments.AsEnumerable(); } // GET api/Comment/5 public Comment GetComment(int id) { Comment comment = db.Comments.Find(id); if (comment == null) { throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound)); } return comment; } // PUT api/Comment/5 public HttpResponseMessage PutComment(int id, Comment comment) { if (ModelState.IsValid && id == comment.ID) { db.Entry(comment).State = EntityState.Modified; try { db.SaveChanges(); } catch (DbUpdateConcurrencyException) { return Request.CreateResponse(HttpStatusCode.NotFound); } return Request.CreateResponse(HttpStatusCode.OK, comment); } else { return Request.CreateResponse(HttpStatusCode.BadRequest); } } // POST api/Comment public HttpResponseMessage PostComment(Comment comment) { if (ModelState.IsValid) { db.Comments.Add(comment); db.SaveChanges(); HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, comment); response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = comment.ID })); return response; } else { return Request.CreateResponse(HttpStatusCode.BadRequest); } } // DELETE api/Comment/5 public HttpResponseMessage DeleteComment(int id) { Comment comment = db.Comments.Find(id); if (comment == null) { return Request.CreateResponse(HttpStatusCode.NotFound); } db.Comments.Remove(comment); try { db.SaveChanges(); } catch (DbUpdateConcurrencyException) { return Request.CreateResponse(HttpStatusCode.NotFound); } return Request.CreateResponse(HttpStatusCode.OK, comment); } protected override void Dispose(bool disposing) { db.Dispose(); base.Dispose(disposing); } }
There are methods for GET
, GET(1)
, PUT
, POST
and DELETE
. The URL for API is http://localhost:port/api/Comment
. APIs return JSON data.
WPF Client
Next, we create a WPF application. It uses a HTTP client to access the Web API. The WPF application has the DataGrid
layout, which displays all comments in a grid like fashion. The DataGrid is bound to an ObservableCollection<Comment>
. Each row contains a Delete button to delete the comment.
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="450" Width="600" xmlns:local="clr-namespace:WpfApplication1" > <Window.Resources> <local:MainViewModel x:Key="Model"></local:MainViewModel> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="50"></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition Height="50"></RowDefinition> </Grid.RowDefinitions> <Label Content="{Binding Source={StaticResource Model}, Path=ErrorMessage}"></Label> <DataGrid Grid.Row="1" Name="CommentsGrid" ItemsSource="{Binding Source={StaticResource Model}, Path=Comments}" AutoGenerateColumns="False" Width="510"> <DataGrid.Columns> <DataGridTextColumn Header="ID" Width="50" Binding="{Binding Path=ID}" IsReadOnly="True"></DataGridTextColumn> <DataGridTextColumn Header="Author" Width="100" Binding="{Binding Path=Author}"></DataGridTextColumn> <!--<DataGridComboBoxColumn Header="Auth Type" Width="100" ItemsSource="{Binding Path=AuthTypes}" SelectedItemBinding="{Binding Path=AuthType}"></DataGridComboBoxColumn>--> <DataGridTextColumn Header="Text" Width="250" Binding="{Binding Path=Text}"></DataGridTextColumn> <DataGridTemplateColumn Header="Delete" Width="100"> <DataGridTemplateColumn.CellTemplate> <ItemContainerTemplate> <Button Content="Delete" Command="{Binding Source={StaticResource Model}, Path=DeleteCommand}" CommandParameter="{Binding Path=ID}"></Button> </ItemContainerTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> </DataGrid.Columns> </DataGrid> <Button Grid.Row="2" Content="Save" Command="{Binding Source={StaticResource Model}, Path=SaveCommand}" Width="200" Height="30"></Button> </Grid> </Window>
There is also a Save button. Save
enumerates through each comment and updates the comment using a PUT
operation. If the update fails because the comment does not exist, we create the comment using a POST
operation.
public void Save(object obj) { HttpClient client = new HttpClient(); client.BaseAddress = new Uri("http://localhost:1121/"); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); ErrorMessage = ""; bool fail = false; foreach (Comment c in Comments) { HttpResponseMessage resp = client.PutAsync<Comment>(String.Format("api/Comment/{0}", c.ID), c, new JsonMediaTypeFormatter()).Result; if (!resp.IsSuccessStatusCode) { ErrorMessage += "Adding new item \n"; HttpResponseMessage resp2 = client.PostAsync<Comment>("api/Comment", c, new JsonMediaTypeFormatter()).Result; if (!resp2.IsSuccessStatusCode) { ErrorMessage += "Error in updating " + c.ID.ToString() + "\n"; fail = true; } else { Comment addedComment = resp2.Content.ReadAsAsync<Comment>().Result; c.ID = addedComment.ID; } } } if (!fail) ErrorMessage += "Update is successful\n"; }
The entire project can be found here: CommentApiDemo