Post JSON data through a form in MVC4

11,868

Solution 1

Assuming you want to post data encoded as json using a form and no XHR, I don't think it's out of the box possible.

Forms don't allow many content types. http://www.w3.org/TR/html401/interact/forms.html#form-content-type

If you post json as a string, its probably possible to create a model binder that looks for strings which appear to be json and deal with deserialization there. Not the prettiest thing, especially if this is just for some one off odd situation.

Solution 2

Instead of the manual deserialization, you can catch the form post event and reconstruct your own post, adding the additional JSON object. Here is an example that uses the serializeObject method from this post):

$(document).ready(function () {
    $('form').live('submit', function (e) {
        e.preventDefault();

        var dataToPost = $(this).serializeObject();
        dataToPost.hiddenFieldName = actionModel; //additional object here
        $.ajax({
            type: $(this).attr('method'),
            url: $(this).attr('action'),
            data: JSON.stringify(dataToPost),
            contentType: 'application/json; charset=utf-8',
            success: function (res) {
                //do something...
            }
        });
    });
});
Share:
11,868
Alejo
Author by

Alejo

Updated on October 17, 2022

Comments

  • Alejo
    Alejo over 1 year

    I'm trying to POST a JSON object (a JSON-ified knockout model, if that's of any relevance) to my MVC controller, and have the controller return a new view. To do this, I'm sending the data with a form. The problem is that I would like to have the JSON automatically converted to a model when the controller receives it.

    If I were to use an AJAX call for this,

    var actionModel = new Object();
    actionModel.Controls = ko.toJS(self.controls());
    var json = JSON.stringify(actionModel);
    $.ajax({
        url: "MyController/Preview",
        type: "POST",
        contentType: 'application/json; charset=utf-8',
        cache: false,
        data: json,
        success: function (data) {
        }
    });
    

    ...the JSON object is successfully deserialized and converted into an instance of my model class.

    public ActionResult Preview(ActionModel actionModel) { ... }
    public class ActionModel
    {
        public List<ControlModel> Controls { get; set; }
    }
    

    If I want to do this with a form, I understand that I need to insert the JSON into a hidden input field, but the best I can manage when doing this is to receive the data as a serialized string:

    @using (Html.BeginForm("Preview", "MyController", FormMethod.Post, new { id = "previewForm" }))
    {
        <input type="hidden" id="hiddenFieldName" />
    }
    
    public ActionResult Preview(string hiddenFieldName) { ... }
    

    I could just deserialize it afterwards, but I really would prefer it if MVC could convert it for me, as it would with an AJAX call. Is this possible?

    Thanks.

  • Alejo
    Alejo over 11 years
    I cannot intercept and reconstruct the form's post request, as I need the data to be sent synchronously to the controller. E.g. Form submits data -> controller receives data (ideally serialized into my model class) -> controller returns the data in a new web page.
  • Alejo
    Alejo over 11 years
    Thanks for the input. I guess I'll just send it as a string. It's not the end of the world as I can pretty much return the same JSON back in the new page, but I was hoping I could make the Preview action consistent with the rest of my controller.