Xamarin android invalid uri exception - android

In my Xamarin android application I need to make an api call to openweathermap to get current weather data according to the user's current location.
Here is my query string code:
url = "api.openweathermap.org/data/2.5/weather?lat=" +
_currentLocation.Latitude +
"&lon=" +
_currentLocation.Longitude +
"&APPID=" + openWeatherAPIKey
+ "&units=imperial";
Now in the method FetchUrlAsync I send the web request and retrieve the response json. Below is the code of the method:
async Task<JsonValue> FetchUrlAsync(string url)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new System.Uri(url));
request.ContentType = "application/json";
request.Method = "GET";
using (WebResponse response = await request.GetResponseAsync())
{
// Get a stream representation of the HTTP web response:
using (System.IO.Stream stream = response.GetResponseStream())
{
// Use this stream to build a JSON document object:
JsonValue jsonDoc = await Task.Run(() => JsonObject.Load(stream));
Console.Out.WriteLine("Response: {0}", jsonDoc.ToString());
// Return the JSON document:
return jsonDoc;
}
}
}
I get a System.URIFormatException thrown on the first line of the method because the format of the uri is wrong. I checked other stack overflow questions and I think it might be because my url string does not start with a http:// or ftp. But I can't add http:// or ftp in front of the url string because that leads to an unrecognized server.
Any solution to this issue? Or does it not have to do with adding the http:// or ftp prefix?

Related

Receiving a json from an API on Flutter app

I'm trying to receive the response on a http post but the response comes empty. I know its something basic but i can't make it work.
It should receive a JSON with some data, but the data doesn't come, probably its a problem on the reply part on my code.
Heres the code:
Future<void> _login2() async {
HttpClient client = new HttpClient();
client.badCertificateCallback =
((X509Certificate cert, String host, int port) => true);
String url = 'https://sistema.hutransportes.com.br/api/login.php';
Map map = {"user": "test", "pass": "123456"};
HttpClientRequest request = await client.postUrl(Uri.parse(url));
request.headers.set('content-type', 'application/json');
request.add(utf8.encode(json.encode(map)));
HttpClientResponse response = await request.close();
String reply = await response.transform(utf8.decoder).join();
print(reply); //should show the data from the http
}
I would recommend you to use the powerful library https://pub.dev/packages/dio

Unable to send body parameter in Dart/ Flutter multipart request

I m trying to upload image using Multipart request using Dart/ Flutter.
but parameter not getting on serverside.
var request = http.MultipartRequest('POST', uri);
request.fields['access_token'] = token;
request.files.add(await http.MultipartFile.fromBytes(
'image', path.readAsBytesSync(),
contentType: MediaType('image', 'jpeg')));
request.headers['Content-Type'] = "multipart/form-data";
request.headers['access_token'] = token;
var response = await request.send();
It's likely that you're sending an empty payload. From the code snippet you've provided, it's possible that path.readAsBytesSync() wasn't able to return the File immediately. You can add an await keyword on your function to wait for the return value before proceeding to send the Request.

How to make a client which authenticates against ASP.NET WebAPI?

