How to use HttpWebRequest with async & await - android

I am new to Xamarin and C# as well. I try to make a Http request to my server with some information.
In general with android Native a uses AsyncTask and HttpClient for that. and build a json object or name value pair, and encrypt it to integrate information with the request.
But when I try to do the same with xamarin I get some problems.
if I try to import the namespace
using System.Net.Http.HttpClient
than my xamarin not have this namespace
Because of the above problem I try to use HttpWebRequest. But when I go for use it with the asyc and await I am not getting any response from server.
I am new to xamarin so I am not sure about async and await keyword.
I read lot of articles but No luck :(
on Click of the Button I call the below Method
public async Task<int> ValidateUser(){
try{
var request = HttpWebRequest.Create (URL);
request.Method = "GET/POST";
String postString = String.Format ("AAA ={0}&BBB={1}&CCC={2}", "111",
"222","333");
byte[] postByte = Encoding.UTF8.GetBytes (postString);
Stream st = request.GetRequestStream ();
//I am reaching here
Console.WriteLine("Check for Validity");
request.ContentLength = postByte.Length;
st.Write (postByte, 0, postByte.Length);
st.Close ();
Task<Stream> contentTask = request.GetRequestStreamAsync();
Stream response = await contentTask;
String str = response.ToString();
// this is not getting printed in Console
Console.WriteLine("=====>>"+str);
}
catch (WebException exception) {
string responseText;
using (var reader = new StreamReader(exception.Response.GetResponseStream())) {
responseText = reader.ReadToEnd ();
Console.WriteLine ("====Dude Error"+responseText);
}
}catch(Exception e){
}
return 1;
}
Any help will be appreciated

Consider using RestSharp, a component created for Xamarin to facilitate web requests. Click here for more info on the component. It will facilitate allot of things about webrequesting ( like serialization, automatic return type detection,... )
Your code would look something like this with restsharp:
public async Task<int> ValidateUser(){
var client = RestClient (URL);
var request = new RestRequest ("AAA ={0}&BBB={1}&CCC={2}", "111",
"222","333");
client.ExecuteAsync (request, response => {
WebApiResponse webApiResponse = new WebApiResponse ();
webApiResponse.Content = response.Content;
webApiResponse.StatusCode = response.StatusCode;
webApiResponse.ResponseStatus = (WebApiResponseStatus)response.ResponseStatus;
return webApiResponse.Content;
});
return -1
}

Using HttpWebRequest is a bad idea, instead it would be better to focus on why you don't have the System.Net.Http.* namespace. Imho the most likely cause is that you didn't add System.Net.Http as a reference to your project.
Here's how you add System.Net.Http.* to your project.
In Visual Studio 2013:
Open the solution
Open the project
Open the Solution Explorer
Right-click on References
Add Reference
Click on 'Search Assemblies'
Type in 'Http'
Select System.Net.Http
Press 'OK'
In Xamarin Studio:
Open the solution
Open the project
Open the Solution Explorer
Right-click on References
Edit References
Type in 'Http'
Select System.Net.Http
Press 'OK'
Afterwards there should be no problems resolving System.Net.Http when 'using System.Net.Http;'

Related

Use http urls with Flutter http during development

I am developing a flutter app with backend running in localhost.
I am using http package for making http calls. I am creating the Uri like this:
Uri.https("localhost:8080", "api/v1/login");
but this Uri.https gives error, instead I need to use Uri.http.
The problem is when the app is ready for production I will have to manually edit code everywhere to use Uri.https instead of Uri.http.
Is there a better way to handle this?
You can simple use kReleaseMode to detect you are in release mode or not.
String baseUrl;
if (kReleaseMode) {
baseUrl = 'https://example.com';
} else {
baseUrl = 'http://localhost';
}
Uri uri = Uri.parse('$baseUrl/api/v1/login');
you can do it like this:
var baseUrl = 'http://localhost:8080/';
Future<void> _fetchData() async {
final response = await http.get(Uri.parse('$baseUrl/api/v1/login'));
print(response.body);
}

xamarin android : httpclient PostAsync

we have an app under xamarin android build with visual studio 2017.
this app works since three years without any problems.
since two weeks and I don't know why actually some device can't sync with our back end.
It's really strange because nothing has change in this part .
this error does not appear on all devices but on one or two from time to time
we use the dll httpClient for to sync the datas with our backend.
If i put a break point inside the postAsync I have an exception with this -> Cannot access a disposed object. Object name: 'System.Net.Sockets.NetworkStream
Any one has an idea about how to solve this ? also what does it meam ?
Here is it the code of the postAsync method :
thanks for our time and comment guys
public override HttpResult ExecutePost(Uri target, string body)
{
var client = new HttpClient();
client.MaxResponseContentBufferSize = MaxHttpResponseBufferSize;
try
{
var requestContent = new StringContent(body, RequestContentEncoding, RequestContentType);
var response = client.PostAsync(target, requestContent).Result;
if (response.IsSuccessStatusCode)
{
var content = response.Content.ReadAsStringAsync().Result;
return new HttpResult(content, null, null);
}
return new HttpResult(null, "Response is empty", response.StatusCode.ToString());
}
catch (Exception e)
{
return new HttpResult(null, "Problem with the HttpPost", e.Message);
}
}
I experienced the same issue. Have been battling for 6 hours on this issue.
If you read the error, I was getting (Failed to connect to localhost/127.0.0.1:7113). If you put localhost in your browser or swagger tool it will work but if you put https://127.0.0.1:7113/api/weatherforecast in your browser it will not work. It will give you a certificate problem.
So I think you have to resolve 127.0.0.1 to localhost with https certificate on your local dev machine.
I'm building a MAUI app with Visual Studio 2022 Preview.
So I solved this issue by deploying my API to AZURE.
Then update to the azure url for example:
string apiUrl = "https://weatherforecast.azurewebsites.net/api/weatherforecast";
and then it worked brilliantly. Like super brilliantly.
Here is my code:
public void LoginAsync()
{
HttpClient client = new HttpClient();
string apiUrl = "https://weatherforecast.azurewebsites.net/api/weatherforecast";
UserCredentials.EmailAddress = LoginUIEntity.EmailAddress;
UserCredentials.Password = LoginUIEntity.Password;
string serialized = JsonConvert.SerializeObject(UserCredentials);
var inputMessage = new HttpRequestMessage
{
Content = new StringContent(serialized, Encoding.UTF8, "application/json")
};
inputMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
try
{
var message = client.PostAsync(apiUrl, inputMessage.Content).Result;
if (message.IsSuccessStatusCode)
{
var apiResponse = message.Content.ReadAsStringAsync();
UserCredentials = JsonConvert.DeserializeObject<UserCredentials>(apiResponse.Result);
if (UserCredentials.IsValid)
{
UserCredentials.IsLoggedIn = true;
}
else
{
ErrorMessage = "Invalid credentials supplied.";
}
}
}
catch (Exception ex)
{
ErrorMessage = "An error has occurred. Please contact support if the error persists.";
}
}
}
thanks for the link your provide.
I've try up the buffer on the postasync / try to sync in wifi OR 3G / delete special character in json / ...
but nothing work
we have move the prod database to the test and try to sync the data to the test database with postman. with postman the result was ENTITY TOO LARGE !
Json is size > 1.2 mega and the default value inside IIS is set to 1 mega
Here is it the problem ...
thanks problem solve

