I have an api call and in this calling another api. My requirement to store all api calls request body i.e., for any issues we can check application insights data with api URL information and parameters.
Using the code shown here, I was able to get first api request body but unable to read external api request body.
Please let me know the best way to achieve the task
Thanks in advance
private async Task LogRequest(HttpContext context, string correlationID)
{
context.Request.EnableBuffering();
aiLogger.LogPageView(context.Request.Path.Value);
using (var requestStream = _recyclableMemoryStreamManager.GetStream())
{
await context.Request.Body.CopyToAsync(requestStream);
string requestBody = ReadStreamInChunks(requestStream);
}
}
Related
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);
});
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
We are trying to set up Identity Server 3 in the right way.
We got authentication working fine and we manage to retrieve the refresh token.
The client application is using Angular.
Now when the acces_token expires any calls to the rest api fails (we managed to get it to return 401) but we are wondering how to re-authenticate the user.
In our tests, any api call made from Javascript is failing (401) but as soon as the page is refreshed the whole mechanism is kicking in. We do see that we are redirected to the identity server but it does not show up the login page, we are sent back to the client application with new tokens apparently.
What I would like to do is to refresh the access token without having to force the user to refresh the page.
What I'm not sure though is whose responsibility is it? Is that the client application (website) or the angular application? In other word, should the application handle this transparently for Angular or should angular do something when it receives a 401, in which case, I'm not too sure how the information will flow back to the web app.
Any clue?
Additional Information: We are using OpenId Connect
I got it working!
As I said in the comments I used this article. The writer is referencing a very nice lib that I am using as well.
Facts:
Identity Server 3 is requesting the client secret upon access token refresh
One should not store the refresh_token or the client_secret on the javascript application as they are considered unsafe (see the article)
So I chose to send the refresh_token as en encrypted cookie sith this class (found of ST BTW, just can't find the link anymore, sorry...)
public static class StringEncryptor
{
public static string Encrypt(string plaintextValue)
{
var plaintextBytes = plaintextValue.Select(c => (byte) c).ToArray();
var encryptedBytes = MachineKey.Protect(plaintextBytes);
return Convert.ToBase64String(encryptedBytes);
}
public static string Decrypt(string encryptedValue)
{
try
{
var encryptedBytes = Convert.FromBase64String(encryptedValue);
var decryptedBytes = MachineKey.Unprotect(encryptedBytes);
return new string(decryptedBytes.Select(b => (char)b).ToArray());
}
catch
{
return null;
}
}
}
The javascript application is getting the value from the cookie. It then deletes the cookie to avoid that thing to be sent over and over again, it is pointless.
When the access_token becomes invalid, I send an http request to the application server with the encrypted refresh_token. That is an anonymous call.
The server contacts the identity server and gets a new access_token that is sent back to Javascript. The awesome library queued all other requests so when I'm back with my new token, I can tell it to continue with authService.loginConfirmed();.
The refresh is actually pretty easy as all you have to do is to use the TokenClient from IdentityServer3. Full method code:
[HttpPost]
[AllowAnonymous]
public async Task<JsonResult> RefreshToken(string refreshToken)
{
var tokenClient = new TokenClient(IdentityServerConstants.IdentityServerUrl + "/connect/token", "my-application-id", "my-application-secret");
var response = await tokenClient.RequestRefreshTokenAsync(StringEncryptor.Decrypt(refreshToken));
return Json(new {response.AccessToken});
}
Comments are welcome, this is probably the best way to do that.
For future reference - using refresh tokens in an angular (or other JS) application is not the correct way as a refresh token is too sensitive to store in the browser. You should use silent renew based on the identityserver cookie to get a new access token. Also see the oidc-client-js javascript library, as this can manage silent renew for you.
Is there something special I need to define in an ASP.NET MVC application to read an incoming response from a ASP.NET Web API?
From my MVC app, I make a request to an ASP.NET Web API using System.Net.HttpClient. The API receives the request and processes it fine and returns a valid response. However, the MVC application, it appears, never gets the response. I have a break point on the line that makes the request. The flow of control never comes back after executing that line. The MVC app just keeps waiting and times-out after a very long time.
However, I can confirm that the API returns a valid Json response. I have tried composing this request in Chrome Postman and see that the API returns a valid response.
Here's the code from my MVC app that makes the request to the Web API:
public async Task<R> PostAsJsonAsync<T, R>(string uri, T value)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(_baseUri);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.PostAsJsonAsync(uri, value);
if (response.IsSuccessStatusCode) return await response.Content.ReadAsAsync<R>();
else return default(R);
}
}
In the past, i.e. before Web API 2, I've had MVC apps talk to the Web API without any problem. I don't know if I am missing something that has been introduced in Web API 2.
I have a feeling you are getting a deadlock. Are you using .Result anywhere? You should be using async all the way. I mean your MVC action method should also be async method and they should await and not use .Result. Read this log post by Stephen Cleary for more info. http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
Is there a good way to debug code from a console app to a web api project in VS2013? For example if I had some code such as:
Web API Controller
// GET api/values
public IEnumerable<string> Get()
{
return string [] { "value1, value2" };
}
Console Application
var client = new HttpClient();
var results = client.GetStringAsync("http://localhost:35690/api/values").Result;
I know I can use a browser or a tool like CURL. However, where this gets more complicated is handling a multipart form post for a file upload scenario I'd like to support.
If the WebAPI service is part of the same solution as the console application, you can simply set breakpoints wherever you wish and they are respected.