WebService Post is working on emulator but not on device - c#

I'm trying to POST data to a WebService with SSL Certification.
It's working fine in Emulator but the Device is keeping stuck on GetResponseAsync(). I tried it with HttpClient with and without ModernHttpClient-Library but it stuck on PostAsync(), so it doesn't work too.
One Solution i tried of another Thread is just to add
System.Net.ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
^but it's also not working
In Manifest i added Permissions for Internet.
Thats the Code with GetResponseAsync()
public async Task<Response<V>> CallWebServiceAsync<T, V>(string ticket, string url, T requestData)
{
try
{
var request = new Request<T>
{
Ticket = ticket,
Data = requestData
};
DataContractJsonSerializer serializer = new DataContractJsonSerializer(request.GetType(), this._knownTypes);
var httpRequest = WebRequest.CreateHttp(url);
httpRequest.Method = "POST";
httpRequest.UseDefaultCredentials = true;
httpRequest.ContentType = "application/json";
var requestStream = await httpRequest.GetRequestStreamAsync().ConfigureAwait(false);
serializer.WriteObject(requestStream, request);
var response = await httpRequest.GetResponseAsync().ConfigureAwait(false);
var resultStream = response.GetResponseStream();
if (resultStream == null)
{
throw new FailedWebServiceInteractionException($"Got no response stream from request. URL:{url}");
}
var jsonResponseSerializer = new DataContractJsonSerializer(typeof(Response<V>), this._knownTypes);
Response<V> result = (Response<V>)jsonResponseSerializer.ReadObject(resultStream);
resultStream.Dispose();
return result;
}
catch (Exception e)
{
throw new FailedWebServiceInteractionException("Deserialization from json response failed", e);
}
}
Code with PostAsync() (+- ModernHttpClient)
public async Task<Response<V>> CallWebServiceAsync<T, V>(string ticket, string url, T requestData)
{
try
{
var request = new Request<T>
{
Ticket = ticket,
Data = requestData
};
var httpClientHandler = new NativeMessageHandler
{
UseDefaultCredentials = true
};
var httpRequest = new HttpClient(httpClientHandler)
{
BaseAddress = new Uri(url)
};
httpRequest.DefaultRequestHeaders.Accept.Clear();
httpRequest.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var content = JsonConvert.SerializeObject(request);
var response =
await
httpRequest.PostAsync(url, new StringContent(content, Encoding.UTF8, "application/json"))
.ConfigureAwait(false);
var jsonString = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
return JsonConvert.DeserializeObject<Response<V>>(jsonString);
}
catch (Exception e)
{
throw new FailedWebServiceInteractionException("Deserialization from json response failed", e);
}
}
I don't know if the certificates are the problem or something else.
They're not self-signed.

I found a solution. Time is gone since then. I don't know the exact solution but here is my code that works fine now:
var request = new Request<T>
{
Ticket = ticket,
Data = requestData
};
var httpClientHandler = new OkHttpClientHandler
{
UseDefaultCredentials = true,
AllowAutoRedirect = true,
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate,
ClientCertificateOptions = ClientCertificateOption.Automatic
};
var client = new HttpClient(httpClientHandler)
{
BaseAddress = new Uri(url),
Timeout = TimeSpan.FromSeconds(15)
};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var jsonRequest = this.SerializeToJson(request);
var compressedRequest = StringCompressor.CompressString(jsonRequest);
var httpRequest = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = new ByteArrayContent(compressedRequest)
{
Headers = {ContentType = new MediaTypeHeaderValue("application/json")}
}
};
var httpResponse = await client.SendAsync(httpRequest, cancellationToken).ConfigureAwait(false);
client.Dispose();
httpResponse.EnsureSuccessStatusCode();
var compressedResponse = await httpResponse.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
httpResponse.Dispose();
var jsonResponse = StringCompressor.DecompressString(compressedResponse);
var jsonResponseSerializer = new DataContractJsonSerializer(typeof(Response<V>), this._knownTypes);
Response<V> result;
using (var jsonResponseStream = this.GenerateStreamFromString(jsonResponse))
{
result = (Response<V>) jsonResponseSerializer.ReadObject(jsonResponseStream);
}
return result;
I'm using a self compiled wrapper of OkHttpClient library. I think ModernHttpClient (it is referencing OkHttp too) works too. Someone needs to test it.
Important to know is any other project that references this project need the library too.
App.Base Project - Implemented the above code to connect to
Webservice
App Project - References to App.Base. Need the library
too.

