I have a problem sending a JSON POST via HttpClient object in a MVVMCROSS solution (Xamarin). MVVMCROSS is just a Model View ViewModel framework for cross-platform e.g. Droid, iOS, Windows etc.
So the Solution is like this:
--Core (where I have my ViewModels and Services)
--Droid (Android Layout etc)
--iOS (Not used currently)
Inside the Core I have my Service classes which I initialize via IoC (Inversion of Control, something like dependency injection)
I have this awesome API which I can use via JSON Post request. The API does face recognition and sends back the 'mood' of the face (Angry, Neutral, Happy etc.)
To use this my JSON should look like this
{
"url" : "http://previews.123rf.com/images/kadettmann/kadettmann1508/kadettmann150800099/43824672-Handsome-argentinian-guy-at-beach-Stock-Photo-happy.jpg"
}
So far so good, now the POST url is : https://api.projectoxford.ai/emotion/v1.0/recognize
Seems not to hard I guess!
I also need to send two headers:
Content-Type = application/json
Ocp-Apim-Subscription-Key = My super awesome secret key
If is send this JSON via POSTMAN (Chrome plugin) I get the expected result:
[
{
"faceRectangle": {
"height": 312,
"left": 563,
"top": 208,
"width": 312
},
"scores": {
"anger": 0.00000000112,
"contempt": 0.000000049,
"disgust": 0.0000000035,
"fear": 0.000000000106,
"happiness": 0.99999994,
"neutral": 0.000000000238,
"sadness": 0.00000000005,
"surprise": 0.00000000160
}
}
]
So now i'm trying to make a MVVMCROSS app for Android and iOS which sends this JSON to the server of Microsoft.
The method I use looks like this:
public async Task<bool> RestRequestSucces(string secret, string jsonSerialized)
{
bool result = false;
try
{
HttpResponseMessage response;
using (var httpClient = new HttpClient())
{
var request = new StringContent(jsonSerialized);
request.Headers.ContentType = new MediaTypeHeaderValue("application/json");
httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", secret);
response = await httpClient.PostAsync(new Uri("https://api.projectoxford.ai/emotion/v1.0/recognize"), request);
result = true;
}
}
catch (Exception e)
{
string error = e.Message;
result = false;
}
return result;
}
The JsonObject to serialized looks like this:
public class URLObject
{
public string url { get; set; }
}
To serialize the object I use this
private IMvxJsonConverter serializer = Mvx.Resolve<IMvxJsonConverter>();
serializer.SerializeObject(urlObject);
But at response = await httpClient.PostAsync
my code hangs. It does not go any furthur.
I call the method RestRequestSucces
like this:
IRestService restService = Mvx.Resolve<IRestService>();
restService.RestRequestSucces(secret, jsonSerialized);
This all happens inside the Core project.
My AndroidManifest.xml looks like this:
...
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application android:label="@string/ApplicationName" android:icon="@drawable/Icon" android:theme="@style/MyTheme"></application>
</manifest>
If someone could show me how to just POST a 'simple' JSON via MVVMCROSS inside the CORE project, that would be awesome!!
Solved it myself,
Turns out HttpClient
has trouble with some TLS/SSL website (https). By just using the ModernHttpClient
solved my issue!
The rest of the code remains the same, only the HttpClient
constructor is different
using (var httpClient = new HttpClient(new NativeMessageHandler()))
{
....
}
The NativeMessageHandler
is a HttpClientHandler
and can be found in the ModernHttpClient
, the code looks like this:
namespace ModernHttpClient
{
public class NativeMessageHandler : HttpClientHandler
{
public NativeMessageHandler();
public NativeMessageHandler(bool throwOnCaptiveNetwork, bool customSSLVerification, NativeCookieHandler cookieHandler = null);
public bool DisableCaching { get; set; }
public void RegisterForProgress(HttpRequestMessage request, ProgressDelegate callback);
[AsyncStateMachine(typeof(<SendAsync>c__async0))]
[DebuggerStepThrough]
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken);
}
}
Hope you guys can use this! Link to ModernHttpClient on github.