locked
How to Enhance Web API Endpoints with HttpResponseMessage ? RRS feed

  • Question

  • User-94355476 posted

    I've successfully built an OWIN-based Web API using C#.  However, currently the endpoints just return data directly - ie. a string, a List of files, etc.

    I'd like to enhance them to return HttpResponseMessages / HttpResponseExceptions instead so that I can bundle the data with status codes and, where warranted, an error message.  To this end, I scoured many forum postings and tutorials but could not find one "solution" that works correctly.

    What I'm looking for is two-fold:

    • C# code on the Web API side
    • jQuery / Javascript code on the Client side

    Any examples would be much appreciated!

    Thank you,

    Robert

    Wednesday, December 21, 2016 3:00 AM

Answers

  • User-2057865890 posted

    Hi Rebert,

    jQuery.ajax()

     $(document).ready(function () {
                $.ajax({
                    url: 'http://localhost:52807/api/products',
                    type: 'Get',
                    dataType: 'json',
                    data: { 'id': 10 },
                    success: function (data, textStatus, xhr) {
                        
                    },
                    error: function (xhr, textStatus, errorThrown) {
                        if (xhr.getResponseHeader('Content-Type').indexOf('application/json') > -1) {
                            // only parse the response if you know it is JSON
                            var error = $.parseJSON(xhr.responseText);
                            alert(error.Message);
                        } else {
                            alert('error');
                        }
                    }
                });
            });

    APIController

    public class ProductsController : ApiController
    {
           Product[] products = new Product[]
           {
                new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
                new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
                new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
           };
    
            public HttpResponseMessage Get(int id)
            {
                var product = products.FirstOrDefault((p) => p.Id == id);
                if (product == null)
                {
                    var error = new HttpError("Not Found Products.");
                    return Request.CreateErrorResponse(
                               HttpStatusCode.InternalServerError,
                               error);
                }
                HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, products);
                return response;
            }
    }

    reference: http://stackoverflow.com/a/18252657

    Best Regards,

    Chris

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, December 22, 2016 2:35 AM

All replies

  • User-2057865890 posted

    Hi Robert,

    The following articles show how to use HttpResponseMessage with  HTTP responses for returning a message/data with “HttpStatusCode” from WebApi action.

    reference:

    https://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/action-results 

    http://www.c-sharpcorner.com/UploadFile/036f9e/httpresponsemessage-in-webapi166/ 

    Best Regards,

    Chris

    Wednesday, December 21, 2016 10:17 AM
  • User-94355476 posted

    Chris,

    Thanks, though these were two of about 20 pages I'd already checked out.

    One immediate question for you:

    • What would be the structure (syntax) of the jQuery Ajax call to an API endpoint?  I need one that has an error/failure clause in it.

    Robert

    Wednesday, December 21, 2016 6:15 PM
  • User-2057865890 posted

    Hi Rebert,

    jQuery.ajax()

     $(document).ready(function () {
                $.ajax({
                    url: 'http://localhost:52807/api/products',
                    type: 'Get',
                    dataType: 'json',
                    data: { 'id': 10 },
                    success: function (data, textStatus, xhr) {
                        
                    },
                    error: function (xhr, textStatus, errorThrown) {
                        if (xhr.getResponseHeader('Content-Type').indexOf('application/json') > -1) {
                            // only parse the response if you know it is JSON
                            var error = $.parseJSON(xhr.responseText);
                            alert(error.Message);
                        } else {
                            alert('error');
                        }
                    }
                });
            });

    APIController

    public class ProductsController : ApiController
    {
           Product[] products = new Product[]
           {
                new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
                new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
                new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
           };
    
            public HttpResponseMessage Get(int id)
            {
                var product = products.FirstOrDefault((p) => p.Id == id);
                if (product == null)
                {
                    var error = new HttpError("Not Found Products.");
                    return Request.CreateErrorResponse(
                               HttpStatusCode.InternalServerError,
                               error);
                }
                HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.OK, products);
                return response;
            }
    }

    reference: http://stackoverflow.com/a/18252657

    Best Regards,

    Chris

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, December 22, 2016 2:35 AM
  • User-94355476 posted

    Chris, this is wonderful!  Thank you!!!

    I will test this out over the next 24 hours.

    Merry Christmas!

    Thursday, December 22, 2016 2:37 AM
  • User-94355476 posted

    I was too excited to wait so I used your code as a model for my own.  It works really great.  Thank you again.

    In hindsight, I just didn't have the correct syntax for the Ajax call.  Now that I know how to do it, I will replicate this throughout my code!

    Thursday, December 22, 2016 3:19 AM
  • User-94355476 posted

    Chris, I have a follow-up question.  Here's an example of one of my Javascript functions, now that I've modified it to use the syntax that you kindly provided:

    function PopulateEditor(org, repo, file) {
        var url = "api/orgs/" + org + "/repos/" + repo + "/files/" + file;
    
        $.ajax({
            url: baseUri + url,
            type: "Get",
            dataType: "json",
            success: function (data, textStatus, xhr) {
                $(data)
                    .each(function (i, item) {
                        AddSection(item.Filename);
                    });
    
                $(".selectSection").val($(".selectSection option:first").val());  // Select the first Option in the Select
                HandleSectionChange($(".selectSection option:first")); // Prepare all elements associated with the Section selection
                CheckForNoSections();  // Invokes a special dialog box if no sections exist after they were supposedly populated
            },
            error: function (xhr, textStatus, errorThrown) {
                if (xhr.getResponseHeader("Content-Type").indexOf("application/json") > -1) {
                    // only parse the response if you know it is JSON
                    var error = $.parseJSON(xhr.responseText);
                    alert(error.Message);
                } else {
                    alert("Unknown Error");
                }
            }
        });
    }

    It has occurred to me that the same construct will be used throughout my app, with the code repeated for every endpoint call I make.  The pattern will very frequently be the same, namely:

    1. Initial parameters
    2. Success function, which will need to execute one or more lines of code
    3. Error function

    In my mind, this is "screaming" for a common function to call, into which I'll pass it initial parameters, plus a success function - a different one for each endpoint.

    Would this be the approach you'd take?  If not, why not?

    Robert

    Thursday, December 22, 2016 8:42 PM