Unable to call API's from ASP.NET MVC App? - asp.net

I've created a API where I want to call another API from, for testing im using Pokemon API with PostMan. However when I want to call this API im my own API application getting an error. Code executed when API is getting called:
[System.Web.Http.AcceptVerbs("GET")]
[System.Web.Http.HttpGet]
[System.Web.Http.Route("RedirectApi")]
public async Task<object> getCall()
{
checkAuthorisation();
setVariables();
if (isAuthorized == true)
{
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync("https://pokeapi.co/api/v2/pokemon/ditto/");
var code = response.StatusCode;
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject(responseBody);
}
else
{
return JsonConvert.DeserializeObject("Unauthorized");
}
}
Im calling my API with this link:
http://localhost:54857/GetPokemon
Whenever I execute this using Postman in debug mode it executes but fails on this code:
HttpResponseMessage response = await client.GetAsync("https:/pokeapi.co/api/v2/pokemon/ditto/");
It also does not give me any feedback except what Postman gives me back:
Hope someone can help!
Thanks in advance!

Related

exception was thrown by the target of invocation” C# Httpclient

I have two API created in .net core 3.1 (let us say API A & API B) API A will call API B and merging two outputs. But when call,
I am getting:
Error:: Exception has been thrown by the target of an invocation.: Error Executing C# Script
The two APIs are running on different ports API A and API B.
I need to get the result from API A  to API B.so In my API A is a combination of API A and API B. I am using the same request for both.
The problem is when I call an external API call to API B from API B. But it works when I run API B only. I don't understand the issue
Code of the API B:
public async Task GetKeyData(string key){
string dataKey = string.Empty;
var requestUri = string.Format("{0}/{1}", _KeyUri, key);
HttpClient client = new HttpClient(new HttpClientHandler() {
UseDefaultCredentials = true
});
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var rawData = await client.GetAsync(requestUri);
// below line are getting error when i call from api A to this
var jsonResponse = await rawData.Content.ReadAsStringAsync(); //error showing here
string value = JsonConvert.DeserializeObject(jsonResponse);
//balance code
}
}
What mistake I am doing here?

How do I make a http request from an asp.net middleware?

I have a middleware which needs to call off to an external service to check for some state and then act on it. I'm wondering how I go about making a request from middleware?
I've seen some docs about having a HttpClientFactory service, but I'm not really sure how I make that available to my middleware?
You can use the default HttpClient
This allows you to create a client in your middleware and send any request you need.
Example:
using(var client = new HttpClient()){
try
{
HttpResponseMessage response = await client.GetAsync("http://www.contoso.com/");
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
// Above three lines can be replaced with new helper method below
// string responseBody = await client.GetStringAsync(uri);
Console.WriteLine(responseBody);
}
catch(HttpRequestException e)
{
Console.WriteLine("\nException Caught!");
Console.WriteLine("Message :{0} ",e.Message);
}
}

API request for LinkedIn user data always returns 401

I am building back-end(API) of mobile application on asp.net core. Using swagger for visualization of API calls and so on. Currently I am creating external authentications, I have some problems with LinkedIn.
The structure of application is simple, mobile side gets LinkedIn user's Access Token and sends it to me with API request, I have to request user data from LinkedIn by received Access Token, register or login him/her and return response to mobile side.
There is the code below, and commented links where I tried to send requests.
public async Task<IResponse<LinkedInAuthenticationResponse>> LinkedInAuthentication(string accessToken)
{
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
httpClient.DefaultRequestHeaders.Add("x-li-format", "json");
var oauthUrl = "https://api.linkedin.com/v1/people";
// https://api.linkedin.com/v2/me
// https://api.linkedin.com/v1/people/~:(id,formatted-name,email-address,picture-url)
var response = httpClient.GetAsync(oauthUrl).Result;
string responseContent = string.Empty;
try
{
responseContent = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
return Ok(JsonConvert.DeserializeObject<GoogleAuthenticationResponse>(responseContent));
}
catch (Exception ex)
{
}
}
}
The problem is that LinkedIn doesn't provide exact link where API call should be send, I had to try several of them but the response is always 401.
My Access Token is valid, this can not be problem. I have used almost same code for Facebook and Google and they work perfectly.
Any one can provide link which works for API calls ?
This issue has nothing to do with the asp.net framework but with the endpoint, you are using. Since v1 of the LinkedIn API has been deprecated, you need to change your endpoint as for this link here

dotnet core webapi calling .net webapi2

