Post JSON with data AND file to Web Api - jQuery / MVC
You can't upload a file(that is arbitrary binary data) with JSON as JSON is a text format. you'll have to use multipart form data.
// create model for controller
var model = new FormData();
model.append('Name', $.trim($contestForm.find('[name="nombre"]').val()) + ' ' + $.trim($contestForm.find('[name="apellido"]').val()));
model.append('Email', $.trim($contestForm.find('[name="email"]').val().toLowerCase()));
model.append('City', $.trim($contestForm.find('[name="cuidad"]').val()));
model.append('Title', $.trim($contestForm.find('[name="title"]').val()));
model.append('Description', $.trim($contestForm.find('[name="description"]').val()));
model.append('CountryCode', 'co');
model.append('Image', $contestForm.find('[name="file-es"]')[0].files[0]); // this has the file for sure
$.ajax({
url: '/Umbraco/api/ControllerName/CreateContestEntry',
type: 'POST',
dataType: 'json',
data: model,
processData: false,
contentType: false,// not json
complete: function (data) {
var mediaId = $.parseJSON(data.responseText); //?
},
error: function (response) {
console.log(response.responseText);
}
});
Rob Scott
Sitecore, Umbraco, C#, APIs, REST, VSTS, Azure DevOps, CI/CD, SCSS, jQuery/JS, Git, Gulp
Updated on April 14, 2020Comments
-
Rob Scott about 4 years
I need to post to an Api Controller w/ JSON (preferably) with ONE request.
The issue is passing data AND a file (image uploaded). My property is coming up empty (null).
I've looked at quite a bit of blogs but can't seem to get the image's data passed.
public class SomeModel { public string Name { get; set; } public string Email { get; set; } public string City { get; set; } public HttpPostedFileBase Image { get; set; } public string Title { get; set; } public string Description { get; set; } public string CountryCode { get; set; } } [HttpPost] public void CreateContestEntry(SomeModel model) { // model.Image is always null // .. get image here - the other properties no issues }
jQuery
// create model for controller var model = { Name: $.trim($contestForm.find('[name="nombre"]').val()) + ' ' + $.trim($contestForm.find('[name="apellido"]').val()), Email: $.trim($contestForm.find('[name="email"]').val().toLowerCase()), City: $.trim($contestForm.find('[name="cuidad"]').val()), Title: $.trim($contestForm.find('[name="title"]').val()), Description: $.trim($contestForm.find('[name="description"]').val()), CountryCode: 'co', Image: $contestForm.find('[name="file-es"]')[0].files[0] // this has the file for sure }; $.ajax({ url: '/Umbraco/api/ControllerName/CreateContestEntry', type: 'POST', dataType: 'json', data: JSON.stringify(model), //data: $('#test-form').serialize(), // tried this and using FormData() processData: false, async: false, contentType: 'application/json; charset=utf-8', complete: function (data) { }, error: function (response) { console.log(response.responseText); } });
Blogs I've looked at:
- File Upload with Additonal Form Data to Web Api from MVC
- http://www.asp.net/web-api/overview/advanced/sending-html-form-data,-part-1
- http://www.asp.net/web-api/overview/advanced/sending-html-form-data,-part-2
- Custom form data with multiple files to Web API controller
When I tried the
FormData
and$('#form1').serialize()
approach, myprovider.FileData
andprovider.FormData
were always empty as well. I removed themodel
param from the method and the breakpoints were hitting when I switched it up.[HttpPost] public void CreateContestEntry() { string root = HttpContext.Current.Server.MapPath("~/App_Data"); var provider = new MultipartFormDataStreamProvider(root); try { // Read the form data. Request.Content.ReadAsMultipartAsync(provider); // This illustrates how to get the file names. foreach (MultipartFileData file in provider.FileData) { // empty } foreach (var key in provider.FormData.AllKeys) { foreach (var val in provider.FormData.GetValues(key)) { // empty } } //return Request.CreateResponse(HttpStatusCode.OK); } catch(Exception ex) { } }
SOLUTION:
Going off of @Musa's answer, here's the Api Controller code. I mapped the NameValueCollection to my model.
[HttpPost] public void CreateContestEntry() { try { // get variables first NameValueCollection nvc = HttpContext.Current.Request.Form; var model = new WAR2015ContestModel(); // iterate through and map to strongly typed model foreach (string kvp in nvc.AllKeys) { PropertyInfo pi = model.GetType().GetProperty(kvp, BindingFlags.Public | BindingFlags.Instance); if (pi != null) { pi.SetValue(model, nvc[kvp], null); } } model.Image = HttpContext.Current.Request.Files["Image"]; } catch(Exception ex) { } }