I am trying to upload an image along with some json data inside a MultipartFormDataContent
object. But my webapi is not receiving the requests properly for some reason. Initially the api was rejecting the request outright with a 415 response. To fix this I added an xml formatter for multipart/form-data to WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
config.Formatters.XmlFormatter.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("multipart/form-data"));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
This seemed to work for the most part, I tested it using ARC and it received all of the parts of the multipart, the only issue was the string content didn't appear in the form,it was in the files but I put that down to the request not being formatted as a StringContent
object.
The current issue I am having is that my Xamarin app, when sending the multipart request doesn't seem to be posting anything. When the request hits the API Controller, the content headers are there and everything, but the files and form fields are both empty.
After doing some research it seems that I have to write a custom MediaTypeFormatter
but none of the ones I have found seem to be the one I am looking for.
Here is the rest of my code:
Api Controller:
[HttpPost]
public SimpleResponse UploadImage(Image action)
{
SimpleResponse ReturnValue = new SimpleResponse();
try
{
if (HttpContext.Current.Request.Files.AllKeys.Any())
{
var httpPostedFile = HttpContext.Current.Request.Files["uploadedImage"];
var httpPostedFileData = HttpContext.Current.Request.Form["imageDetails"];
if (httpPostedFile != null)
{
MiscFunctions misctools = new MiscFunctions();
string fileName = User.Identity.Name + "_" + misctools.ConvertDateTimeToUnix(DateTime.Now) + ".jpg";
string path = User.Identity.Name + "/" + DateTime.Now.ToString("yyyy-mm-dd");
string fullPath = path + fileName;
UploadedFiles uploadedImageDetails = JsonConvert.DeserializeObject<UploadedFiles>(httpPostedFileData);
Uploaded_Files imageDetails = new Uploaded_Files();
imageDetails.FileName = fileName;
imageDetails.ContentType = "image/jpeg";
imageDetails.DateCreated = DateTime.Now;
imageDetails.UserID = User.Identity.GetUserId();
imageDetails.FullPath = fullPath;
Stream imageStream = httpPostedFile.InputStream;
int imageLength = httpPostedFile.ContentLength;
byte[] image = new byte[imageLength];
imageStream.Read(image, 0, imageLength);
Image_Data imageObject = new Image_Data();
imageObject.Image_Data1 = image;
using (var context = new trackerEntities())
{
context.Image_Data.Add(imageObject);
context.SaveChanges();
imageDetails.MediaID = imageObject.ImageID;
context.Uploaded_Files.Add(imageDetails);
context.SaveChanges();
}
ReturnValue.Success = true;
ReturnValue.Message = "success";
ReturnValue.ID = imageDetails.ID;
}
}
else
{
ReturnValue.Success = false;
ReturnValue.Message = "Empty Request";
ReturnValue.ID = 0;
}
}
catch(Exception ex)
{
ReturnValue.Success = false;
ReturnValue.Message = ex.Message;
ReturnValue.ID = 0;
}
return ReturnValue;
}
Xamarin App Web Request:
public async Task<SimpleResponse> UploadImage(ImageUpload action)
{
SimpleResponse ReturnValue = new SimpleResponse();
NSUserDefaults GlobalVar = NSUserDefaults.StandardUserDefaults;
string token = GlobalVar.StringForKey("token");
TaskCompletionSource<SimpleResponse> tcs = new TaskCompletionSource<SimpleResponse>();
try
{
using (HttpClient httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
httpClient.DefaultRequestHeaders.Add("Accept", "application/xml");
using (var httpContent = new MultipartFormDataContent())
{
ByteArrayContent baContent = new ByteArrayContent(action.Image.Data);
baContent.Headers.ContentType = new MediaTypeHeaderValue("Image/Jpeg");
string jsonString = JsonConvert.SerializeObject(action.UploadFiles);
StringContent stringContent = new StringContent(jsonString);
stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
using (HttpResponseMessage httpResponse = await httpClient.PostAsync(new Uri("http://10.0.0.89/api/Location/UploadImage"), httpContent))
{
string returnData = httpResponse.Content.ReadAsStringAsync().Result;
SimpleResponse jsondoc = JsonConvert.DeserializeObject<SimpleResponse>(returnData);
ReturnValue.ID = jsondoc.ID;
ReturnValue.Message = jsondoc.Message;
ReturnValue.Success = jsondoc.Success;
}
}
}
}
catch(WebException ex)
{
ReturnValue.Success = false;
if (ex.Status == WebExceptionStatus.Timeout)
{
ReturnValue.Message = "Request timed out.";
}
else
{
ReturnValue.Message = "Error";
}
tcs.SetResult(ReturnValue);
}
catch (Exception e)
{
ReturnValue.Success = false;
ReturnValue.Message = "Something went wrong";
tcs.SetResult(ReturnValue);
}
return ReturnValue;
}