Related

Postman form-data: How to program it inside a HttpRequestMessage?

I am doing a request through postman to a specific url but I set the form-data type in order to get data to the site like this:
Now I want to program this request inside C# but everything I tried so far is returning a 400 Bad Request response. This is what I tried:
public async Task<CheckAccessTokenModel> CheckAccessTokenAsync(string accessToken)
{
string uriString = "someurl";
var uri = new Uri(uriString);
try
{
using(var httpClient = new HttpClient())
{
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = uri
};
var ClientId = ConfigurationAccessor.Configuration["WebCredentials:ClientId"];
var Secret = ConfigurationAccessor.Configuration["WebCredentials:Secret"];
var authString = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{ClientId}:{Secret}"));
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", authString);
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(new StringContent("token"), accessToken);
request.Content = content;
var response = await httpClient.SendAsync(request);
var checkTokenResponseData = await response.Content.ReadAsStringAsync();
//return new CheckAccessTokenModel { Active = true, Exp = 1647431224233 };
return JsonConvert.DeserializeObject<CheckAccessTokenModel>(checkTokenResponseData);
}
}
catch
{
return null;
}
}
I am doing it with the MultipartFormDataContent Object as suggested by many others here but it still won't work.
What can be the problem here?
EDIT: Wrong picture replaced
You can simply
request.Content = new StringContent($"token={accessToken}");
With form data I think it's something like this:
var data = new Dictionary<string, string>
{
{"token", acccessToken}
};
using var content = new FormUrlEncodedContent(data);
request.Content = content;

POST API does not give any result or error on being called using HTTPClient in C# .NET

I have an API made in .NET which I am trying to call in my frontend.
The JSON is being generated just fine but the API itself is not being called at all from the cs file code.
public async void createTransaction(String e)
{
Transaction t = new Transaction();
t.EmployeeEmail=e;
t.ManagerEmail="test#test.com";
t.Request="admin";
var json = JsonConvert.SerializeObject(t);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var url = "http://localhost:5001/ssp/addData";
using var client = new HttpClient();
var response = await client.PostAsync(url, data);
string result = response.Content.ReadAsStringAsync().Result;
Console.WriteLine(result);
}
No error is being thrown but the API is not being called also.
But after some time it says TaskCanceledException and I am unable to make any sense of that.
Any kind of help will be greatly appreciated.
using var client = new HttpClient();
var response = await client.PostAsync(url, data);
Should be
HttpResponseMessage response;
using (var client = new HttpClient())
{
response = await client.PostAsync(url, data);
}
Or
var client = new HttpClient();
var response = await client.PostAsync(url, data);
// ...
client.Dispose();
The problem was not at all with code. After hours of debugging found out that the "https" in the API url was required instead of http.
HttpClientHandler clientHandler = new HttpClientHandler();
clientHandler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; };
// Pass the handler to httpclient(from you are calling api)
var client = new HttpClient(clientHandler)
After adding this everything started working exactly fine.

How to redirect call to API from particular proxy server?

