Asynchronous request not working after separating data retrieval code - asp.net-mvc

I am trying to display some results after querying a webapi as below -
public async Task<ActionResult> Get()
{
string _address = "someurl";
string results = null;
HttpClient client = new HttpClient(new OAuthMessageHandler(new HttpClientHandler()));
HttpResponseMessage responseTask = await client.GetAsync(_address);
if (responseTask.IsSuccessStatusCode)
{
results = await responseTask.Content.ReadAsStringAsync();
}
ResultModel model = JsonConvert.DeserializeObject<ResultModel>(results);
return View(model);
}
This code works fine and I am able to read the results from "someurl" url. Now, when I refator the code as below (by moving the async data retrieval to another function), it stops working. It forever takes to query and does not return any result. Is this because of some deadlock or am I not using async correctly.
public ActionResult Get()
{
string _address = "someurl";
Task<string> results = HttpClientService.HttpClientService.GetRequest(_address);
IEnumerable<ResultModel> model = JsonConvert.DeserializeObject<IEnumerable<ResultModel>>(results.Result);
return View(model);
}
public static class HttpClientService
{
public static async Task<string> GetRequest(string Url)
{
HttpClient client = new HttpClient(new OAuthMessageHandler(new HttpClientHandler()));
HttpResponseMessage responseTask = await client.GetAsync(Url);
if (responseTask.IsSuccessStatusCode)
{
return await responseTask.Content.ReadAsStringAsync();
}
else
{
return "Sorry buddy, cannot retrieve the requested data!";
}
}
}
Please let me know what am I doing wrong here. I am new to Async implementation.

You should await the GetRequest method. Otherwise you are defeating the purpose of async processing which is to release the thread so it can do other work. In this case you are still blocking the thread when you ask for a result via results.Result.
public async Task<ActionResult> Get()
{
string _address = "someurl";
string results = await HttpClientService.HttpClientService.GetRequest(_address);
IEnumerable<ResultModel> model = JsonConvert.DeserializeObject<IEnumerable<ResultModel>>(results);
return View(model);
}
Frankly I am not sure why your code is not returning but even if it was working correctly it would be pointless to do async requests in this way.

Related

Is it fine to use "return Ok(await result)" in MVC/.Net Core

I got this sample code I used in MVC/.Net Core Controller
public async Task<IActionResult> GetData([FromQuery]string id, CancellationToken cancellationToken)
{
Person person= new Person {
Id = id,
Name = "Test name"
};
return Ok(await Task.FromResult(person));
}
The await is it fine to use inside Ok() ?
It's fine to use await when passing parameters to Ok (or any other method).
return Ok(await SomeMethodAsync());
is roughly equivalent to
var result = await SomeMethodAsync();
return Ok(result);
which is roughly equivalent to
var resultTask = SomeMethodAsync();
var result = await resultTask;
return Ok(result);

Web ApI: HttpClient is not invoking my web api action