enter image description hereI have created REST API in ASP.NET with http://server/token as URL.
The header having
content-type: application/x-www-form-urlencode
The body have grant_type as password, username and password will get json data with token.
For further data access token can be used above method works with postman
I need to implement a client in Android Studio or Xamarin.
as urls in postman is "example.com/token"; , then in Header Key value pais for content type as ("Content-Type:application/x-www-form-urlencoded) and in body key value pair as (grant_type:password, username:email,password:pass) and after send the response is in json format as follows { "access_token": "token", "token_type": "bearer", "expires_in": 1209599, "userName": "mail#gmail.com", ".issued": "Fri, 09 Dec 2016 19:19:18 GMT", ".expires": "Fri, 23 Dec 2016 19:19:18 GMT" }
this same needed to be done in android
Include in your dependencies System.Net.Http (requires Xamarin profile 111) and then you can use that to create a HttpClient and request the token via HTTP POST (akin to what you were doing in Postman) like this..
_client = new HttpClient();
var uri = new Uri("http://server/token");
var content = new FormUrlEncodedContent(
new List<KeyValuePair<string, string>> {
new KeyValuePair<string, string>("username", _username),
new KeyValuePair<string, string>("password", _password),
new KeyValuePair<string, string>("grant_type", "password")
});
HttpResponseMessage response = await _client.PostAsync(uri, content);
Where _username and _password are strings.
Then read the response out by converting it into a Dictionary or any other reasonable alternative approach to parsing the JSON response.
if (response.StatusCode == HttpStatusCode.OK) {
var jsonContent = await response.Content.ReadAsStringAsync();
var responseDict = JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonContent);
if (responseDict.ContainsKey("access_token"))
_token = responseDict["access_token"];
}
Then once you have the token, you can include it as a default authorization value for all headers from that HttpClient instance!
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _token);
Where _token is the token as it's encoded string, e.g. "eyJ0eXAiOiJKV1QiLC..."
Just implemented this and to verify it's correctness - I ran it against a production environment I have set up to verify using JWTs and it worked a charm.
this works, it looks ugly but you can change it
var authCredentials = "grant_type=password&username=" + WebUtility.UrlEncode(LoginBindingModel.Email) + "&password=" + LoginBindingModel.Password;
string response = await Client.MakePostFormRequest("token", authCredentials);
public static async Task<string> MakePostFormRequest(string url, string data)
{
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(BaseUrl + "token");
// Set the Method property of the request to POST.
request.Accept = "*/*";
request.Method = "POST";
// Create POST data and convert it to a byte array.
byte[] byteArray = Encoding.UTF8.GetBytes(data);
// Set the ContentType property of the WebRequest.
request.ContentType = "application/x-www-form-urlencoded";
// Set the ContentLength property of the WebRequest.
//request.ContentLength = byteArray.Length;
// Get the request stream.
Stream dataStream = await request.GetRequestStreamAsync().ConfigureAwait(false);
// Write the data to the request stream.
dataStream.Write(byteArray, 0, byteArray.Length);
// Close the Stream object.
dataStream.Dispose();
// Get the response.
WebResponse response = await request.GetResponseAsync().ConfigureAwait(false);
// Display the status.
//Console.WriteLine(((HttpWebResponse)response).StatusDescription);
// Get the stream containing content returned by the server.
dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
string responseFromServer = reader.ReadToEnd();
// Display the content.
//Console.WriteLine(responseFromServer);
// Clean up the streams.
TokenViewModel TokenViewModel = JsonConvert.DeserializeObject<TokenViewModel >(responseFromServer);
VariablesGlobales.Token = TokenViewModel.access_token;
VariablesGlobales.LoginStamp = TokenViewModel.LoginStamp;
reader.Dispose();
dataStream.Dispose();
response.Dispose();
return responseFromServer;
}
catch (Exception ex)
{
return "";
}
}
And when you want to authenticate your request
public static async Task<string> MakePostRequest(string url, string data)
{
var result = "";
try
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(BaseUrl + url);
httpWebRequest.ContentType = "application/json; charset=utf-8";
httpWebRequest.Method = "POST";
if (VariablesGlobales.Token != "")
{
httpWebRequest.Headers[HttpRequestHeader.Authorization] = "Bearer " + VariablesGlobales.Token;
}
using (var streamWriter = new StreamWriter(await httpWebRequest.GetRequestStreamAsync().ConfigureAwait(false)))
{
streamWriter.Write(data);
streamWriter.Flush();
}
var httpResponse = (HttpWebResponse)(await httpWebRequest.GetResponseAsync().ConfigureAwait(false));
if (httpResponse.StatusCode.ToString() == "OK")
{
result = httpResponse.StatusCode.ToString();
}
else
{
result = "";
}
}
catch (Exception ex)
{
result = "";
}
return result;
}
}

Xamarin Android Rest API to PassSlot - nameResolutionFailure