I have an API which i want to get access from one of my proxy server only. As that server have given all access to access that particular API. So I have single endpoint.
I have proxy server URL and Port and i want to add proxy settings in my app settings file and implement it so when call is given to API, that particular call pass through the Proxy server.
Please assist me how can I achieve this?
Current Call to API as below.
PushMessageAndroidRequest req = new PushMessageAndroidRequest();
req.registration_ids = list.Select(x => x.Token).ToList();
req.data = new AndroidData() { Payload = CommonLib.ConvertObjectToJson(payload) };
response = await RequestHandler.PostDataAsync<PushMessageResponse>(_appConfig.pushMessageConfigs.Url, req, new List<KeyValue>() { new KeyValue("Authorization", "key=" + _appConfig.pushMessageConfigs.Key) });
Sample code have written
public static async Task<ResJsonOutput> ProxyDataAsync(string ApiPath,string obj, List<KeyValue> Headers = null)
{
ResJsonOutput result = new ResJsonOutput();
HttpResponseMessage response = new HttpResponseMessage();
var requestUri = string.Format(ApiPath);
var request = (HttpWebRequest)WebRequest.Create(requestUri);
WebProxy myproxy = new WebProxy(Settings.ProxyAddress, Settings.ProxyPort);
myproxy.BypassProxyOnLocal = false;
request.Proxy = myproxy;
using (WebResponse response = request.GetResponse())
{
using (StreamReader stream = new StreamReader(response.GetResponseStream()))
{
//JObject jResponse = JObject.Parse(stream.ReadToEnd());
//var isSuccess = jResponse.Value<bool>("success");
//result = (isSuccess) ? true : false;
}
}
return result;
}

C# Add item to Sharepoint list using REST API

I would like to add an item to a list in sharepoint using below code:
protected string httpGetPost(string getPostMode, string url, string dataToPost = "")
{
HttpWebRequest endpointRequest = (HttpWebRequest)WebRequest.Create(url);
endpointRequest.Method = getPostMode;
var credentialCache = new CredentialCache();
credentialCache.Add(
new Uri(endpointRequest.RequestUri.GetLeftPart(UriPartial.Authority)), // request url's host
"Digest", // authentication type
new NetworkCredential(userName, password) // credentials
);
endpointRequest.Credentials = credentialCache;
endpointRequest.Accept = "application/json;odata=verbose";
endpointRequest.ContentType = "application/json;odata=verbose";
if (!string.IsNullOrEmpty(dataToPost))
{
using (Stream dataStream = endpointRequest.GetRequestStream())
{
byte[] bs = Encoding.ASCII.GetBytes(dataToPost);
dataStream.Write(bs, 0, bs.Length);
}
}
using (var resp = endpointRequest.GetResponse())
{
var html = new StreamReader(resp.GetResponseStream()).ReadToEnd();
return html;
}
}
And call the above method using below code:
httpGetPost("POST", url, "{\"__metadata\": { \"type\": \"SP.Data.Test_x0020_ListListItem\" }, \"Title\": \"Test\", \"Column B\", \"BBB\"}");
Here's the data I'm posting:
{"__metadata": { "type": "SP.Data.Test_x0020_ListListItem" }, "Title":
"Test", "Column B", "BBB"}
I've took a look at this website https://msdn.microsoft.com/en-us/library/office/dn292552.aspx, but the authorization is different, it's using an accesstoken, but here's the problem:
In this website: http://sharepoint.stackexchange.com/questions/69617/sharepoint-2013-oauth-url-to-get-token, it saids I can't get the accesstoken, so I used username and password to login the sharepoint, but here comes another problem:
A System.Net.WebException is thrown in var resp = endpointRequest.GetResponse(), the error is saying The remote server returned an error: (403) Forbidden.
The account is a domain admin as well as a sharepoint admin.
Why I'm still getting the 403 error?
For some reasons, I can only use the REST API to communicate with sharepoint.
Here is a slightly different method to achieve your goals. Some of the objects are specific to Store Apps in this example, but they can all easily be replaced with other values in a standard app.
public string digest()
{
String retVal = "";
try
{
string url = "https://YourSite.com/";
HttpClient client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true });
client.BaseAddress = new System.Uri(url);
string cmd = "_api/contextinfo";
client.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
client.DefaultRequestHeaders.Add("ContentType", "application/json");
client.DefaultRequestHeaders.Add("ContentLength", "0");
StringContent httpContent = new StringContent("");
var response = client.PostAsync(cmd, httpContent).Result;
if (response.IsSuccessStatusCode)
{
string content = response.Content.ReadAsStringAsync().Result;
JsonObject val = JsonValue.Parse(content).GetObject();
JsonObject d = val.GetNamedObject("d");
JsonObject wi = d.GetNamedObject("GetContextWebInformation");
retVal = wi.GetNamedString("FormDigestValue");
}
}
catch
{ }
return retVal;
}
FileOpenPicker picker = new FileOpenPicker();
picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
picker.ViewMode = PickerViewMode.Thumbnail;
// Filter to include a sample subset of file types.
picker.FileTypeFilter.Clear();
picker.FileTypeFilter.Add(".bmp");
picker.FileTypeFilter.Add(".png");
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".jpg");
// Open the file picker.
StorageFile path = await picker.PickSingleFileAsync();
if (path != null)
{
string url = "https://YourSite.com/Subsite/";
HttpClient client = new HttpClient(new HttpClientHandler() { UseDefaultCredentials = true });
client.BaseAddress = new System.Uri(url);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Accept", "application/json;odata=verbose");
client.DefaultRequestHeaders.Add("X-RequestDigest", digest());
client.DefaultRequestHeaders.Add("X-HTTP-Method", "POST");
client.DefaultRequestHeaders.Add("binaryStringRequestBody", "true");
IRandomAccessStream fileStream = await path.OpenAsync(FileAccessMode.Read);
var reader = new DataReader(fileStream.GetInputStreamAt(0));
await reader.LoadAsync((uint)fileStream.Size);
Byte[] content = new byte[fileStream.Size];
reader.ReadBytes(content);
ByteArrayContent file = new ByteArrayContent(content);
HttpResponseMessage response = await client.PostAsync("_api/web/lists/getByTitle(#TargetLibrary)/RootFolder/Files/add(url=#TargetFileName,overwrite='true')?#TargetLibrary='Project Photos'&#TargetFileName='TestUpload.jpg'", file);
response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{ }
}

