Xamarin Forms Json Service Insert Data - c#

I want to add a record to the json service in my application. How can I do this via Service Url. Here is my code.
CustomerModel customer = new CustomerModel();
customer.Name = entryCompanyName.Text;
customer.Title = entryCompanyTitle.Text;
customer.PhoneNumber = entryTelephone.Text;
customer.FaxNumber = entryFax.Text;
customer.Email = entryEmail.Text;
customer.CityId = 6444;
string json = JsonConvert.SerializeObject(customer);
string sContentType = "application/json";
string path = "service url";
HttpClient Client = new HttpClient();
var task = Client.PostAsync(path, new StringContent(json.ToString(), Encoding.UTF8, sContentType));
I'm trying M. Wiśnicki's solution, but I took this error
I did not get an error when I added System.net :( Where do i make mistakes?

This worked for me
public static async Task<string> PostEntityToApi<T>(string yourMethodUrl, T yourModel)
{
try
{
if (_httpClient == null)
{
_httpClient = new HttpClient { BaseAddress = new Uri(yourWebSiteUrl) };
}
var stringContentInput = new StringContent(JsonConvert.SerializeObject(dto), Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync(new Uri(yourWebSiteUrl. + apiUrl), stringContentInput);
if (!response.IsSuccessStatusCode)
{
throw new Exception(response.StatusCode.ToString());
}
var stringAsync = await response.Content.ReadAsStringAsync();
LoggingManager.Error("Received error response: " + stringAsync);
return stringAsync;
}
catch (Exception exception)
{
return null;
}
}

You can use WebRequest, this sample working for me, i use it in my app.
This is System.Net.WebRequest class, here you find doc.
public async Task<string> PostSample(object data, string uri)
{
// Create an HTTP web request using the URL:
var request = (HttpWebRequest) WebRequest.Create(new Uri(uri));
request.ContentType = "application/json";
request.Method = "POST";
var itemToSend = JsonConvert.SerializeObject(data);
using (var streamWriter = new StreamWriter(await request.GetRequestStreamAsync()))
{
streamWriter.Write(itemToSend);
streamWriter.Flush();
streamWriter.Dispose();
}
// Send the request to the server and wait for the response:
using (var response = await request.GetResponseAsync())
{
// Get a stream representation of the HTTP web response:
using (var stream = response.GetResponseStream())
{
var reader = new StreamReader(stream);
var message = JsonConvert.DeserializeObject<string>(reader.ReadToEnd());
return message;
}
}
}

Related

Refactor HttpWebRequest to HttpClient?

How would I convert this to HttpClient? What I'm looking to do is submit a Tweet to the Twitter api and get the response as Json. The HttpWebRequest is working fine but I just want to port it to HttpClient. I made an attempt at it in the second code example, but it's not actually sending or receiving the response.
HttpWebRequest request = null;
WebResponse response = null;
string responseCode = String.Empty;
try
{
string postBody = "status=" + EncodingUtils.UrlEncode(status);
request = (HttpWebRequest)HttpWebRequest.Create(resource_url);
request.ServicePoint.Expect100Continue = true;
request.UseDefaultCredentials = true;
request.PreAuthenticate = true;
request.Credentials = CredentialCache.DefaultCredentials;
request.ServicePoint.ConnectionLimit = 1;
request.Headers.Add("Authorization", authHeader);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
using (Stream stream = request.GetRequestStream())
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(postBody);
}
}
using (response = request.GetResponse())
{
response.ContentType = "application/json";
responseCode = ((HttpWebResponse)response).StatusCode.ToString();
}
}
catch (WebException ex)
{
if (ex.Status != WebExceptionStatus.NameResolutionFailure)
{
request.Abort();
request = null;
}
throw ex;
}
return responseCode;
This is what I've tried to get it work:
private async Task<string> MakeWebRequest1(string status, string resource_url, string authHeader)
{
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.Credentials = CredentialCache.DefaultCredentials;
clientHandler.PreAuthenticate = true;
clientHandler.AllowAutoRedirect = true;
string responseCode = "";
string postBody = "status=" + EncodingUtils.UrlEncode(status);
var request = new HttpRequestMessage()
{
RequestUri = new Uri(resource_url),
Method = HttpMethod.Post,
};
request.Headers.Add("Authorization", authHeader);
// request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
request.Content = new StringContent(postBody, Encoding.UTF8,"application/x-www-form-urlencoded");//CONTENT-TYPE header
using (HttpClient client = new HttpClient(clientHandler))
{
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
// Stream stuff = await client.GetStreamAsync(resource_url);
using (HttpResponseMessage response = await client.SendAsync(request))
{
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
if(response.StatusCode == HttpStatusCode.OK)
{
responseCode = "OK";
}
}
}
clientHandler.Dispose();
return responseCode;
}
enter code here
I've tried to add another parameter to the request and it's always coming back as 401 unauthorized. I'm trying to create a Twitter thread. If I remove the in_reply_to_status_id then it's fine.
data = new Dictionary<string, string> {
["status"] = "#username + status,
["in_reply_to_status_id"] = "1167588690929115136"
};
The Twitter API describes it here https://developer.twitter.com/en/docs/tweets/post-and-engage/api-reference/post-statuses-update
Reference You're using HttpClient wrong to understand why a static client is being used.
static Lazy<HttpClient> client = new Lazy<HttpClient>(() => {
HttpClientHandler clientHandler = new HttpClientHandler {
Credentials = CredentialCache.DefaultCredentials,
PreAuthenticate = true,
AllowAutoRedirect = true
};
return new HttpClient(clientHandler);
});
private async Task<string> PostStatusRequestAsync(string status, string resource_url, string authHeader) {
using (var request = new HttpRequestMessage(HttpMethod.Post, resource_url)) {
request.Headers.TryAddWithoutValidation("Authorization", authHeader);
request.Headers.Accept.Clear();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var data = new Dictionary<string, string> {
["status"] = status
};
request.Content = new FormUrlEncodedContent(data);
using (HttpResponseMessage response = await client.Value.SendAsync(request)) {
return response.StatusCode.ToString();
}
}
}
Note the use of the FormUrlEncodedContent for the request body, which will encode and concatenate the data as well as take care of the mime type header
...but it's not actually sending or receiving the response.
Ensure that the above is not invoked as a synchronous blocking call, like .Result, which could cause a deadlock.
For example, an async event handler can be used to make the async call
public async void onButtonClick(object sender, EventArgs args) {
//Non-blocking call
var tweetRequestCode = await PostStatusRequestAsync(TweetText, AuthUtils.GetResourceUrl(), AuthUtils.GetWebRequestHeader()));
//back on UI thread
//...
}
Reference Async/Await - Best Practices in Asynchronous Programming