I am calling a .NET WebApi2 endpoint from a dotnet core webapi. When I debug into the .NET WebApi2 POST endpoint, my value is always null. Is this not possible to do?
When I call the GET endpoint with an ID, the ID is passed with no issues.
I have used both Postman and Fiddler to debug. Whenever I pass my JSON object from Postman to the .NET WebApi2 POST endpoint, my value is populated.
Beyond frustrated as this seems pretty simple. :,(
Updated to include code
dotnet core web api (calling from Postman)
[HttpPost]
public async Task PostAsync([FromBody] string value)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var jsonObject = new JObject();
jsonObject.Add("text", "Rich");
var response = await client.PostAsJsonAsync("http://localhost:54732/api/Rich", jsonObject);
var responseResult = response.Content.ReadAsStringAsync().Result;
}
.NET WebApi2 (JObject is always null)
// POST: api/Rich
public void Post(JObject value)
{
}
This boils down to using JObject basically. For your older Web Api action, JObject works merely because you're posting JSON, and JObject is a dynamic. However, that is an entirely incorrect approach. You should be binding to a concrete class that represents the JSON being posted. That said, you may or may not be able to change anything there, and its not technically the source of your current issue.
The actual source is that you're attempting to send a JObject, which is not doing what you think it is. Again, JObject is a dynamic. It has accessors to parse and access the underlying JSON, but it does not actually expose the members of that JSON object directly. As a result, if you attempt to serialize it, you won't get anything usable from it. Passing it to PostAsJsonAsync causes it to be serialized.
What you actually need is something like:
var jsonObject = new { text = "Rich" };
Then, what you're passing to PostAsJsonAsync will be an anonymous object with actual members that can be serialized.
My "REAL" issue turned out to be Transfer-Encoding: chunked was being sent in the request header.
Here is my corrected code (dotnet core web api):
public async Task PostAsync([FromBody] JObject value)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
var jsonObject = new { variable1 = "Rich" };
var json = JsonConvert.SerializeObject(jsonObject);
var content = new StringContent(json, Encoding.UTF8, "application/json");
content.Headers.ContentLength = json.Length;
var response = await client.PostAsync("http://localhost:54732/api/Rich", content);
var responseResult = response.Content.ReadAsStringAsync().Result;
}
Here is my .NET WebApi2 code:
public IHttpActionResult Post([FromBody]RichTest value)
{
return Ok(value.variable1 + " done");
}
public class RichTest
{
public string variable1 { get; set; }
}
When I set the content.Headers.ContentLength, the Transfer-Encoding: chunked is removed. Now my code is working!!
I am still curious why the original PostAsJsonAsync does not work...

Web API External Bearer Unauthorized

I am trying to call the RegisterExternal method in Web API, after having retrieved a token from facebook. But I keep getting a 401 Unauthorized from my Web API. I am not sure I am correctly implementing the logic flow. My code is;
Ask for supported external login providers;
public async Task<List<ExternalLoginViewModel>> GetExternalLoginsAsync()
{
using (var client = GetNewHttpClient(false))
{
var response = await client.GetAsync("api/account/externalLogins?returnUrl=/&generateState=true");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsAsync<List<ExternalLoginViewModel>>();
}
}
From this, I am returned a facebook URL. I follow this and then enter in my facebook username and password. I return back to my app via a deep link and then try and call the RegisterExternal method in the web API like this, passing the facebook "access token" that is returned.
public async Task<bool> SendSubmitRegisterExternalAsync(RegisterExternalBindingModel ro, string accessToken)
{
using (var client = GetNewHttpClient(true))
{
client.DefaultRequestHeaders.Add("Authorization", String.Format("Bearer {0}", accessToken));
HttpResponseMessage response = await client.PostAsJsonAsync("api/Account/RegisterExternal", ro);
if (response.IsSuccessStatusCode) return true;
var value = await response.Content.ReadAsStringAsync();
throw new ResponseErrorException(ErrorHelper.GetErrorString(value));
}
}
I receive 'Unauthorized' every time. I do not know what is wrong. My Web API method looks like this, and the class is marked with the [Authorize] attribute.
[OverrideAuthentication]
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("RegisterExternal")]
public async Task<IHttpActionResult> RegisterExternal(RegisterExternalBindingModel model)
{
...
I have found three different posts this evening of people asking this exact same question, and in all cases there are no replies, so I am not hopeful but if anyone can shed some light on this it would be great!
EDIT: I have also changed the method signature to 'allowanonymous' and still get unauthorized!
[OverrideAuthentication]
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[AllowAnonymous]
[Route("RegisterExternal")]
public async Task<IHttpActionResult> RegisterExternal(RegisterExternalBindingModel model)
{
I have sorted this by not using FacebookSessionClient and doing it via a WebBrowser control instead.
I use the URL from the first step (provided to me by the WebAPI). Then on the Navigated event from the WebBrowser control, i parse the Url for the access token;
public async void ParseUrlForAccessToken(string url)
{
string fieldName = "access_token";
int accessTokenIndex = url.IndexOf(fieldName, StringComparison.Ordinal);
if (accessTokenIndex > -1)
{
int ampersandTokenIndex = url.IndexOf("&", accessTokenIndex, StringComparison.Ordinal);
string tokenField = url.Substring(accessTokenIndex, ampersandTokenIndex - accessTokenIndex);
string token = tokenField.Substring(fieldName.Length);
token = token.Remove(0, 1);
await _dataService.SubmitLoginExternal("Test", token);
}
}
Then as shown above, I call SubmitLoginExternal, which is a call to the following code which uses the access token retrieved from the WebBrowser control Url to register the account (in this case a 'Test' account);
using (var client = GetNewHttpClient(true))
{
client.DefaultRequestHeaders.Add("Authorization", String.Format("Bearer {0}", accessToken));
HttpResponseMessage response = await client.PostAsJsonAsync("api/Account/RegisterExternal", ro);
if (response.IsSuccessStatusCode) return true;
var value = await response.Content.ReadAsStringAsync();
throw new ResponseErrorException(ErrorHelper.GetErrorString(value));
}
This has worked and now I have the user registered in my database.
The key was to use a WebBrowser control and not the FacebookSessionClient object or a WebBrowserTask. You cannot use a WebBrowserTask as you need to hook in to the navigated event once the page has loaded to call ParseUrlForAccessToken().

Resources