UnityWebRequest does nothing on IL2CPP Build

I've been trying to simply call an api on an android build supporting 64 bit (IL2CPP build) and the UnityWebRequest class didnt seem to work. It's being called via a simple ui button click. It hits the webRequest.SendWebRequest(); and nothing happens. Ive tried the following samples. One, directly from the Unity docs for UnityWebRequest and others using standard HttpClient.
UnityWebRequest:
IEnumerator GetRequest(string uri)
{
using (UnityWebRequest webRequest = UnityWebRequest.Get(uri))
{
webRequest.SetRequestHeader("Authorization", "Bearer " + API_KEY);
yield return webRequest.SendWebRequest();
if (webRequest.isNetworkError)
{
debugText.text = ": Error: " + webRequest.error;
coroutineAllowed = false;
}
else
{
debugText.text = ":\nReceived: " + webRequest.downloadHandler.text;
dynamic jsonObj = JsonConvert.DeserializeObject(webRequest.downloadHandler.text);
foreach (var obj in jsonObj["businesses"])
{
businessResults.Add(new Business()
{
name = (string)obj["name"],
image_url = (string)obj["image_url"],
review_count = (string)obj["review_count"],
rating = (string)obj["rating"],
Coordinates = new Coordinates()
{
Latitude = (float)obj["coordinates"]["latitude"],
Longitude = (float)obj["coordinates"]["longitude"]
},
price = (string)obj["price"]
});
}
debugText.text = businessResults.Count.ToString();
//coroutineAllowed = true;
}
debugText.text = "getRequest 4";
}
}
This unfortunately did nothing at the yield return webRequest.SendWebRequest();
The next sample I tried was using HttpClient():
IEnumerator HttpClientCall(string uri) //possibly wrap in IEnumerator
{
debugText.text += "http coroutine started" +Environment.NewLine;
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", API_KEY);
var response = httpClient.GetAsync(uri);
if (response.Result.StatusCode != HttpStatusCode.OK)
{
debugText.text += "FAILED HTTP GET";
}
yield return response.Result.Content.ReadAsStringAsync();
dynamic jsonObj = JsonConvert.DeserializeObject(response.Result.Content.ReadAsStringAsync().Result);
foreach (var obj in jsonObj["businesses"])
{
businessResults.Add(new Business()
{
name = (string)obj["name"],
image_url = (string)obj["image_url"],
review_count = (string)obj["review_count"],
rating = (string)obj["rating"],
Coordinates = new Coordinates()
{
Latitude = (float)obj["coordinates"]["latitude"],
Longitude = (float)obj["coordinates"]["longitude"]
},
price = (string)obj["price"]
});
debugText.text += Environment.NewLine + ((string)obj["name"]);
}
}
}
Once again, nothing when it hits yield return response.Result.Content.ReadAsStringAsync();
These all work on PC, and they both return results that i'm expecting.
The next thing i heard was about setting the android manifest application tag with android:usesCleartextTraffic="true"
This unfortunately, also did nothing for me lol. I know it has to be the 64 support, because this works on a standard build. The moment i go to build with 64 support, it doesnt work.
Any help on why it's not returning appropriately would be very helpful.
side note, i know the code is pretty ugly, but after i can figure out why the build doesnt work on the device a heavy refactoring is going to be in play. Thanks in advance!
So after a lot of trouble shooting ive found out why this was not working. The main issue seems to be stemming from my use of the standard Newtonsoft Json package when Unity, apparently, has their own internal JsonUtility class. After changing this:
dynamic jsonObj = JsonConvert.DeserializeObject(response.Result.Content.ReadAsStringAsync().Result);
To This:
var js = JsonUtility.FromJson<T>(response.Result.Content.ReadAsStringAsync().Result);
my results are finally showing in the the apk build correctly.
Also, to note that to map correctly, the JsonUtility.FromJson must be typed to a class that exactly mirrors the incoming json object explicitly.
The page article that finally helped me with this issue is here.
P.S.
Thank you to #RetiredNinja for trying to help instead of just downvoting and saying nothing of value. You're amazing!