Calling WEB API with basic authentication in C#

I have a working WEB API that I wrote, and I added basic authentication to the API (username is "testing", password is "123456"). However, when trying to call that API from my web form, I keep getting the "(401) Unauthorized" message. What should I change in the web code to call the API successfully?
string url = String.Format("http://example.com"); //here I have the correct url for my API
HttpWebRequest requestObj = (HttpWebRequest)WebRequest.Create(url);
requestObj.Method = "Get";
requestObj.PreAuthenticate = true;
requestObj.Credentials = new NetworkCredential("testing", "123456");
HttpWebResponse responseObj = null;
responseObj = (HttpWebResponse)requestObj.GetResponse();
string strresult = null;
using (Stream stream = responseObj.GetResponseStream())
{
StreamReader sr = new StreamReader(stream);
strresult = sr.ReadToEnd();
sr.Close();
}
This is what my API searches for in terms of authentication:
actionContext.Request.Headers.Authorization.Parameter
Should I be adding a header instead of NetworkCredential or is it the same thing?
This should help:
HttpMessageHandler handler = new HttpClientHandler()
{
};
var httpClient = new HttpClient(handler)
{
BaseAddress = new Uri(url),
Timeout = new TimeSpan(0, 2, 0)
};
httpClient.DefaultRequestHeaders.Add("ContentType", "application/json");
//This is the key section you were missing
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes("testing:123456");
string val = System.Convert.ToBase64String(plainTextBytes);
httpClient.DefaultRequestHeaders.Add("Authorization", "Basic " + val);
HttpResponseMessage response = httpClient.GetAsync(url).Result;
string content = string.Empty;
using (StreamReader stream = new StreamReader(response.Content.ReadAsStreamAsync().Result, System.Text.Encoding.GetEncoding(_encoding)))
{
content = stream.ReadToEnd();
}
This is the line I needed:
requestObj.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.Default.GetBytes("username:password"));
I just found out that with .NET Core 3.1 you could do it like this:
HttpRequestMessage request = new HttpRequestMessage(
HttpMethod.Post,
"your-api-url-here");
request.Headers.Authorization = new BasicAuthenticationHeaderValue(username, password);
I think your API might need a header being added to it (if you haven't done so already). Take a look at this article:
https://en.wikipedia.org/wiki/Basic_access_authentication#Client_side
But essentially, your API will need an Authorization header added to it. The Authorization key will contain the word Basic followed by a space, then the username and password encrypted using Base64. So in your instance, testing:123456 would be encrypted using base64 as dGVzdGluZzoxMjM0NTY=. So the header record will look like this:
Authorization: Basic dGVzdGluZzoxMjM0NTY=
(Basic Authentication) Here is the other solution to call Authenticated API
class Program
{
static void Main(string[] args)
{
BaseClient clientbase = new BaseClient("https://website.com/api/v2/", "username", "password");
BaseResponse response = new BaseResponse();
BaseResponse response = clientbase.GetCallV2Async("Candidate").Result;
}
public async Task<BaseResponse> GetCallAsync(string endpoint)
{
try
{
HttpResponseMessage response = await client.GetAsync(endpoint + "/").ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
baseresponse.ResponseMessage = await response.Content.ReadAsStringAsync();
baseresponse.StatusCode = (int)response.StatusCode;
}
else
{
baseresponse.ResponseMessage = await response.Content.ReadAsStringAsync();
baseresponse.StatusCode = (int)response.StatusCode;
}
return baseresponse;
}
catch (Exception ex)
{
baseresponse.StatusCode = 0;
baseresponse.ResponseMessage = (ex.Message ?? ex.InnerException.ToString());
}
return baseresponse;
}
}
public class BaseResponse
{
public int StatusCode { get; set; }
public string ResponseMessage { get; set; }
}
public class BaseClient
{
readonly HttpClient client;
readonly BaseResponse baseresponse;
public BaseClient(string baseAddress, string username, string password)
{
HttpClientHandler handler = new HttpClientHandler()
{
Proxy = new WebProxy("http://127.0.0.1:8888"),
UseProxy = false,
};
client = new HttpClient(handler);
client.BaseAddress = new Uri(baseAddress);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var byteArray = Encoding.ASCII.GetBytes(username + ":" + password);
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
baseresponse = new BaseResponse();
}
}

