locked
Call external WebAPI from internal Web Application WebAPI RRS feed

  • Question

  • User1618902529 posted

    Hi I have a problem I'm trying to solve without enabling CORS (it's against company policy)

    Without getting into too much detail I have a WebAPI that returns a HttpResponseMessage as a PDF.

      HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
                        response.Content = new ByteArrayContent(thePDFSet[0].PdfBytes);
                        response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                        response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("INLINE");
                        return response;

    pretty straight forward...this works perfectly, however the web application that will be calling the WebAPI  and the WebAPI will live on different servers.

    I created a WebAPI inside my webApplication that calls out to the external WebAPI...It works great for everything except the example above.

    This is what I'm currently trying...

     HttpResponseMessage theResponse = new HttpResponseMessage();
    
                            String strResponse = webClient.DownloadString(theURI);
                            if (String.IsNullOrWhiteSpace(strResponse) == false)
                            {
                                Newtonsoft.Json.Linq.JObject parsedResponse = new Newtonsoft.Json.Linq.JObject();
                                theResponse = Newtonsoft.Json.JsonConvert.DeserializeObject<HttpResponseMessage>(strResponse);
                                response = theResponse;
    
                            }
                        }
                        return response;

    The Json Deserializer seems to work for other object types but is not working for HttpReponseMessage

    I guess my question is, how can I pass the HttpResponseMessage from the WebAPI on the server through the WebAPI in the application?

    Tuesday, August 11, 2015 1:06 PM

Answers

  • User1618902529 posted

    In the end this is what I ended up going with...

     HttpResponseMessage response = new HttpResponseMessage();
                using (IDisposable impersonation = A call to get priciple )
                {
    
                try
                {
    
    
                    System.Net.WebClient client = new System.Net.WebClient();
    
                    String Domain = A call to get value from web.config;
                    String theURI = String.Format("{0}/api/WebAPIController?Parm1={1}&Parm2={2}&Parm3={3}&Parm4={4}&Parm5={5}&Parm6={6}&Parm7={7}", Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8);
    
                    client.BaseAddress = theURI;
                    client.Headers.Add("X-Current-User", User.Identity.Name);
                    client.UseDefaultCredentials = true;
    
                    
    
                    byte[] pdfData = client.DownloadData(theURI);
    
                    response.Content = new ByteArrayContent(pdfData);
                    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                    response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("INLINE");
    
                    return response;
                }

    In the end this was a authentication issue between the calling server and the destination server...the error was quit hard to debug because what was returned was a 503 service unavailable error which is completely misleading...once on the server and looking through the logs there was another return code of 302 which was misleading as well saying the service had been temporarily moved...I happened to see that the credentials being passed in by "User.Identity.Name" were (Domain\Computer Name) not what I thought they would be? Once I wrapped the call in the principle it resolved the issue...the issue was complicated by the fact that the calling code for getting the principle error-ed in debug mode.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, August 13, 2015 6:48 AM

All replies

  • User1779161005 posted

    If you can't use CORS, then you'll have to write your JS to contact your own origin server and have that endpoint proxy to the real (cross-origin) endpoint.

    Tuesday, August 11, 2015 1:14 PM
  • User1618902529 posted

    Yes that's what I'm doing above...I believe

    The problem isn't with getting to the external WebAPI it's with handling the response...I can't seem to get the response back into a state (HttpResponseMessage) to then pass along again to the final destination.

    Tuesday, August 11, 2015 1:36 PM
  • User1779161005 posted

    Use a StreamContent (I think that's what the name of the response message was in Web API)

    Tuesday, August 11, 2015 2:04 PM
  • User1618902529 posted

    Ok, how do you use StreamContent? I searched for it but didn't come up with a good example.

    Tuesday, August 11, 2015 2:52 PM
  • User1779161005 posted

    You set it as the Content property on the HttpResponseMessage. I looked and you might actually want ByteArrayContent instead if you've loaded the PDF into a byte array on your server.

    Tuesday, August 11, 2015 3:05 PM
  • User1618902529 posted

    Please excuse my ignorance as I've never done this before...

    I have...

    HttpResponseMessage response = new HttpResponseMessage();
    HttpClientHandler handler = new HttpClientHandler();
                        handler.UseDefaultCredentials = true;
                        String WebAPIUrl = Some code to get the correct Domain;
                        HttpClient aClient = new HttpClient(handler);
                        aClient.BaseAddress = new Uri(WebAPIUrl);
                        String theURI = String.Format("WebAPI address and Parms");
    
                        response = aClient.GetAsync(theURI).Result;
                        StreamContent SC = (StreamContent)response.Content;

    Is this close to what I need to do?  Then do i just create a new HttpResponseMessage and set the content equal to SC?

    Tuesday, August 11, 2015 3:18 PM
  • User-782957977 posted

    Try adding  Accept type as "application/pdf" in request header and then return response

    HttpClient aClient = new HttpClient(handler);
    aClient.BaseAddress = new Uri(WebAPIUrl);
    aClient.DefaultRequestHeaders.Accept.Clear();
    aClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/pdf"));
    String theURI = String.Format("WebAPI address and Parms");
    response = aClient.GetAsync(theURI).Result;
    return response;

    Tuesday, August 11, 2015 9:01 PM
  • User1618902529 posted

    In the end this is what I ended up going with...

     HttpResponseMessage response = new HttpResponseMessage();
                using (IDisposable impersonation = A call to get priciple )
                {
    
                try
                {
    
    
                    System.Net.WebClient client = new System.Net.WebClient();
    
                    String Domain = A call to get value from web.config;
                    String theURI = String.Format("{0}/api/WebAPIController?Parm1={1}&Parm2={2}&Parm3={3}&Parm4={4}&Parm5={5}&Parm6={6}&Parm7={7}", Value1, Value2, Value3, Value4, Value5, Value6, Value7, Value8);
    
                    client.BaseAddress = theURI;
                    client.Headers.Add("X-Current-User", User.Identity.Name);
                    client.UseDefaultCredentials = true;
    
                    
    
                    byte[] pdfData = client.DownloadData(theURI);
    
                    response.Content = new ByteArrayContent(pdfData);
                    response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                    response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("INLINE");
    
                    return response;
                }

    In the end this was a authentication issue between the calling server and the destination server...the error was quit hard to debug because what was returned was a 503 service unavailable error which is completely misleading...once on the server and looking through the logs there was another return code of 302 which was misleading as well saying the service had been temporarily moved...I happened to see that the credentials being passed in by "User.Identity.Name" were (Domain\Computer Name) not what I thought they would be? Once I wrapped the call in the principle it resolved the issue...the issue was complicated by the fact that the calling code for getting the principle error-ed in debug mode.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, August 13, 2015 6:48 AM