C# get a http response from another class method - c#

Previously i handled all my http requests in a single class but i would like to move the http login functionality to a different class but now i cant access the http client response.IsSuccessStatusCode
this is my original code whic works
var http = new HttpClient();
var url = String.Format(shared.AppDetails.domainurl+"/v2auth/default/login");
var response2 = await http.PostAsync(url, credentials);
if (response.IsSuccessStatusCode)
{
//do after login stuff
}
Now i would like to move the login logic to a different class that is in a different folder(auth->dbhelpers)
class LoginHttp
{
public static async Task<object> loginAsync(String username, String password)
{
var values = new Dictionary<string, string>
{
{ "username",username },
{ "password", password }
};
var credentials = new FormUrlEncodedContent(values);
var http = new HttpClient();
var url = String.Format(shared.AppDetails.domainurl + "/v2auth/default/login");
var response = await http.PostAsync(url, credentials);
return response;
}
}
So am now trying to access the returned response via
var responsefromhttplogin = auth.dbhelpers.AuthHttp.loginAsync(login_username.Text, login_password.Password);
if (responsefromhttplogin .IsSuccessStatusCode) //this fails
{
//do after login stuff
}
How can i get the retrned response be of type HttpClient again?
Am getting an error of
Task<Objct> does not contain defination for IsSuccessStatusCode

Make your loginAsync method return Task instead. Currently you are returning an object, then you will have access to the IsSuccessStatusCode
class LoginHttp{
public static async Task<HttpResponseMessage> loginAsync(String username, String password)
{
var values = new Dictionary<string, string>
{
{ "username",username },
{ "password", password }
};
var credentials = new FormUrlEncodedContent(values);
var http = new HttpClient();
var url = String.Format(shared.AppDetails.domainurl + "/v2auth/default/login");
var response = await http.PostAsync(url, credentials);
return response;
}
}
You also need to use await in your calling method, otherwise you get a Task back
var responsefromhttplogin = await auth.dbhelpers.AuthHttp.loginAsync(login_username.Text, login_password.Password);
if (responsefromhttplogin.IsSuccessStatusCode)
{
//do after login stuff
}

Try to change your code to await async method like this:
var responsefromhttplogin = await auth.dbhelpers.AuthHttp.loginAsync(login_username.Text, login_password.Password);
if (responsefromhttplogin.IsSuccessStatusCode)
{
//do after login stuff
}
Now after you add await this responsefromhttplogin.IsSuccessStatusCode should be accessible.
And also change your method to return Task<HttpResponseMessage> instead of Task<object>

You are returning Task<object> from loginAsync(), to access the result of the task you can use Task.Result.
I would consider to narrow down the type that you are returning from object to HttpResponseMessage.

Judging from your code, you are returning a Task<object>
You should either cast the return response; as return (HttpResponseMessage) response;
Or change the return type to be Task<HttpResponseMessage>
Relevant documentation

Related

how to obtain token info at response when calling post method api client adding parameters

With this I just can obtain 200 status code and reason Phrase is OK
public HttpResponseMessage Authenticate(string userName,string password)
{
var jsonString = JsonConvert.SerializeObject(new {userName=userName,password=password});
var parameters = new RestApiClientMethodParameter
{
AdditionalUri = "authenticate" , Body = jsonString
};
var result = _restApiClient.Post(parameters);
return result;
}
This is Post method of _restApiClient :
public HttpResponseMessage Post(RestApiClientMethodParameter parameter)
{
try
{
var httpContent = new StringContent(parameter.Body, Encoding.UTF8, "application/json");
return _client.PostAsync(parameter.AdditionalUri, httpContent).GetAwaiter().GetResult();
}
catch (Exception e)
{
Console.WriteLine(e);
}
return null;
}
And my requestUri is also true when im debugging, any ideas?
Thanks
I tried to change method return type as my model, i expect to return a bearer token from that uri so i can say that im authenticated to that system
Hope my understanding about your question is right.
If you are just want to change the return type to a string which is a token, you can use ReadAsStringAsync()
// 📌 Change method's return type
public async Task<string> Authenticate(string userName,string password)
{
var jsonString = JsonConvert.SerializeObject(new {userName=userName,password=password});
var parameters = new RestApiClientMethodParameter
{
AdditionalUri = "authenticate" , Body = jsonString
};
var result = _restApiClient.Post(parameters);
// 📌 Use ReadAsStringAsync()
return await result.Content.ReadAsStringAsync();
}
Get result by Result property
string token = Authenticate("userName", "password").Result;

C# stops working when performing async post request