Send Json as body and file webrequest

How to send both body and also a file?
From the API Guide: "Upload Requests are submitted with multiple parts: body (request) and file buffer (file)."
I know how to send only a Json as body, but I need now to seng Json as body and also a file.
My code looks something like:
const string WEBSERVICE_URL = "https://myurl.com";
var webRequest = System.Net.WebRequest.Create(WEBSERVICE_URL);
webRequest.Method = "POST";
webRequest.ContentType = "multipart/form-data;boundary=12345678912345678912345678";
webRequest.Headers.Add("Authorization:7786FFFGFDDDP");
And:
string json="{"\some json"\ :\"here\" }"
using (var streamWriter = new StreamWriter(webRequest.GetRequestStream()))
{
streamWriter.Write(json);
}
var httpResponse = (HttpWebResponse)webRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
Console.WriteLine(result.ToString());
}
But how to send both file and body together? I mean I want also to upload some file wih path #c:\\myFile.txt
I need to do this in a Xamarin application. Post an image to a web api with token based authentication. I made some changes in code to be posible use in a web application.
public async void SendFile()
{
using (System.IO.FileStream stream = System.IO.File.Open(#"c:\file.txt", System.IO.FileMode.Open))
{
var content = new System.Net.Http.MultipartFormDataContent();
content.Add(new System.Net.Http.StreamContent(stream),
"\"file\"",
"Path to your file (ex: c:\temp\file.txt");
await PostItemAsyncWithToken("url to post", content, "accessToken");
}
}
public async System.Threading.Tasks.Task<bool> PostItemAsyncWithToken(string url, System.Net.Http.HttpContent content, string accessToken)
{
try
{
using (var httpClient = new System.Net.Http.HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
System.Net.Http.HttpResponseMessage response = await httpClient.PostAsync(url, content).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
return true;
}
else
{
return false;
}
}
}
catch (System.Exception ex)
{
throw new System.Exception("Error message", ex);
}
}

Get Access Token Using C#, Windows phone 8.1

I am trying to get the access token for the feed.Below is a code, i used to get the access token.
public async Task<string> GetAccessToken()
{
string postString = String.Format("username={0}&password={1}&grant_type=password", "userName", "pwd");
string url = "http://example.net/Token";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url.ToString());
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
UTF8Encoding utfenc = new UTF8Encoding();
byte[] bytes = utfenc.GetBytes(postString);
try
{
HttpWebResponse webResponse = (HttpWebResponse)(await request.GetResponseAsync());
Stream responseStream = webResponse.GetResponseStream();
StreamReader responseStreamReader = new StreamReader(responseStream);
string result = responseStreamReader.ReadToEnd();//parse token from result
}
catch(Exception ex)
{
}
return "";
}
The error below
"An error occurred while sending the request. The text associated with this error code could not be found.
The server name or address could not be resolved"
is throwing while it executes the below code
HttpWebResponse webResponse = (HttpWebResponse)(await request.GetResponseAsync());
Please help me to solve the issue
Try this if you are using POST request
public async Task<string> GetAccessToken()
{
string postString = String.Format("username={0}&password={1}&grant_type=password", "userName", "pwd");
try
{
using (var httpClient = new HttpClient())
{
var request1 = new HttpRequestMessage(HttpMethod.Post, "FeedURL");
request1.Content = new StringContent(postString);
var response = await httpClient.SendAsync(request1);
var result1 = await response.Content.ReadAsStringAsync();
result1 = Regex.Replace(result1, "<[^>]+>", string.Empty);
var rootObject1 = JObject.Parse(result1);
string accessToken = rootObject1["access_token"].ToString();
}
}
catch (Exception ex)
{
}
}