How to post data using HttpClient?

I have got this HttpClient from Nuget.
When I want to get data I do it this way:
var response = await httpClient.GetAsync(url);
var data = await response.Content.ReadAsStringAsync();
But the problem is that I don't know how to post data?
I have to send a post request and send these values inside it: comment="hello world" and questionId = 1. these can be a class's properties, I don't know.
Update I don't know how to add those values to HttpContent as post method needs it. httClient.Post(string, HttpContent);
You need to use:
await client.PostAsync(uri, content);
Something like that:
var comment = "hello world";
var questionId = 1;
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("comment", comment),
new KeyValuePair<string, string>("questionId", questionId)
});
var myHttpClient = new HttpClient();
var response = await myHttpClient.PostAsync(uri.ToString(), formContent);
And if you need to get the response after post, you should use:
var stringContent = await response.Content.ReadAsStringAsync();
Try to use this:
using (var handler = new HttpClientHandler() { CookieContainer = new CookieContainer() })
{
using (var client = new HttpClient(handler) { BaseAddress = new Uri("site.com") })
{
//add parameters on request
var body = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("test", "test"),
new KeyValuePair<string, string>("test1", "test1")
};
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "site.com");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded; charset=UTF-8"));
client.DefaultRequestHeaders.Add("Upgrade-Insecure-Requests", "1");
client.DefaultRequestHeaders.Add("X-Requested-With", "XMLHttpRequest");
client.DefaultRequestHeaders.Add("X-MicrosoftAjax", "Delta=true");
//client.DefaultRequestHeaders.Add("Accept", "*/*");
client.Timeout = TimeSpan.FromMilliseconds(10000);
var res = await client.PostAsync("", new FormUrlEncodedContent(body));
if (res.IsSuccessStatusCode)
{
var exec = await res.Content.ReadAsStringAsync();
Console.WriteLine(exec);
}
}
}
Use UploadStringAsync method:
WebClient webClient = new WebClient();
webClient.UploadStringCompleted += (s, e) =>
{
if (e.Error != null)
{
//handle your error here
}
else
{
//post was successful, so do what you need to do here
}
};
webClient.UploadStringAsync(new Uri(yourUri), UriKind.Absolute), "POST", yourParameters);

Categories