I'm using a REST API to access PassSlot in an attempt to generate a pass / coupon. It seems that when i run the program i get the error: "Error: NameResolutionFailure".
I have:
public static async Task<string> SendAndReceiveJsonRequest()
{
string responseStr = null;
string uri = "https://api.passslot.com/v1/templates/my-template-ID/pass";
// Create a json string with a single key/value pair.
var json = new JObject (new JProperty ("lastName", lastName),
new JProperty ("firstName", firstName),
new JProperty ("percentOff", percentOff),
new JProperty ("offerDescription", offerDescription),
new JProperty ("entityName", entityName),
new JProperty ("expiry", expiry));
//Console.WriteLine ("Jake's JSON " + json.ToString ());
using (var httpClient = new HttpClient ())
{
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("My-Key-Here-xxx-xxx-xxx");
//create the http request content
HttpContent content = new StringContent(json.ToString());
try
{
// Send the json to the server using POST
Task<HttpResponseMessage> getResponse = httpClient.PostAsync(uri, content);
// Wait for the response and read it to a string var
HttpResponseMessage response = await getResponse;
responseStr = await response.Content.ReadAsStringAsync();
}
catch (Exception e)
{
Console.WriteLine("Error communicating with the server: " + e.Message);
}
}
return responseStr;
}
I'm running this on Android 4.4 via a Nexus 4. I'm on 3G (not wifi).
Any hints as to what might be happening here and why i'm getting the error.
In case the url request is in local network, Check if you url ip is set in the hosts device (the hosts setting of the smartphone, tablet, whatever you are using to test)
PD.
To edit the hosts setting device in android you may use this app
https://play.google.com/store/apps/details?id=com.nilhcem.hostseditor

remote server returned an error: (401) unathorized in C# GCM response

I have seen this question posted in a thousand places and I have tried all the solutions that have worked for others but I am not able to get this to work for me. I used this post as my baseline for the project that Im using (Unauthorized when calling Google GCM). I have tried both the API key and the browser key with no success.
Here is my code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Web;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.IO;
namespace GCMTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string BrowserAPIKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
string message = "some test message";
string tickerText = "example test GCM";
string contentTitle = "content title GCM";
string postData = "{ \"registration_ids\": [ \"" + txtRegistrationID.Text + "\" ], \"data\": {\"tickerText\":\"" + tickerText + "\", \"contentTitle\":\"" + contentTitle + "\", \"message\": \"" + message + "\"}}";
string response = SendGCMNotification(BrowserAPIKey, postData);
}
private string SendGCMNotification(string apiKey, string postData, string postDataContentType = "application/json")
{
// from here:
// https://stackoverflow.com/questions/11431261/unauthorized-when-calling-google-gcm
//
// original:
// http://www.codeproject.com/Articles/339162/Android-push-notification-implementation-using-ASP
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateServerCertificate);
//
// MESSAGE CONTENT
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
//
// CREATE REQUEST
HttpWebRequest Request = (HttpWebRequest)WebRequest.Create("https://android.googleapis.com/gcm/send");
Request.Method = "POST";
Request.KeepAlive = false;
Request.ContentType = postDataContentType;
//Request.Headers.Add(string.Format("Authorization: key={0}", apiKey));
Request.Headers.Add(HttpRequestHeader.Authorization, String.Format("key={0}", apiKey));
Request.ContentLength = byteArray.Length;
//Stream dataStream;
try
{
Stream dataStream = Request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
//
// SEND MESSAGE
try
{
WebResponse Response = Request.GetResponse();
HttpStatusCode ResponseCode = ((HttpWebResponse)Response).StatusCode;
if (ResponseCode.Equals(HttpStatusCode.Unauthorized) || ResponseCode.Equals(HttpStatusCode.Forbidden))
{
MessageBox.Show("Unauthorized - need new token");
}
else if (!ResponseCode.Equals(HttpStatusCode.OK))
{
MessageBox.Show("Response from web service isn't OK");
}
StreamReader Reader = new StreamReader(Response.GetResponseStream());
string responseLine = Reader.ReadToEnd();
Reader.Close();
return responseLine;
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
return "error";
}
public static bool ValidateServerCertificate(
object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
return true;
}
}
}
Its erring on this line:
WebResponse Response = Request.GetResponse();
With the following message:
"The remote server returned an error: (401) Unauthorized."
The form allows an input of a device registration id. If I can get this working it will be altered to be more usable in a production environment. The application is running on my local machine right now but will ultimately reside on a remote server.
Any help that I can get would be GREATLY appreciated. I have been reading posts about this for a week now and I haven't been able to make any progress. One thing that I think might be causing this problem is the fact that Im running this locally instead of on the server. Does this request need to come from the address that is listed in the "referer" in the browser key?
Thanks again!
If you are using a Browser Key, you should remove the allowed referrers of that key, so that it would say Any referrer is allowed. This would allow you to send the notifications from a locally run server.
Otherwise, you'll be able to send GCM messages using that Browser Key only from Web Sites that have the domain specified in allowed referrers.
Check on the console (console.developers.google.com) if the API "Google Cloud Messaging for Android" is active.
I had the same problem, I thought it was active and wasn't

Categories

Resources