C# Xamarin Android Rest call in PCL error "Unexpected character encountered while parsing value: S. Path '', line 0, position 0."

I have used SO to help with several issues in the past. However, I cannot find a solution to something I have been struggling with for 2 days now.
I am a noob, please be kind :)
I have an app that I created using Xamarin Studio, targeted for Android. It is a basic GET request from a Rest Api. It was working perfectly until I realized I was not helping myself when it came time to create the same app in IOS and Windows. Once I changed my project to utilize a PCL I started getting errors, primarily around my RestClient class (originally got from http://www.codeproject.com/Tips/497123/How-to-make-REST-requests-with-Csharp)
From my droid app class:
var apiUser = GetString(Resource.String.apiUser);
var apiPass = GetString(Resource.String.apiPass);
//Get token from API
string token = authenticate(apiUser,apiPass);
public static string authenticate(string apiUser, string apiPass)
{
Authentication Auth = new Authentication ();
try
{
// set json by passing AuthenticationUrl as endpoint, returns json data
var o = JObject.Parse(EntryRepository.getJson(PJTApiUrls.getAuthenticationUrl(apiUser,apiPass)));
Auth.Token = (string)o["Token"];
return Auth.Token;
}
catch (Exception e)
{
// Couldn't do stuff. Log the exception.
// TODO possible timeout, try again, if fails again then return error message
if (e.Message.Contains("400") || e.Message.Contains("401"))
{
string error = string.Format("Invalid credentials, please try again");
return error;
} else {
string error = string.Format ("An error occurred: \r\n{0}", e.Message);
return error;
}
}
}
getAuthenticationUrl gets the api URL.
Here is getJson (in PCL):
public static string getJson(string endpoint)
{
string apiurl = endpoint;
var client = new _RestClient();
client.EndPoint = apiurl;
client.ContentType = "application/json";
client.Method = HttpVerb.GET;
//client.Method = HttpVerb.POST;
client.PostData = "";
//client.PostData = "{postData: value}";
//client.PostData = "{'someValueToPost': 'The Value being Posted'}";
var json = client._MakeRequestAsync();
// to append parameters, pass them into make request:
//var json = client.MakeRequest("?param=0");
return json.ToString();
}
And for the _RestClient class (in PCL):
public async Task<string> _MakeRequestAsync()
{
try {
var request = _MakeRequestAsync ("");
return await request;
}
catch (Exception e){
return e.Message;
}
}
public async Task<string> _MakeRequestAsync(string parameters)
{
var uri = new Uri(EndPoint + parameters);
var request = WebRequest.Create(uri) as HttpWebRequest;
using (var response = await request.GetResponseAsync () as HttpWebResponse) {
var responseValue = string.Empty;
if (response.StatusCode != HttpStatusCode.OK) {
var message = String.Format ("Request failed. Received HTTP {0}", response.StatusCode);
throw new Exception (message);
}
// grab the response
using (var responseStream = await Task.Factory.FromAsync<Stream>(request.BeginGetRequestStream, request.EndGetRequestStream, null)) {
//using (var responseStream = response.GetResponseStream ()) {
if (responseStream != null)
using (var reader = new StreamReader (responseStream)) {
responseValue = reader.ReadToEnd ();
}
}
return responseValue;
}
}
responseValue is returning null
return await request is saying "Status = Waiting for activation"
I have also had the error: "Unexpected character encountered while parsing value: S. Path '', line 0, position 0."
But this works if the RestClient class is within Droid (Instead of the shared PCL) and contains the following:
public string MakeRequest ()
{
return MakeRequest ("");
}
public string MakeRequest (string parameters)
{
var request = (HttpWebRequest)WebRequest.Create (EndPoint + parameters);
request.Method = Method.ToString ();
request.ContentLength = 0;
request.ContentType = ContentType;
if (!string.IsNullOrEmpty (PostData) && Method == HttpVerb.POST) {
var bytes = Encoding.GetEncoding ("iso-8859-1").GetBytes (PostData);
request.ContentLength = bytes.Length;
using (var writeStream = request.GetRequestStream ()) {
writeStream.Write (bytes, 0, bytes.Length);
}
}
using (var response = (HttpWebResponse)request.GetResponse ()) {
var responseValue = string.Empty;
if (response.StatusCode != HttpStatusCode.OK) {
var message = String.Format ("Request failed. Received HTTP {0}", response.StatusCode);
throw new ApplicationException (message);
}
// grab the response
using (var responseStream = response.GetResponseStream ()) {
if (responseStream != null)
using (var reader = new StreamReader (responseStream)) {
responseValue = reader.ReadToEnd ();
}
}
return responseValue;
}
}
I cannot figure this out, any help/guidance is appreciated. Let me know if I can clarify anything.
***** UPDATE ***** Thanks to #milen-pavlov help thus far, here is where I am currently at:
in Android project:
var apiUser = GetString(Resource.String.apiUser);
var apiPass = GetString(Resource.String.apiPass);
//Get token from API
var token = await authenticate(apiUser,apiPass);
lblOutput.Text = token;
calls (also in Android project):
public static async Task<string> authenticate(string apiUser, string apiPass)
{
Authentication Auth = new Authentication ();
try
{
// set json by passing AuthenticationUrl as endpoint, returns json data
var o = JObject.Parse(await EntryRepository.getJson(PJTApiUrls.getAuthenticationUrl(apiUser,apiPass)));
Auth.Token = (string)o["Token"];
return Auth.Token;
}
catch (Exception e)
{
if (e.Message.Contains("400") || e.Message.Contains("401"))
{
string error = string.Format("Invalid credentials, please try again");
return error;
} else {
string error = string.Format ("An error occurred: \r\n{0}", e.Message);
return error;
}
}
}
Calls json class in PCL project:
public static async Task<string> getJson(string endpoint)
{
string apiurl = endpoint;
var client = new _RestClient();
client.EndPoint = apiurl;
client.ContentType = "application/json";
client.Method = HttpVerb.GET;
client.PostData = "";
var json = await client._MakeRequestAsync();
return json;
}
which then calls restclient class in PCL project:
public async Task<string> _MakeRequestAsync()
{
var request = _MakeRequestAsync ("");
return await request;
}
public async Task<string> _MakeRequestAsync(string parameters)
{
var uri = new Uri(EndPoint + parameters);
using (var client = new HttpClient())
{
var response = await client.GetAsync(uri);
return await response.Content.ReadAsAsync<string>();
};
}
End result/error:
Any guidance is appreciated!
Can you use HttpClient instead?
Sample Get request will look similar to this:
public async Task<string> _MakeRequestAsync(string parameters)
{
var uri = new Uri(EndPoint + parameters);
using (var client = new HttpClient())
{
var response = await client.GetAsync(uri);
return await result.Content.ReadAsStringAsync();
};
}

Categories

Resources