I am working on a mobile app, and the problem is that when I perform a async request ( PostAsync ) using Net.Http my program stops running.
Here is my request class, where I perform the requests using Net.Http.
...
namespace BSoft.Requests
{
public class Requests
{
public Requests(){}
public static string HostName = "https://dev5.360businesssoft.com/";
private static readonly HttpClient httpClient = new HttpClient();
public static async Task<string> PerformPostRequest(Dictionary<string, string> values, string path)
{
string url = HostName + path;
FormUrlEncodedContent content = new FormUrlEncodedContent(values);
HttpResponseMessage response = await httpClient.PostAsync(url, content);
string responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
}
}
and here is my login class, where I call call the request and display the result as string.
...
namespace BSoft.Login
{
public class Login
{
public Login()
{
}
public static void PerformLogin(string username, string password, bool remember)
{
var values = new Dictionary<string, string>();
values.Add("User", username);
values.Add("Password", password);
var ReturnedObj = Requests.Requests.PerformPostRequest(values, "test.php").Result;
System.Diagnostics.Debug.WriteLine(ReturnedObj);
}
}
}
This is a screenshot of the app, you can notice that the button is freezed
The call to Result is blocking the gui thread. Instead, await the result:
var ReturnedObj = await Requests.Requests.PerformPostRequest(values, "test.php");
System.Diagnostics.Debug.WriteLine(ReturnedObj);
Your call to Result will block the gui thread until PerformPostRequest completes, so there's not really a lot of point using the async features here. If you really don't want the code to execute asynchronously then you might as well remove the calls to the async methods and make the calls synchronous.
Try
string returnedString = await Requests.Requests.PerformPostRequest(values, "test.php");

HttpClient Async Method return value

I studied over the Internet regarding Task Async method but cannot seem to find an approach to assign my return value in Task Async to another object. The first method is to prepare HTTP Request header and Uri.
public static async Task MainAsync()
{
string token = await AuthHelper.AcquireToken(tenantId, clientId, clientSecret);
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
client.BaseAddress = new Uri("https://foo.net");
await GetValue(client);
}
}
The second method is to use GetAsync to call to an API to get the JSON and the two last lines I extract only value from the "Value" field in the JSON body.
public static async Task<String> GetValue(HttpClient client)
{
string url = $"/mykey/key01";
using (var httpResponse = await client.GetAsync(url))
{
httpResponse.EnsureSuccessStatusCode();
string responsContent = await httpResponse.Content.ReadAsStringAsync();
JObject json = JObject.Parse(responsContent);
string value = json["value"].ToString();
return value;
}
}
Now I would like to use this value to assign to another object, but not sure how to do so. I managed to return the valid value. Is it possible to retrieve the value from another method or even different class?
[Updated] The main function is:
static void Main(string[] args)
{
try
{
MainAsync().Wait();
}
catch (Exception e)
{
Console.WriteLine(e.GetBaseException().Message);
}
}
Update
To be more clear. The HTTP response message is a JSON format and I can return the value from Value property in this JSON. Now how I can to reuse the value from an external method or class
I'm not sure exactly what you are trying to achieve. And there would be thorough debates about your architecture, you can do something like this..
Update
Because your MainAsync is static it can be called form anywhere.
You just need to modify it a bit to return your result as follows :
public static async Task<string> MainAsync()
{
...
return await GetValue(client);
...
And somewhere else
public class MyAwesomeClass
{
public async Task DoMagic()
{
var newValueOfSomething = await MainAsync();
// hilarity ensues
}
}
You can Make it more generic and useful, something like below :
Your initial method can be changes to :
public async Task<T> GetContentAsync<T>(HttpClient client)
{
string url = $"/mykey/key01";
using (var httpResponse = await client.GetAsync(url))
{
httpResponse.EnsureSuccessStatusCode();
string responsContent = await httpResponse.Content.ReadAsStringAsync();
return Deserialize<T>(json);
}
}
private T Deserialize<T>(string json)
{
return JsonConvert.DeserializeObject<T>(json, SerializationSettings);
}
You can now call method like :
var person = await GetContentAsync<Person>(/*http client*/)

How to Return HTTP Status Codes from Azure Queue's in C# ASP.NET Web API 2

I have a web api (written in c# on ASP.NET Web API 2). One of the methods takes a HTTP POST and adds it to an Azure Queue.
I'd like to know how I can get hold of a http status code (or whatever is available) from the Azure Queue so that I can return an appropriate http status code from my method.
The code so far is similar to this:
[Route("api/v1/somewhere/")]
[ResponseType(typeof(Thingy))]
public async Task<IHttpActionResult> Post(Thingy thingy)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["AzureWebJobsStorage"].ToString());
var queueClient = storageAccount.CreateCloudQueueClient();
var queue = queueClient.GetQueueReference("thingys");
var msg = new CloudQueueMessage(JsonConvert.SerializeObject(thingy));
await queue.AddMessageAsync(msg);
return Json(thingy);
}
I'd like to swap out the return Json(thingy); line and return a http status code 202 if all goes well with the await queue.AddMessageAsync(msg); and another appropriate code if something goes wrong.
Any ideas?
You should make use of LastResult property of OperationContext object. It has a HttpStatusCode property which will return the status code from Storage Service. Here's an example of the same:
static void QueueTest1()
{
var account = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
var queueClient = account.CreateCloudQueueClient();
var queue = queueClient.GetQueueReference("my-queue");
queue.CreateIfNotExists();
var messageContents = "This is a test message";
var opContext = new OperationContext();
var msg = new CloudQueueMessage(messageContents);
queue.AddMessage(msg, null, null, null, opContext);
var statusCode = opContext.LastResult.HttpStatusCode;
Console.WriteLine("Status Code = " + statusCode);//Prints 201 as status code
queue.DeleteIfExists();
}
Check out this page:
http://bitoftech.net/2014/03/05/new-asp-net-web-api-2-ihttpactionresult-cors-tutorial/
I think you should wrapp the response you want in your own class, something like that:
public class MyResponse : IHttpActionResult
{
public string Message { get; private set; }
public HttpRequestMessage Request { get; private set; }
public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
{
return Task.FromResult(ExecuteResult());
}
public HttpResponseMessage ExecuteResult()
{
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Accepted);
response.Content = new StringContent(Message);
response.RequestMessage = Request;
return response;
}
}

