Using a WPF client to access MVC Web API

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

Related Posts

Leave a Reply

Your email address will not be published.