locked
How client call a web Api which wil call another Web Api RRS feed

  • Question

  • User-1980778524 posted

    Hi I am new in web api. I have a scenario as below:

    A Client app will consume a Rest Api from Web Api (1) which will consume another Rest Api from Web Api (2).

    So,

    When client Consume Rest Api From Web Api (1),

    How this Web Api(1) call or consume a REST Api from Web Api(2).

    Please help.

    Thanks

    Friday, October 6, 2017 12:57 AM

All replies

  • User1120430333 posted

    What you would do is use a Service Layer that sits between the two services. The Service Layer classlib project, a client, consumes the second service. The first service sets reference  to the Service Layer, it calls methods on the Service Layer that calls methods on the second service.

    webapi calls SL that calls WCF service.

    DTO pattern is being used to pass data between all projects, some you don't see, with all DTO(s) in the Entities project.  

    https://en.wikipedia.org/wiki/Data_transfer_object

    https://www.codeproject.com/Articles/1050468/Data-Transfer-Object-Design-Pattern-in-Csharp

    using System.Collections.Generic;
    using System.Web.Http;
    using Entities;
    using Helper.Enums;
    using ServiceLayer;
    
    namespace WebAPI.Controllers
    {
        public class StudentController : ApiController, IStudentControllerAPI
        {
            private IServiceA srv;
            public StudentController(IServiceA service)
            {
                srv = service;
            }
    
            [HttpGet]
            public List<DTOStudent> GetStudents()
            {
                var dtos = srv.GetStudents();
    
                return dtos;
            }
    
            [HttpGet]
            public DTOStudent GetStudentById(int id)
            {
                return srv.GetStudentById(id);
            }
    
            [HttpPost]
            public void CreateStudent(DTOStudent dto)
            {
                srv.CreateStudent(dto);
            }
    
            [HttpPost]
            public void UpdateStudent(DTOStudent dto)
            {
                srv.UpdateStudent(dto);
            }
    
            [HttpPost]
            public void DeleteStudent(int id)
            {
                srv.DeleteStudent(id);
            }
    
            [HttpGet]
            public bool IsStudentAuthorised(ResourceTypeEnum resourceType, object resourceId, string username)
            {
                return Models.Helper.IsStudentAuthorised(resourceType, resourceId, username, srv);
            }
        }
    }
    
    using System;
    using System.Collections.Generic;
    using Entities;
    
    namespace ServiceLayer
    {
        public interface IServiceA
        {
            DTOStudent GetStudentById(Int32 id);
            List<DTOStudent> GetStudents();
            void CreateStudent(DTOStudent dto);
            void UpdateStudent(DTOStudent dto);
            void DeleteStudent(Int32 id);
            DTOEnrollment GetEnrollmentById(Int32 id);
            List<DTOEnrollment> GetEnrollments();
            void CreateEnrollment(DTOEnrollment dto);
            void UpdateEnrollment(DTOEnrollment dto);
            void DeleteEnrollment(Int32 id);
        }
    }
    

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Entities;
    
    namespace ServiceLayer
    {
        public class ServiceA : IServiceA
        {
            public List<DTOStudent> GetStudents()
            {
                var dtos = new List<DTOStudent>();
    
                var client = new WCFServiceReference1.Service1Client();
    
                dtos = client.GetStudents().ToList();
                 
                if (dtos[0].DtoResponse.Message != null)
                {
                    throw new Exception(dtos[0].DtoResponse.Message + " " + dtos[0].DtoResponse.InnerException
                        + " " + dtos[0].DtoResponse.StackTrace);
                }
    
                return dtos;
            }
    
            public DTOStudent GetStudentById(Int32 id)
            {
                var client = new WCFServiceReference1.Service1Client();
    
               var dto = client.GetStudentById(id);
    
                if (dto.DtoResponse.Message != null)
                {
                    throw new Exception(dto.DtoResponse.Message + " " + dto.DtoResponse.InnerException
                        + " " + dto.DtoResponse.StackTrace);
                }
    
                return dto;
            }
            public void CreateStudent(DTOStudent dto)
            {
                var client = new WCFServiceReference1.Service1Client();
    
                var dtor = client.CreateStudent(dto);
    
                if (dtor != null)
                {
                    throw new Exception(dtor.DtoResponse.Message + " " + dtor.DtoResponse.InnerException
                        + " " + dtor.DtoResponse.StackTrace);
                }
            }
            public void UpdateStudent(DTOStudent dto)
            {
                var client = new WCFServiceReference1.Service1Client();
    
                var dtor = client.UpdateStudent(dto);
    
                if (dtor != null)
                {
                    throw new Exception(dtor.DtoResponse.Message + " " + dtor.DtoResponse.InnerException
                        + " " + dtor.DtoResponse.StackTrace);
                }
            }
            public void DeleteStudent(Int32 id)
            {
                var client = new WCFServiceReference1.Service1Client();
    
                var dtor = client.DeleteStudent(id);
    
                if (dtor != null)
                {
                    throw new Exception(dtor.DtoResponse.Message + " " + dtor.DtoResponse.InnerException
                        + " " + dtor.DtoResponse.StackTrace);
                }
            }
            public DTOEnrollment GetEnrollmentById(Int32 id)
            {
                var client = new WCFServiceReference1.Service1Client();
    
                return client.GetEnrollmentById(id);
            }
            public List<DTOEnrollment> GetEnrollments()
            {
                var dtos = new List<DTOEnrollment>();
    
                var client = new WCFServiceReference1.Service1Client();
    
                dtos = client.GetEnrollments().ToList();
    
                return dtos;
            }
            public void CreateEnrollment(DTOEnrollment dto)
            {
                var client = new WCFServiceReference1.Service1Client();
                client.CreateEnrollment(dto);
            }
            public void UpdateEnrollment(DTOEnrollment dto)
            {
                var client = new WCFServiceReference1.Service1Client();
                client.UpdateEnrollment(dto);
            }
            public void DeleteEnrollment(Int32 id)
            {
                var client = new WCFServiceReference1.Service1Client();
                client.DeleteEnrollment(id);
            }
        }
    }
    



    Friday, October 6, 2017 2:51 AM
  • User-1980778524 posted

    Hi, I intend to use Asp.net Web Api 2.  I see that you use WCF. 

    here my scenario:

     Client  <--- consume Rest Api from Web Api(1) ------>  Web Api (1)     ------------------------>  Web Api(2)

                                                                                                                      -------------------------> Web Api(3)

                                                                                              api/getAllInfo

    Client Call api/getAllInfo and it will call rest Api in WebApi(2) and WebApi(3)

    webApi(1) will return result to client.

    How I solve this problem?

    Thanks

    Friday, October 6, 2017 6:46 AM
  • User1120430333 posted

    The classlib project called ServiceLayer that you make that is put into the solution is the proxy for the API1. The ServiceLayer project makes the calls to API2 and API3 on the behalf of API1. The ServiceLayer is the API client to API2 and API3 and API1 makes the call to the ServiceLayer to contact API2 or API3, just like you see in the example of API using SL to call methods on WCF.

    But the SL is a .NET WebAPI  client contacting a WebAPI service on the behalf of WebAPI1.

    https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client

    capiche

    pi

    Friday, October 6, 2017 11:05 AM
  • User475983607 posted

    I intend to use Asp.net Web Api 2.  I see that you use WCF. 

    The HttpClient API is Microsoft's answer to handling RESTful request from C# code.  Plus HttpClient implements the async await pattern.  I use HttpClient a lot and it's pretty simple to use but like anything there is a learning curve.  Read the docs and build a few examples. 

    https://msdn.microsoft.com/en-us/library/system.net.http.httpclient(v=vs.118).aspx

    https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client

    Friday, October 6, 2017 12:01 PM
  • User-1980778524 posted

    @mgebhard

    Can you advise how to handle the timeout issue from WebServer 

    Example:

    1.Client Consume Rest Api --------------> WebApi(a)

                                                                      2.  here consume --------------------------------->  3. WebApi(b)

                                                                     4.  return from(2)

                                                                         here consume -----------------------------------> 5. WebApi(c)    

    How to consume Rest api from WebApi(b) and WebApi(c) from WebApi(a)?

    Can show some sample or code?

    How to handle the timeout issue while waiting result from WebApi(b) and WbApi(c)?

    Thanks

                                                      

    Sunday, October 8, 2017 9:53 AM
  • User753101303 posted

    Hi,

    Which timeout issue? Do you mean that you try and add a timeout error message?

    If using HttpClient it could be changed using https://msdn.microsoft.com/en-us/library/system.net.http.httpclient.timeout(v=vs.118).aspx but I would investigate first exactly what happens. For example:
    - if caused by returning a huge amount of data it is common to return a "page" and allows to query for other "pages" on demand
    - if this is really a long query (video conversion or whatever), another approach is to return a jobid and to allow to check the job status and to get results using a later call

    Sunday, October 8, 2017 10:21 AM
  • User475983607 posted

    Can you advise how to handle the timeout issue from WebServer

    A timeout is an exception and exception are handled using try...catch blocks in .NET.

    How to consume Rest api from WebApi(b) and WebApi(c) from WebApi(a)?

    Can show some sample or code?

    It is a simple as making a request to WebAPI(b) and WebApi(c).  The documentation posted in my previous thread has HttpClient code examples that explains how to call a Web API service using HttpClient.  Please read the docs and try the code.  If you are having trouble, post the code and explain the issue. 

    Sunday, October 8, 2017 1:11 PM
  • User1120430333 posted

    @mgebhard

    Can you advise how to handle the timeout issue from WebServer 

    Example:

    1.Client Consume Rest Api --------------> WebApi(a)

                                                                      2.  here consume --------------------------------->  3. WebApi(b)

                                                                     4.  return from(2)

                                                                         here consume -----------------------------------> 5. WebApi(c)    

    How to consume Rest api from WebApi(b) and WebApi(c) from WebApi(a)?

    Can show some sample or code?

    How to handle the timeout issue while waiting result from WebApi(b) and WbApi(c)?

    Thanks

                                                      

    Why are you making these other calls to other API(s)? The way I see it, WebAPI is to facilitate usage of a browser and MVC solutions as the default data context is Json.  Are all these API(s) being used in thee same .NET infrastructure solution?

    Sunday, October 8, 2017 2:11 PM
  • User-1980778524 posted

    @PatriceSc

    This is what I means.  WebApi(a) in Server A , WebApi(b) and WebApi(c) are in Server B.

    So making a HttpClient  IN  WebApi(a) to webApi(b) and (c) 

    will there timeout in Server B if processing take longer ?

    Thanks

    Monday, October 9, 2017 6:33 AM
  • User-271186128 posted

    Hi SkyDriving,

    As mgebhard said, in this tutorial is explained how to consume a web api with C#, in this example a console application is used, but you can also use another web api to consume of course.

    http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client 

    Something like this should do the job:

    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri("http://localhost/yourwebapi");
    client.DefaultRequestHeaders.Accept.Add(
    new MediaTypeWithQualityHeaderValue("application/json"));
    HttpResponseMessage response = client.GetAsync("api/yourcustomobjects").Result;
    if (response.IsSuccessStatusCode)
    {
        var yourcustomobjects = response.Content.ReadAsAsync<IEnumerable<YourCustomObject>>().Result;
        
    }
    else
    {
        //Something has gone wrong, handle it here
    }

    will there timeout in Server B if processing take longer ?

    As for this issue, I suggest you could try to set the timeout property

    And, you could also use try-catch statement to catch the timeout exception:

    try
    {
       using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
       {
          WebHeaderCollection headers = response.Headers;    
          using (Stream answer = response.GetResponseStream())
          {
              // Do stuff
          }
       }
    }
    catch (WebException e)
    {
       if (e.Status == WebExceptionStatus.Timeout)
       {
          // Handle timeout exception
       }
       else throw;
    }

    Best regards,
    Dillion

    Monday, October 9, 2017 8:29 AM
  • User475983607 posted

    This is what I means.  WebApi(a) in Server A , WebApi(b) and WebApi(c) are in Server B.

    So making a HttpClient  IN  WebApi(a) to webApi(b) and (c) 

    will there timeout in Server B if processing take longer ?

    Yes, a timeout can happen in any HTTP request. 

    However, it seems you are asking a hypothetical question.  If an HTTP request to server B times out, the caller, server A,  will throw an exception.  It is up to you to catch the exception and do something like log the exception and/or send a message to the caller.  It is also up to you to determine why the request timeout and try to fix the code on server B or extend the timeout configuration.

    I suggest that you try writing the code and posting if you run into trouble.

    Monday, October 9, 2017 11:06 AM
  • User753101303 posted

    Yes, by definition a timeout happens when a request takes longer than a given threshold. Usually the default value is quite sufficient and you should always investigate why it happens before possisbly increasing the value as a very last resort.

    If you have a problem please discuss directly the current problem. Else just go ahead, make sure to log and be warn about exception and you'll deal with this problem if it happens (and it is possible that it will never happen or at least will happen very rarely).

    Monday, October 9, 2017 11:13 AM
  • User-1980778524 posted

    Hi All,

    Thank you all for the input.  I am implementing this scenario. Thus, I need to know some scenario that will happen. 

    I will try it out and get back here later.

    Thanks

    Monday, October 9, 2017 11:23 AM
  • User-1980778524 posted

    @Zhi Lv

    Thanks. Will try your approach.

    I will re visit here.

    Monday, October 9, 2017 3:35 PM