32

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);
        }
    });

enter image description here

Blogs I've looked at:


When I tried the FormData and $('#form1').serialize() approach, my provider.FileData and provider.FormData were always empty as well. I removed the model 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)
        {

        }
    }
0

1 Answer 1

24

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);
    }
});
Sign up to request clarification or add additional context in comments.

6 Comments

Keep receiving error on var model = new FormData(); Uncaught TypeError: object is not a function. And yes, I commented out my previous model object so I wasn't duplicating the variable.
What browser are you using? Did you define FormData somewhere else in you code?
Chrome - add this js file is huge - searched for FormData() and it pops up a few times, but for other variables defined elsewhere. No methods are named that either
So you found no FormData = ... anywhere? What does console.log(typeof FormData); give you?
I found it - however, the method hit and provider.FormData and provider.FileData are empty. I updated the bottom method to show all the code I have
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.