HttpResponseMessage from HttpClient to User Defined Object C#

I have seen similar questions asked but none that seem to help me with my issue so please bear with me.
I have a WebAPI controller method that is defined as such:
[HttpPost]
[Route("")]
public HttpResponseMessage CreateMyObject(MyObjectRequest myObject)
{
MyObject o;
try
{
o = _serviceFactory.GetInstance().CreateMyObject(myObject);
}
catch (Exception ex)
{
ex.WriteToLog();
throw ApiHelper.CreateResponseException(HttpStatusCode.InternalServerError, ex);
}
var response = Request.CreateResponse(HttpStatusCode.Created, o);
var uri = Url.Link("GetMyObjectById", new { myObjectId = o.MyObjectId.ToString() });
response.Headers.Location = new Uri(uri);
return response;
}
Say, MyObject contains two properties,
public MyObject
{
public Guid MyObjectId;
public string MyObjectName
}
A client was written to call these controller methods in a WPF application. Here is the client method that is being used:
public HttpResponseMessage CreateQuote(MyObjectRequest myObject)
{
var hashtable = new Hashtable
{
{"myObject", myObject}
};
var task = GetResponse("", hashtable);
var response = task.Result;
return response;
}
protected async Task<HttpResponseMessage> GetResponse(string path, Hashtable parameters)
{
var response = await GetAsync(BuildRequestUri(path, parameters)).ConfigureAwait(false);
return response.IsSuccessStatusCode ? response : new HttpResponseMessage();
}
protected async Task<HttpResponseMessage> GetResponse(string path)
{
return await GetResponse(path, null);
}
The controller and supporting client code was not written by me and was already in the system. I am just consuming this in the WPF application. Now, I am trying to call the controller method via the client in the application and get the MyObject from the response so that I can access the MyObjectId that has been created and set. I have tried some of the other responses to similar questions but have not even seen some of the methods that are called on the response in order to get the information. Here is the first part of the call to the client that I have in the application:
var httpResponse = ApplicationService.CreateMyObject(myObjectRequest);
The application service simply injects the client into the constructor and allows me to call the CreateMyObject method. Is there any insight that can be given to me on how I should be getting the MyObject object out of the response?
I'm still a little new to web api as well, but I'm currently working with it on a project. Give the following code a try:
MyObject myObject;
if (response.IsSuccessStatusCode)
{
// Parse the response body. Blocking!
myObject = response.Content.ReadAsAsync<MyObject>().Result;
}
So you could theoretically change your method like this (may not be exactly what you want):
public MyObject CreateQuote(MyObjectRequest myObject)
{
var hashtable = new Hashtable
{
{"myObject", myObject}
};
var task = GetResponse("", hashtable);
var response = task.Result;
MyObject newObject;
if (response.IsSuccessStatusCode)
{
// Parse the response body. Blocking!
newObject= response.Content.ReadAsAsync<MyObject>().Result;
}
return newObject; // instead of response
}

Categories

Resources