I have my Web Api on a production server online and working well in postman and in Xamarin forms so far until I needed to do a Get Request and does not return any data. Infact it stops at the GetAsStringAsync line and does not continue. Instead, it jumps out of the method and then nothing more.
Does any one know what the problem could be? I have checked and made sure my Internet is working and the Uri too.
This is where I am doing my Get in Xamarin forms:
public async Task<List<OfferModel>> AllOffers()
{
var httpclient = new HttpClient();
httpclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", Settings.AccessToken);
//it does not continue after this line, it jumps out of the method instead
var response = await httpclient.GetStringAsync(UrlConstants.offerurl);
var data =JsonConvert.DeserializeObject<List<OfferModel(response);
return data;
}
Solution 1
Can you try access task via awaiter it may be wait until result when responded
public class HttpHelperService
{
public async Task<List<OfferModel>> AllOffers()
{
List<OfferModel> result;
string responseBody;
using (HttpClient client = new HttpClient())
{
try
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", Settings.AccessToken);
HttpResponseMessage response = client.GetStringAsync(new Uri(UrlConstants.offerurl)).GetAwaiter().GetResult();
result = JsonConvert.DeserializeObject<List<OfferModel>>(response);
}
catch (Exception ex)
{
result = null;
}
return result;
}
}
}
Solution 2
public class MyPage : ContentPage
{
//Here is your page constructor
public MyPage()
{
GetServices(); //--> call here without awaiter
}
}
//Here is your awaiter method
private async void GetServices()
{
LoadingPopupService.Show();
var result = await HttpService.AllOffers();
LoadingPopupService.Hide();
}
//Here is your service.
public async Task<List<OfferModel>> AllOffers()
{
var httpclient = new HttpClient();
httpclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", Settings.AccessToken);
var response = await httpclient.GetStringAsync(UrlConstants.offerurl);
var data =JsonConvert.DeserializeObject<List<OfferModel(response);
return data;
}
Related
I want to connect to my Web api with these code
but when debugger arrived on
var response = await client.GetAsync(url);
skip without any error,
UPDATE
it's mean:
I set breakpoint and when debugger arrive on that line after that don't catch the next line and exit from this block and jump to caller method
public class Constants
{
public const string BaseUrl = "https://localhost:44301/";
}
2:
public static class GeneralUrl
{
public static string ComapnyNameUrl()
{
return string.Format(Constants.BaseUrl);
}
}
3: change to 3.1
public async static Task<List<CompanyName>> GetCompanyNamesAsync()
{
List<CompanyName> companyNameList = new List<CompanyName>();
string url = GeneralUrl.ComapnyNameUrl() + "api/CompanyName";
using (HttpClient client = new HttpClient())
{
var response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
string content =await response.Content.ReadAsStringAsync();
companyNameList = JsonConvert.DeserializeObject<List<CompanyName>>(content);
}
}
return companyNameList;
}
UPDATE 2
3.1:
I change above code to this but the problen exist
Update
public class CompanyNameService
{
private static HttpClient client = new HttpClient();
public async static Task<List<CompanyName>> GetCompanyNamesAsync()
{
List<CompanyName> companyNameList = new List<CompanyName>();
string url = GeneralUrl.ComapnyNameUrl() + "api/Companyname";
var response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
string content =await response.Content.ReadAsStringAsync();
companyNameList = JsonConvert.DeserializeObject<List<CompanyName>>(content);
}
return companyNameList;
}
}
also my startup.cs in my web api is
services.AddControllers().AddJsonOptions(o =>
{
o.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
o.JsonSerializerOptions.MaxDepth = 0;
});
services.AddControllers().AddNewtonsoftJson(options =>
options.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore);
END OF UPDATE 2
and final for calling them is=>
4:
protected override async void OnAppearing()
{
base.OnAppearing();
var companyName = await CompanyNameService.GetCompanyNamesAsync();
}
I think that it was for async method what is my mistake??
UPDATE
In debug mode in output windows I have this message
02-10 13:04:21.568 I/Choreographer( 790): Skipped 428 frames! The application may be doing too much work on its main thread.
02-10 13:04:21.642 I/OpenGLRenderer( 790): Davey! duration=7213ms; Flags=0, IntendedVsync=51372290598463, Vsync=51379423931511, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=51379430268200, AnimationStart=51379430347200, PerformTraversalsStart=51379430673700, DrawStart=51379441519600, SyncQueued=51379446948700, SyncStart=51379447122900, IssueDrawCommandsStart=51379447270300, SwapBuffers=51379483411800, FrameCompleted=51379504170100, DequeueBufferDuration=409000, QueueBufferDuration=612000,
UPDATE 3:
As I try use local address, after more than 5 min got a message in out put window that "the operation in canceled" and catch the exception with the same message.
Try this:
protected async override void OnAppearing()
{
base.OnAppearing();
var companyName = await GetCompanyNamesAsync();
}
public async static Task<List<CompanyName>> GetCompanyNamesAsync()
{
List<CompanyName> companyNameList = new List<CompanyName>();
string url = GeneralUrl.ComapnyNameUrl() + "api/Companyname";
using (HttpClient client = new HttpClient())
{
var response = await client.GetStringAsync(url);
companyNameList = JsonConvert.DeserializeObject<List<CompanyName>>(response);
}
return companyNameList;
}
First of all, I would like to say, I'm quite new to C#.
I'm trying to create a POST request which sends some data to a PHP file somewhere on a different server.
Now, after the request is send I would like to see the response, as I'm sending back a JSON string from the server as a success message.
When I use the following code:
public MainPage()
{
this.InitializeComponent();
Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().SetDesiredBoundsMode(Windows.UI.ViewManagement.ApplicationViewBoundsMode.UseCoreWindow);
responseBlockTxt.Text = start();
}
public string start()
{
var response = sendRequest();
System.Diagnostics.Debug.WriteLine(response);
return "";
}
public async Task<string> sendRequest()
{
using (var client = new HttpClient())
{
var values = new Dictionary<string, string>
{
{ "vote", "true" },
{ "slug", "the-slug" }
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("URL/api.php", content);
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
}
The output is:
System.Threading.Tasks.Task`1[System.String]
So, how would I see all the results from this?
Go Async all the way. Avoid blocking calls when calling async methods. async void is allowed in event handlers so update page to perform the call on load event
Read up on Async/Await - Best Practices in Asynchronous Programming
And then update your code accordingly
public MainPage() {
this.InitializeComponent();
Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().SetDesiredBoundsMode(Windows.UI.ViewManagement.ApplicationViewBoundsMode.UseCoreWindow);
this.Loaded += OnLoaded;
}
public async void OnLoaded(object sender, RoutedEventArgs e) {
responseBlockTxt.Text = await start();
}
public async Task<string> start() {
var response = await sendRequest();
System.Diagnostics.Debug.WriteLine(response);
return response;
}
private static HttpClient client = new HttpClient();
public async Task<string> sendRequest() {
var values = new Dictionary<string, string> {
{ "vote", "true" },
{ "slug", "the-slug" }
};
var content = new FormUrlEncodedContent(values);
using(var response = await client.PostAsync("URL/api.php", content)) {
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
}
I Guess
public string start()
{
var response = sendRequest();
Task<String> t = sendRequest();
System.Diagnostics.Debug.WriteLine(t.Result);
return "";
}
public async Task<string> sendRequest()
{
using (var client = new HttpClient())
{
var values = new Dictionary<string, string>
{
{ "vote", "true" },
{ "slug", "the-slug" }
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("URL/api.php", content);
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
}
The problem is in the start method, the SendRequest method returns a Task<string> and that's what you get on your response variable. Since you are attempting to run an async method synchronously you have to do some extra stuff, try this:
public string start()
{
var response = sendRequest().ConfigureAwait(true)
.GetAwaiter()
.GetResult();
System.Diagnostics.Debug.WriteLine(response);
return "";
}
That get the actual result inside your awaitable Task<string>. If you want to find some more info on this take a look at this question
public string start()
{
var response = sendRequest().ConfigureAwait(true)
.GetAwaiter()
.GetResult();
System.Diagnostics.Debug.WriteLine(response);
return "";
}
I have Tried this. It is working perfectly.
I'm trying to build an MVC that requests through a PCL to a WebApi. I am sending a get requests and getting stuck on the awaiting for the response. Postman returns the correct values. I also don t get exceptions on send. The 3 projects are both on the same solution.
PCL
HttpResponseMessage httpResponse = null;
try
{
httpResponse = await _http.GetAsync( "http://localhost:43818/api/values" );
}
catch (Exception e)
{
var meessage = e.Message;
var stack = e.StackTrace;
}
if (httpResponse.StatusCode == HttpStatusCode.OK)
{
string json = await httpResponse.Content.ReadAsStringAsync( );
}
So the issue is that in the PCL, it's doesn pass the await, it gets stuck.
MVC
var result = apiClient.GetIndex( );
Web Api
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}
Also, how do i wait in my MVC for the response before rendering the controller view
In your Class library (PCL), Create method GetIndex as below,
public async Task GetIndexAsync()
{
HttpResponseMessage httpResponse = null;
try
{
_http.BaseAddress = new Uri("http://localhost:43818/");
httpResponse = await _http.GetAsync("api/values");
}
catch (Exception e)
{
var meessage = e.Message;
var stack = e.StackTrace;
}
if (httpResponse.StatusCode == HttpStatusCode.OK)
{
string json = await httpResponse.Content.ReadAsStringAsync();
}
}
And In MVC calling method as below,
var result = apiClient.GetIndexAsync().Wait();
which solved both your problems.
Ok so i found the best sollution. Blocking threads is not a very good idea.
This is the fix
PCL
public async Task<HttpResponseMessage> Register()
{
HttpRequestMessage request = new HttpRequestMessage
{
RequestUri = new Uri( _http.BaseAddress, "account/register/" ),
Method = HttpMethod.Post,
Content = new StringContent( "{\"Email\": \"email#yahoo.com\",\"Password\": \"Password!1\",\"ConfirmPassword\": \"Password!1\"}",
Encoding.UTF8,
_contentType
),
};
HttpResponseMessage response = new HttpResponseMessage();
try
{
response = await _http.SendAsync( request, CancellationToken.None );
}
catch (Exception e)
{
Debugger.Break();
}
return response;
}
MVC Client
public async Task<ViewResult> Index( )
{
var thisTask = await Api.Register( );
return View();
}
I have a httpclient that is calling a WebAPI service. The GET reaches the service and returns the content but the client just keeps waiting...
Client code:
static async Task RunAsyncGet(string baseUri, string uri)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(baseUri);
HttpResponseMessage response = await client.GetAsync(uri); // <-- stuck here
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
IEnumerable<UserAccountModel> users = await response.Content.ReadAsAsync<IEnumerable<UserAccountModel>>();
//...
}
}
}
WebAPI code:
public class UserAccountController : ApiController
{
private IRepository _repo;
public UserAccountController(IRepository repo)
{
_repo = repo;
}
public HttpResponseMessage Get()
{
var s = _repo.GetAllUserAccounts();
IContentNegotiator negotiator = Configuration.Services.GetContentNegotiator();
ContentNegotiationResult result = negotiator.Negotiate(typeof(AuthResponseModel), Request, Configuration.Formatters);
var bestMatchFormatter = result.Formatter;
var mediaType = result.MediaType.MediaType;
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.OK,
Content = new ObjectContent<IQueryable<UserAccount>>(s, bestMatchFormatter, mediaType)
};
}
}
Thoughts?
Further up in your client code (whatever ends up calling RunAsyncGet), some code is calling Task.Wait or Task<T>.Result. That will cause a deadlock if called from the UI thread, as I explain on my blog.
The proper solution is to change that Wait/Result to use await.
This is how I ended up calling the WebAPI:
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:23302");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("api/useraccount").Result;
if (response.IsSuccessStatusCode)
{
var t = response.Content.ReadAsAsync<IEnumerable<UserAccount>>().Result;
...
}
else
{
//Something has gone wrong, handle it here
}
}
It seems that your call to EnsureSuccessStatusCode is the likely culprit. That method actually returns a HttpResponseMessage that will have a HTTP status in the 200 range, or will throw an exception. So, you probably want something like:
static async Task RunAsyncGet(string baseUri, string uri)
{
var client = new HttpClient();
client.BaseAddress = new Uri(baseUri);
HttpResponseMessage response = await client.GetAsync(uri);
IEnumerable<UserAccountModel> users = await response.EnsureSuccessStatusCode().Content.ReadAsAsync<IEnumerable<UserAccountModel>>();
// ... the rest ...
}
I'm currently developing an Android app using the Xamarin framework, so I'm writing it in c#. In this app I'm fetching data from a REST-api, like this:
//Method implemented from interface IOnScrollListener
public async void OnScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
//lots of other stuff that's not important for this example
List<Message> messageList = await PopulateMessagebox(arg1, arg2));
}
The method is being called when you reach the bottom of a list (hence the IOnScrollListener implementation). However; the screen freezes when I reach the bottom, and the method is being invoked. And I'm curious as to how this can be, considering I'm using an ansync method call? Shouldn't it run on another thread, allowing the main thread to be uninterrupted/not having to wait?
How would I go about fixing this, so that the app would be responsive while it, in the background, fetches additional info from the API?
Edit: Here's the populateMessageBox-method
public async Task<List<Message>> PopulateMessagebox(Constants.MMBType type, int skipSize)
{
string messagesJson = await _dal.GetMessageBox(type, skipSize, url);
var mess = new List<Message>();
try
{
if (!string.IsNullOrEmpty(messagesJson))
{
mess = Serializer.DeserializeMessagebox(messagesJson);
}
}
catch (Exception e)
{
Logger.Logg("Failed to de-serialize the messagebox:" + e);
throw new AppException(ErrorMessages.SerializationError);
}
return mess;
}
public async Task<string> GetMessageBox(Constants.MMBType type, int skipSize, string url)
{
return await GetMessageBoxJSON(type, skipSize, url);
}
--
private async Task<string> GetMessageBoxJSON(Constants.MMBType type, int skipSize, string url)
{
string res = null;
if (type == Constants.MMBType.Messagebox)
{
string param = string.Format("?$filter=Status ne '{0}' and Status ne '{1}'&$skip={2}",
Constants.NO.Nob.Status.Sent, Constants.NO.Nob.Status.SentCorres, skipSize);
string request = url + param;
res = await DownloadAndHandle(request);
}
And a couple more calls like this, ends us up here:
protected virtual async Task<string> SetupAndDownloadString(string uri)
{
string responseText;
if (Session.CookieJar.Size() > 0)
{
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, uri);
request.Headers.Add("ApiKey", AppContext.ApiKey);
request.Headers.Add("Accept", Constants.ApiFormat);
request.Headers.Add("Cookie", Session.CookieJar.ToString());
HttpResponseMessage response = await client.SendAsync(request);
responseText = response.Content.ReadAsStringAsync().Result;
}
else
{
throw new AppException(ErrorMessages.InsufficientAuthorization);
}
return responseText;
}