handling xml responses from httpclient in javascript policy - apigee

I have a backend SOAP webservice which has two methods - getCustomerByPhoneNumber and getOrderByCustomerId. I have a requirement to build a apigee json endpoint to fetch the latest order of a customer which should take phone number as input.
This means, I will have to create an API endpoint and a resource pointing to the SOAP method getOrderByCustomerId. Build an internal callout proxy (preferably javascript policy and use httpClient proxy object) to call SOAP method getCustomerByPhoneNumber to get the customer id and pass on the customerId to the endpoint method getOrderByCustomerId.
My concern is - how to handle the SOAP response from the method getCustomerByPhoneNumber!? if its JSON, its very easy to write logic to read the values from javascript code.
How can I easily parse xml/soap response in javascript or convert xml to JSON in javascript to read the response like an object?
Or, as another alternative, should I convert all my SOAP method to REST methods and the wrapper cumulative method should call converted REST method (in the callout proxy) instead of calling the SOAP method directly..
Any insights?

Apigee uses E4X which adds support for XML (see: http://apigee.com/docs/api-services/content/javascript-object-model). An example below demonstrates how you can work with a SOAP response. This is something I quickly put together using an example soap message from w3schools.
Example SOAP response message:
<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
<soap:Body xmlns:m="http://www.example.org/stock">
<m:m:GetStockPriceResponse>
<m:Price>34.5</m:Price>
</m:m:GetStockPriceResponse>
</soap:Body>
</soap:Envelope>
Example javascript in Apigee:
var mockResponse ='<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"><soap:Body xmlns:m="http://www.example.org/stock"><m:GetStockPriceResponse><m:Price>34.5</m:Price></m:GetStockPriceResponse></soap:Body></soap:Envelope>';
var soap = new Namespace('http://www.w3.org/2001/12/soap-envelope');
var m = new Namespace('http://www.example.org/stock');
var xmlObj = new XML (mockResponse);
var stockPrice = xmlObj.soap::Body.m::GetStockPriceResponse.m::Price;
response.content.status = 200;
response.content.status.message = 'OK';
response.headers['content-type'] = 'text/plain';
response.content = 'stockPrice: ' + stockPrice;
Leaves you with a response like:
HTTP/1.1 200 OK
content-type: text/plain
Content-Length: 16
stockPrice: 34.5

Related

Get the raw request that is sent with HttpClient and HttpRequestMessage

In my C# code running .NET 6 (Azure Function) I am sending an HttpRequestMessage using HttpClient. It doesn't work but it should work, so I want to get the raw request that I am sending, including the header, so I can compare with the documentation and see the differences.
In the past I have used Fiddler but it doesn't work for me now, probably because of some security settings on my laptop. So I am looking for a solution within the world of Visual Studio 2022 or .NET 6 where I can get the raw request out for troubleshooting purposes.
This question is not really about code, but here is my code anyway.
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://myendpoint.com/rest/something");
var apiToken = "AOU9FrasdgasdfagtHJNV";
request.Headers.Add("Authorization", "Basic " + apiToken);
var message = new
{
sender = "Hey",
message = "Hello world",
recipients = new[] { new { id = 12345678} }
};
request.Content = new StringContent(JsonSerializer.Serialize(message), Encoding.UTF8, "application/json");
request.Headers.Add("Accept", "application/json, text/javascript");
HttpResponseMessage response = await httpClient.SendAsync(request);
When SendAsync is invoked, I wish to know what exactly is sent, both header and content.
If you cannot use any proxy solution (like Fiddler) then I can see 2 options. One is described in comments in your question to use DelegatingHandler. You can read more about this in documentation. What is interesting is that HttpClient supports logging out of the box which is described in this section https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-6.0#logging of the article which describes DelegatingHandlers
If you are worried that something will manipulate the outgoing request then you can implement option 2. This is to create temporary asp.net core application with .UseHttpLogging() middleware plugged in into pipeline as described here https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-logging/?view=aspnetcore-6.0 That way you will know exactly how your request looks like from application which is being requested point of view. Now if you will point your azure function to you temporary app - you should see what gets send
Hope it helps

.net core 3.0/3.1 write custom response to http request

I'm writing an Api gateway and implementing the custom aggregators that we need. To do this I am taking the any incoming http request via the middleware, interrogating the request to see if this is one I need to handle and, if so, making multiple downstream calls to different apis to get the fragments I need to re-assemble back together to make the response. If it's not one I want to handle, I just forward it to the downstream system (e.g. like a reverse proxy), so I'm not implementing web api controllers just middleware interception.
In .net core 2.x I'd use something like originalIncomingRequest.CreateResponse to create my custom response after all the aggregated calls have finished and then write to the response body my stitched together json response.
This extension method doesn't appear to exist in .net core 3.x
it looks like I'm stuck with this (e.g.)
var json = JsonConvert.SerializeObject(aggregation);
var b = Encoding.UTF8.GetBytes(json);
originalIncomingRequest.HttpContext.Response.StatusCode = 200;
await request.HttpContext.Response.Body.WriteAsync(b, 0, b.Length);
but this is a pattern from a very long time ago.... is there something simpler in .net core 3.x to achieve this goal?
If you want to use this code as a middleware you should try some code like this:
app.Use(async (context, next) =>
{
var json = JsonConvert.SerializeObject(<aggregation>);
var b = Encoding.UTF8.GetBytes(json);
context.Response.StatusCode = 200;
await context.Response.Body.WriteAsync(b, 0, b.Length);
});

Xamarin Form not able to invoke the Http URL

I am new to Xamarin Cross-Flatform technology (C#). I am developing one small application where I need to call the http url, get the json data, parse it and display it on the screen.
I am using System.Net.Http for achieving the http call.But request is not reaching to http url
Regards,
Amit Joshi
You can use RestSharp for making http calls.
It is very easy to use.
Code sample:
using RestSharp;
var client = new RestClient ("http://rxnav.nlm.nih.gov/REST/RxTerms/rxcui/");
var request = new RestRequest (String.Format ("{0}/allinfo", "198440"));
client.ExecuteAsync (request, response => {
Console.WriteLine (response.Content);
});
RestSharp Examples

Return data in xml or json format in asp.net 5 web api 2 according to request header

I am developing web api using asp.net web api 2, MVC 6 and asp.net 5 i.e. dnxcore50 (core clr).
My requirement is to return data in in xml or json format as required in request header. If header has Accept type set to application/xml or application/xhtml+xml my api endpoint should return requested data in xml format. Also same for json format as well if header has Accept type set to application/json, my api endpoint should return data in json format.
I have tried using following code in startup but with no success.
In ConfigureServices() method I have following code:
services.AddMvc().AddXmlDataContractSerializerFormatters();
services.Configure<MvcOptions>(options => {
options.RespectBrowserAcceptHeader = true;
options.InputFormatters.Add( new XmlSerializerInputFormatter());
options.OutputFormatters.Add( new XmlSerializerOutputFormatter());
});
Can anyone guide me what am I missing here or what is wrongly configured.

BufferedMediaTypeFormatter HttpContent does not contain all Headers sent in Request

Within my Owin Self hosted Web Api project I am trying to build a custom MediaTypeFormatter that inherits from BufferedMediaTypeFormatter.
But the problem is the HttpContent object passed into ReadFromStream(..) does not contain all the headers sent in the request.
How do you access ALL the headers that were sent in the request (I know this because I made the request), or access the original HttpRequestMessage in the ReadFromStream(..) method ?
This seams to be a major bug and I cannot think of any reason why all the Request headers are not provided.
Sounds like the ASP.NET Request object does not expose a property for the specific header field name you are looking for.
So it looks like first, you need the Request and to do that you might be able to override GetPerRequestFormatterInstance:
How do I retrieve the HTTP request method in an ASP.NET WebAPI MediaTypeFormatter?
Once you have the request object you can search for the specific header field name you are looking for like so:
IEnumerable<string> headerValues = request.Headers.GetValues("MyHeaderFieldName");
var id = headerValues.FirstOrDefault();
You can also get the raw request if needed:
Request.InputStream.Position = 0;
var input = new StreamReader(Request.InputStream).ReadToEnd();

Resources