See first how i design my web api action.
[System.Web.Http.RoutePrefix("api/Appointments")]
public class AppointmentsServiceController : ApiController
{
[System.Web.Http.HttpGet, System.Web.Http.Route("UserAppointments/{email}")]
public IHttpActionResult UserAppointments(string email)
{
if (!string.IsNullOrEmpty(email))
{
AppointmentsService _appservice = new AppointmentsService();
IEnumerable<Entities.Appointments> app = _appservice.GetUserWiseAppointments(email);
if (app.Count() <= 0)
{
return NotFound();
}
else
{
return Ok(app);
}
}
else
{
return BadRequest();
}
}
}
Now this way i am calling web api action from my asp.net mvc action by HttpClient.
public async Task<ActionResult> List()
{
var fullAddress = ConfigurationManager.AppSettings["baseAddress"] + "api/Appointments/UserAppointments/" + Session["useremail"];
IEnumerable<Entities.Appointments> app = null;
try
{
using (var client = new HttpClient())
{
using (var response = client.GetAsync(fullAddress).Result)
{
if (response.IsSuccessStatusCode)
{
var customerJsonString = await response.Content.ReadAsStringAsync();
app = JsonConvert.DeserializeObject<IEnumerable<Entities.Appointments>>(customerJsonString);
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(response.Content.ReadAsStringAsync().Result);
//MessageBox.Show(dict["Message"]);
}
}
}
}
catch (HttpRequestException ex)
{
// catch any exception here
}
return View();
}
}
i want capture the return IEnumerable and if not data return that also i have to capture. please show me the right direction.
Where i made the mistake. thanks
Mixing async with blocking calls like .Result
var response = client.GetAsync(fullAddress).Result
And
response.Content.ReadAsStringAsync().Result
can lead to deadlocks, which is possibly why it it not hitting your API.
Refactor the code to be async all the way.
That would mean updating the using to
var response = await client.GetAsync(fullAddress)
and the reading of the content in the else statement to
await response.Content.ReadAsStringAsync()
Reference Async/Await - Best Practices in Asynchronous Programming
It looks like you are not awaiting your GetAsync call, so in the following if (response.IsSuccessStatusCode) is probably always returning false. Try calling your method like this:
using (var response = (await client.GetAsync(fullAddress)).Result)
{

Invoke Task Method in an MVC Action but current Thread be Locked

public class HomeController : Controller
{
public ActionResult Index()
{
var t1= Test1().Result;
return View();
}
private async Task<HttpResponseMessage> Test1()
{
string strUrl = "http://localhost:52033/api/values";
var instanceClient = new HttpClient();
var requestMessage = new HttpRequestMessage(HttpMethod.Get, strUrl);
var httpRespons = await instanceClient.SendAsync(requestMessage);
return httpRespons;
}
}
When I was in the Index Action called Test1 (). The Result; Will happen when the current thread deadlock program has been no response, do not bring the Result calls suffixes can normal operation!
You shouldn't call Result or Wait in an ASP.NET context; one reason is that it could cause deadlocks, as I explain on my blog.
Instead, you should use await, like this:
public async Task<ActionResult> Index()
{
var t1 = await Test1();
return View();
}

async calls using HttpClient on MVC4

I'm playing a little bit with this new technology in .net 4.5, I would like to check the code for this call and how should I control the errors or the response of my async call.
The call is working perfectly, I need full control of possible errors returned from my service.
this is my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
namespace TwitterClientMVC.Controllers
{
public class Tweets
{
public Tweet[] results;
}
public class Tweet
{
[JsonProperty("from_user")]
public string UserName { get; set; }
[JsonProperty("text")]
public string TweetText { get; set; }
}
}
public async Task<ActionResult> Index()
{
Tweets model = null;
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync("http://mywebapiservice");
response.EnsureSuccessStatusCode();
model = JsonConvert.DeserializeObject<Tweets>(response.Content.ReadAsStringAsync().Result);
return View(model.results);
}
Is this the better way to do it? or I'm missing something?
Thanks
I refactor it, is this method async as well?
public async Task<ActionResult> Index()
{
Tweets model = null;
using (HttpClient httpclient = new HttpClient())
{
model = JsonConvert.DeserializeObject<Tweets>(
await httpclient.GetStringAsync("http://search.twitter.com/search.json?q=pluralsight")
);
}
return View(model.results);
}
Is this the better way to do it?
The response.EnsureSuccessStatusCode(); will throw an exception if the status code returned by your remote service is different than 2xx. So you might want to use the IsSuccessStatusCode property instead if you want to handle the error yourself:
public async Task<ActionResult> Index()
{
using (HttpClient client = new HttpClient())
{
var response = await client.GetAsync("http://mywebapiservice");
string content = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var model = JsonConvert.DeserializeObject<Tweets>(content);
return View(model.results);
}
// an error occurred => here you could log the content returned by the remote server
return Content("An error occurred: " + content);
}
}

MVC4 "Cannot await"

The following code snippet is causing a compilation error that I am hard to understand.
Error 1 Cannot await System.Collections.Generic.List'<BusinessLogic.News>'
Any suggestions?
public class NewsController : Controller
{
public async Task<ActionResult> Index(int page=1)
{
NewsNavigator News = new NewsNavigator();
await News.Load(page);
...
return View(News);
}
}
public List<News> Load(int page = DefaultPage, int pageSize = DefaultPageSize, string filter = DefaultFilter)
{
//DBLayer_News
...
return LoadedNews;
}
Await is applied to the result of a method call that returns a Task.
You cannot call it on News because News isn't a Task. Create a Task and pass your News.Load method to it.
NewsNavigator News = new NewsNavigator();
var newsLoadTask = Task.Factory.StartNew(() => News.Load(page));
await newsLoadTask;
...

Resources