1

I post $('#myForm').serializeArray() to an ASP.NET MVC (2.0) action. serialized array looks as follows:

filters[0][name]    : gemcolor
filters[0][value]   : Yellow
filters[1][name]    : gemcolor
filters[1][value]   : Green
filters[2][name]    : jcOnly
filters[2][value]   : true
someOtherData       : abc

I want to have that consumed in:

public ActionResult GetData(Filter filter)

class Filter {
    string someOtherData;
    bool jcOnly;
    List<string> gemcolor;
}

I can just dig through FormCollection, but I am looking for a more elegant solution (I suspect it will involve a custom model binder).

THX-1138
  • 21,316
  • 26
  • 96
  • 160
  • What about using JSON? I don't know if jQuery's serialized data will easily be consumed by ASP.NET MVC, but JSON would surely be. – rsenna Jan 26 '11 at 16:46
  • I can't find one-liner to do form->JSON. Am I missing something? I still would like to know the answer to my question, justFMI. – THX-1138 Jan 26 '11 at 16:57
  • jQuery + JSON = [JSON Plugin Encoder](http://plugins.jquery.com/project/JSONEncoder) – rsenna Jan 26 '11 at 17:03
  • 1
    is there a one-liner form->JSON? JSON Plugin Encoder doesn't do form->JSON, it does JS-Object->JSON. I can't find a way to turn a form into JSON with one line of code. Although using JSON probably be easier then custom model binder. – THX-1138 Jan 26 '11 at 17:11

2 Answers2

1

This won't work because the default model binder doesn't expect the data to be formatted like this. Simply use .serialize() instead of serializeArray(). Example:

$.ajax({
    url: '/foo',
    type: 'post',
    data: $('#myForm').serialize(),
    success: function(result) {
        alert('ok');
    }
});

or simplify your life by using the excellent jquery form plugin which allows you to AJAXify existing HTML forms in an elegant manner:

$(function() {
    $('#myForm').ajaxForm(function(result) {
        alert('ok');
    });
});

UPDATE:

After the explanation in your comment here's how you could proceed:

You could use the plugin from this answer which transforms the form elements into an object understandable by the default model binder and could be aggregated with some other information:

$.fn.serializeObject = function()
{
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name]) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};

and then simply:

data: { filters: $('#myForm').serializeObject(), someOtherData: 'foo bar'  }
Community
  • 1
  • 1
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • I anticipate that solution will require custom model binder. – THX-1138 Jan 26 '11 at 16:56
  • I can't use ajaxForm in this case, since data being submitted is not a form-submit-post. It is an AJAX post (done for and by DataTables.Net) – THX-1138 Jan 26 '11 at 16:57
  • @user93422, so you are saying you cannot modify the request strings? If this is the case only a custom model binder can help you here. – Darin Dimitrov Jan 26 '11 at 17:01
  • Ajax data looks like: `data: { JSON.stringify(aoData), filters: $('#myForm').serializeArray() }` replacing `serializeArray` with `serialize` will not help, since I still need to parse query-like string. – THX-1138 Jan 26 '11 at 17:07
  • 1
    @user93422, the information in your last comment should have been provided as part of your question. Please see my update about how you could compose an AJAX request where part of the data comes from a form and other part from somewhere else. – Darin Dimitrov Jan 26 '11 at 17:15
  • @Darin, True. Now I receive two values : filters as JSON and someAtherData as string. How do I bind it to my `Filter` class? (the original question) – THX-1138 Jan 26 '11 at 17:31
  • @user93422, your `Filter` class has a `someOtherData` string property, so that's what the `someOtherData: 'foo bar'` part does. Now you have another boolean property which you could set like this: `jcOnly: true`, and the `gemcolor` collection could be sent as `gemcolor: ['1', '2', '3']`. It is not clear what does the form you are trying serialize and send to the server contains as fields. – Darin Dimitrov Jan 26 '11 at 17:35
0

I know this is old, but how about something like this - this is what I use generically on my pages to submit via ajax:

$(function () {

    @*-- PostAll--*@

    $(".postAll").click(function () {
        var container = $(this).closest(".postGroup");
        var p = {};

        container.find("input[type='text'], input[type='radio']:checked, input:checkbox:checked, textarea").each(function (i, e) {

            p[$(e).attr("name")] = $(e).val();

        });

        container.find('select').each(function (i, e) {

            p[$(e).attr("name")] = $(e).find('option:checked').val();

        });

        $.post($(this).data("url"), p, function (data, status) {
            //Do Some Notification
        })

    });


});

I tend to have html structure as:

  1. Div containing all the form elements
  2. A button with within the div
  3. button with a url attribute with the url

Something like this:

<div class="postGroup">
    <div class="row">
        <div class="col-md-2 col-md-offset-3">
            <input type="text" name="myText" />
        </div>
        <div class="col-md-2">
            <input type="radio" name="myRad" value="A1" />
            <input type="radio" name="myRad" value="A2" />
            <input type="radio" name="myRadTwo" value="A3" />
            <input type="radio" name="myRadTwo" value="A4" />

        </div>
        <div class="col-md-2">
            <input type="checkbox" name="mycheck" value="B1" />
            <input type="checkbox" name="mycheck" value="B2" />
            <input type="checkbox" name="mycheckTwo" value="B3" />
            <input type="checkbox" name="mycheckTwo" value="B4" />
        </div>
        <div class="col-md-2">
            <select name="mySelect">
                <option value="S1">Select 1</option>
                <option value="S2">Select 2</option>
                <option value="S3">Select 3</option>
                <option value="S4">Select 4</option>
            </select>
            <select name="mySelectTwo">
                <option value="R1">Select 1</option>
                <option value="R2">Select 2</option>
                <option value="R3">Select 3</option>
                <option value="R4">Select 4</option>
            </select>
        </div>
    </div>
    <button class="postAll" data-url="/MyEndpoint">click</button>
</div>

Then you can have a normal model to capture what you need. Not sure if this is the best way or anything but I use this a of times.

user3836415
  • 952
  • 1
  • 10
  • 25