Xamarin Forms Sending Image - c#

I'm trying to send an image to my server using a multipart data form, but whenever I attempt to send it I am timing out due to a lack of response. I am able to connect to the server when I try to post an HTTPContent object, but am having problems once I throw in MultiPartFormDataContent objects. I have tested the PHP code with an html form, so I know the problem lies in my Xamarin code
Xamarin Code:
MultipartFormDataContent Content = new MultipartFormDataContent();
HttpContent FileContent = new ByteArrayContent(Appointment.PicBytes);
Content.Add(FileContent, "AppointmentPicture", "AppointmentPicture");
HttpResponseMessage Response = await Client.PostAsync(Uri, Content);
string Details = await Response.Content.ReadAsStringAsync();

You could try this
string convertedImage = Convert.ToBase64String(data);
HttpContent content = new StringContent(convertedImage, Encoding.UTF8, "application/json");

Related

Send zip file using web service

I have created a web service using .NET Web API. The web service part works great, I am able to send the zip file using Advanced REST Client. The problem is that I can't send the zip file programmatically. Here is the Advanced REST Client Request Headers:
I have try some things but without success. I am not posting what I have try, considering that this is basic stuff for web developers (I am desktop developer), but if it is necessary, I will. Thank you in advance.
EDIT: This is my recent version
private async void BeginUpdate(bool webserverStatus)
{
if (!webserverStatus) return;
var httpClient = new HttpClient();
var form = new MultipartFormDataContent();
var byteArray = File.ReadAllBytes("myUpdatePackage.zip");
form.Add(new ByteArrayContent(byteArray, 0, byteArray.Length), "myUpdatePackage", "myUpdatePackage.zip");
HttpResponseMessage response = await httpClient.PostAsync(#"http://localhost:9000/api/file/", form);
response.EnsureSuccessStatusCode();
httpClient.Dispose();
string sd = response.Content.ReadAsStringAsync().Result;
}
I realized that on Advanced REST Client, I was it using PUT, meanwhile on my C# application I call it using POST
HttpResponseMessage response = await httpClient.PostAsync(#"http://localhost:9000/api/file/", form);
So, here is the complete code:
private async void BeginUpdate(bool webserverStatus)
{
if (!webserverStatus) return;
var byteArray = File.ReadAllBytes("myUpdatePackage.zip");
var httpClient = new HttpClient();
var form = new MultipartFormDataContent();
form.Add(new ByteArrayContent(byteArray, 0, byteArray.Length), "myUpdatePackage", "myUpdatePackage.zip");
HttpResponseMessage response = await httpClient.PutAsync(#"http://localhost:9000/api/file/", form);
response.EnsureSuccessStatusCode();
httpClient.Dispose();
string sd = response.Content.ReadAsStringAsync().Result;
}
More details on this question

Unable to Send JSON data to HttpClient in C# Android

I'm trying to do something that seems like it should be simple: to send a JSON request to a PHP script on my webserver and get the response.
I can request the site without issue, I can read the response without issue, but for some reason this refuses to send the contents of my JSON data.
string url = "https://www.exampleserver.com/examplescript.php";
HttpClient client = new HttpClient(new Xamarin.Android.Net.AndroidClientHandler());
client.BaseAddress = new Uri(url);
string jsonData = #"{""key1"" : ""data1"",""key2"" : ""data2"",""key3"" : ""data3""}";
HttpContent content = new StringContent(jsonData, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(url, content);
string result = await response.Content.ReadAsStringAsync();
responsebox.Text = result;
Each time I run it the contents of responsebox.Text is replaced with the default contents of the page pointing out explicitly that there was no content in the $_POST data. (Even checked $_REQUEST to make sure it wasn't showing up as GET).
I know it's gotta be something simple, but I can't find it.

InvokeApiAsync returning 415 on StringContent (Monodroid / Xamarin.Android)

Using Xamarin Studio, making Xamarin.Android app with Azure Mobile Service + .NET Backend custom managed API (WebApi 2). I know my Mobile Service is working, because I can see that my app is hitting it in the logs. Here's the signature of my custom api:
[HttpPost]
[Route("postplant")]
public HttpResponseMessage PostPlant([FromBody] string imageInBase64)
I'm trying to trigger this using InvokeApiAsync, have tried a few overloads but am trying to go with the Raw Http one. My string is a jpg that's been converted to base 64; if I input the string directly to my mobile services test site, it works fine.
My problem is, I'm getting a 415 unsupported entity media type (text/plain) error.
Message='UserMessage='The request entity's media type 'text/plain' is
not supported for this resource.'', Status=415 (UnsupportedMediaType),
Exception=System.Web.Http.HttpResponseException: Processing of the
HTTP request resulted in an exception.
Here's my call in Xamarin:
HttpContent content = new StringContent(imageInBase64, System.Text.Encoding.UTF8);
HttpResponseMessage resp = await _service.InvokeApiAsync(#"jv/postplant", content, HttpMethod.Post, null, null);
I have also tried the following versions (and a combination of the following) defining the content-type as application/json explicitly; these hit the API OK, but the input parameter is coming through as null, so the method fails:
HttpContent content = new StringContent(imageInBase64, System.Text.Encoding.UTF8, "application/json");
HttpResponseMessage resp = await _service.InvokeApiAsync(#"jv/postplant", content, HttpMethod.Post, null, null);
and
HttpContent content = new StringContent(imageInBase64, System.Text.Encoding.UTF8);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
HttpResponseMessage resp = await _service.InvokeApiAsync(#"jv/postplant", content, HttpMethod.Post, null, null);
and
HttpContent content = new StringContent(imageInBase64, System.Text.Encoding.UTF8);
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
Dictionary<string, string> reqHeaders = new Dictionary<string, string>();
reqHeaders.Add("ContentType", "application/json; charset=UTF-8");
HttpResponseMessage resp = await _service.InvokeApiAsync(#"jv/postplant", content, HttpMethod.Post, reqHeaders, null);
I've also tried switching up the string so it's in json (like {"imageInBase64"="xxxxlotofcharactersinbase64"}), but nothing's working. What am I missing?
Solved my problem. The image was already in a string, but I had to serialize it like so:
string jObj = JsonConvert.SerializeObject(imageInBase64);
StringContent content = new StringContent(jObj, System.Text.Encoding.UTF8);
MediaTypeHeaderValue mValue = new MediaTypeHeaderValue("application/json");
content.Headers.ContentType = mValue;
That fixed my 415 unsupported entity media type (text/plain) error; unfortunately the call was still failing on the client side, freezing at the call and never registering a response (despite my server confirming a response of 200 had been sent back).
I ultimately fixed this by removing async/await from InvokeApiAsync; either I'm not using them properly, or my app is failing when trying to await stuff. The calls never complete. Instead I changed these to get the Result of the async InvokeApiAsync. Here's my solution:
HttpResponseMessage resp = _service.InvokeApiAsync(#"jv/postplant", content, HttpMethod.Post, null, null).Result;
_service.Dispose();
string result = await resp.Content.ReadAsStringAsync();
JToken json = JToken.Parse(result);
return json;

Migrating a C# library to Windows Phone

I'm trying to migrate a Windows C# library to Windows Phone 8 and I'm forced to make some changes in how the library gets data from an online URI.
I'm using the BCL's HttpClient to perform my data retrieval and everything's fine for now.
The library also requires an upload feature, and I can't find a way to do this using th HttpClient.
Here's the code:
// Client setup
var httpclient = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, string.Format(SubmitURI, value));
// Add the headers
request.Headers.Add("header", header);
var postData = GetPostData();
var data = Encoding.UTF8.GetBytes(postData);
// Side question -> Content is null here!
request.Content.Headers.Add("ContentType", "multipart/form-data; boundary=" + Boundary);
// BEGIN ORIGINAL CODE
var stream = request.GetRequestStream();
stream.Write(data, 0, data.Length);
stream.Close();
// END ORIGINAL CODE
// Get response
var response = await httpclient.SendAsync(request);
var responseContent = new StreamReader(await response.Content.ReadAsStreamAsync()).ReadToEnd();
Between the BEGIN ORIGINAL CODE and END ORIGINAL CODE comments, there's the code that I'm not able to migrate, so that you can understand what it does and I may need to make it work on WP.
The other of the code is already working on WP, except for the
request.Content.Headers.Add("ContentType", "multipart/form-data; boundary=" + Boundary);
because, for some reasons, request.Content is null.
So my question is: how can I migrate those 3 lines to WP using HttpClient (or any better way)?
And, as a little side question, why is request.Content null?
EDIT: based on #Johan van der Slikke's answer I've edited my code. It compiles, but the server reports that no file was uploaded, so I guess that there are still some issues.
var stream = new MemoryStream(data);
var streamContent = new StreamContent(stream);
request.Content = streamContent;
request.Content.Headers.Add("ContentType", "multipart/form-data; boundary=" + Boundary);
// Get response
var response = await httpclient.SendAsync(request);
You should wrap your stream in the StreamContent class (a subclass of HttpContent) and send it with the HttpClient using the PostAsync or PutAsync methods.
Edit
You don't need to use HttpRequestMessage.
var stream = new MemoryStream(data);
var streamContent = new StreamContent(stream);
// Get response
var response = await httpclient.PostAsync(streamContent)
Also you don't need to create a MemoryStream with your byte array. You can wrap it in a ByteArrayContent directly.
var response = await httpclient.PostAsync(new ByteArrayContent(data))
Maybe (because I see you using multipart/form-data header) you should use MultipartFormDataContent classes or FormUrlEncodedContentClasses.
You can send multi-part content like this,
var client = new HttpClient();
var content = new MultipartContent();
content.Add(new ByteArrayContent(data));
var response = await client.PostAsync(SubmitUrl, content);
However, I am curious what media type your "PostData" is. You may want to set the content-type header on the ByteArrayContent.

What purposes should I use class StringContent for?

There is StringContent class in System.Net.Http namespace. What purposes should I use class StringContent for?
StringContent class creates a formatted text appropriate for the http server/client communication. After a client request, a server will respond with a HttpResponseMessageand that response will need a content, that can be created with the StringContent class.
Example:
string csv = "content here";
var response = new HttpResponseMessage();
response.Content = new StringContent(csv, Encoding.UTF8, "text/csv");
response.Content.Headers.Add("Content-Disposition",
"attachment;
filename=yourname.csv");
return response;
In this example, the server will respond with the content present on the csv variable.
It provides HTTP content based on a string.
Example:
Adding the content on HTTPResponseMessage Object
response.Content = new StringContent("Place response text here");
Whenever I want to send an object to web api server I use StringContent to add format to HTTP content, for example to add Customer object as json to server:
public void AddCustomer(Customer customer)
{
String apiUrl = "Web api Address";
HttpClient _client= new HttpClient();
string JsonCustomer = JsonConvert.SerializeObject(customer);
StringContent content = new StringContent(JsonCustomer, Encoding.UTF8, "application/json");
var response = _client.PostAsync(apiUrl, content).Result;
}
Every response that is basically text encoded can be represented as StringContent.
Html reponse is text too (with proper content type set):
response.Content = new StringContent("<html><head>...</head><body>....</body></html>")
On the other side, if you download/upload file, that is binary content, so it cannot be represented by string.

Categories

Resources