Getting error when use Android Koush Ion to call Laravel route

I'm trying to learn android development, I'm using Android Studio. I need to access an external database (to insert, get itens ... CRUD) and I've found a tutorial that tells me to use koush ion, from Android using Ion, I call a web page that is a Laravel 7 Route. When I call without parameters, it works very well and I can get in Android the returned value. But when I use "setBodyParameter", I get the following error:
java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.gson.JsonElement com.google.gson.JsonObject.get(java.lang.String)' on a null object reference
My laravel route just calls this function:
function cadastrar(){
date_default_timezone_set('America/Sao_Paulo');
$resposta = array();
$myUser = null;
$nome = isset($_POST['nome']) ? $_POST['nome'] : 'Teste 2';
$email = isset($_POST['email']) ? $_POST['email'] : 'teste#gmail.com';
$myUser = new Usuario;
$myUser->nome = $nome;
$myUser->email = $email;
$myUser->save();
$resposta = array('id' => strval($myUser->id_usuario), 'nome' => $myUser->nome, 'email' => $myUser->email);
return json_encode($resposta);
}
My Laravel route is Route::get (but when I change it to Route::post I get an error too).
And my Android code that calls this page is:
final TextView txtErro = (TextView) findViewById(R.id.textView4);
txtErro.setText("");
final String strNome = nome.getText().toString();
final String strEmail = email.getText().toString();
String url = "**My URL to the route in laravel**";
Ion.with(MainActivity.this)
.load(url)
.setBodyParameter("nome", strNome)
.setBodyParameter("email", strEmail)
.asJsonObject()
.setCallback(new FutureCallback<JsonObject>() {
#Override
public void onCompleted(Exception e, JsonObject result) {
try {
txtErro.setText(result.get("id").getAsString());
} catch (Exception erro) {
txtErro.setText(erro.toString());
}
}
});
When I comment the two lines of ".setBodyParameter", I get the returned value from laravel (if laravel route is Route::get). When I change the line of "load" to "load("POST", url)", I get an error.
I tried something related to CORS that I found here in StackOverflow and in my Laravel Kernel.php I commented the line that calls "VerifyCsrfToken", but still didn't working.
(Finally, I'm sorry if have something wrong in my english)
Did you try logging the Exception e and JsonObject result?
or set logging for the request and watch it in logcat
.setLogging("MyLogs", Log.DEBUG)

I cannot established connection with WCF services in Xamarin

I have a WPF application in VB.NET that already developed by my old colleagues. Now, my superior want to replace current platform by implementing the same concept to be run on the Android system. So, I've decided to use Xamarin Android .NET Standard.
I have searched for a way to consume WCF and the error throw before I'm asking but I'm still stuck at the same error.
I have set up the service references WCF on the android class. Given on solution, I have 2 projects:- MyProject and MyProject.Android
===========================================================================
WPF
Private Function EstablishConnect() As Boolean
Try
Dim context As InstanceContext = New InstanceContext(Me)
svrobj = New DisplayServicesClient(context, "DisplayTcpBinding")
Dim endpointAddress As New EndpointAddress(modUtility.ServerEndPointAddress)
svrobj.Endpoint.Address = endpointAddress
svrobj.Open()
SecondDiffFromServer = DateDiff(DateInterval.Second, Now, svrobj.GetDateTime)
Return True
Catch ex As Exception
WriteLog.Log(ex.ToString, True)
Return False
End Try
End Function
modUtility.ServerEndPointAddress get from INI:
net.tcp://localhost:8002/AppServ/WCFServices/Display
===========================================================================
XAMARIN FORMS
private async Task<bool> EstablishConnectAsync()
{
try
{
InstanceContext context = new InstanceContext(this);
svrobj = new DisplayServicesClient(DisplayServicesClientBase.EndpointConfiguration.DisplayTcpBinding); //, DisplayServicesClientBase.EndpointConfiguration.DisplayTcpBinding
EndpointAddress endpointAddress = new EndpointAddress(modUtility.ServerEndPointAddress);
svrobj.Endpoint.Address = endpointAddress;
await svrobj.OpenAsync();
modUtility.SecondDiffFromServer = (int)(DateTime.Now - await svrobj.GetDateTimeAsync()).TotalSeconds;
return true;
}
catch (Exception ex)
{
Device.BeginInvokeOnMainThread(() =>
{
ResultText.Text = "Unable to established connection with endpoint service. Ex-" + ex.Message;
});
return false;
}
}
modUtility.ServerEndPointAddress get from settings:
net.tcp://10.0.2.2:8002/AppServ/WCFServices/Display
I'm currently run android on emulator.
My code throw exception on any call to svrobj function. Below are the error that throw:-
The communication object System.ServiceModel.DuplexChannelFactory`1[AppServ.IDisplayServices] is not at created state but at Opening state.
The method or operation is not implemented.
Do I missing something or do I have implement wrong way?

Categories

Resources