1

I am having trouble passing a ViewModel between my partial views and the controller.

What I basicly want is to have one ViewModel which is beeing passed through different Views using Jquery and updated dynamicly.

I have a modal dialog wich is using a Fuel UX Wizard. The code for the modal is in a file called "Container" and partial views is beeing loaded into the container.

When the modal is clicked the changed.fu.wizard function is getting called.

$('#uiWizard').on('changed.fu.wizard', function () {
        switch ($('#uiWizard').wizard('selectedItem').step) {
            case 1:
                console.log("step 1");

                $.ajax({
                    url: '@Url.Action("Step1", "Alert")',
                    datatype: "json",
                    type: "POST",
                    contentType: 'application/json; charset=utf-8',
                    beforeSend: function () {
                        $('#container1').html(loadingData());
                    },
                    success: function (data) {
                        $('#container1').html(data);
                    },
                    error: function (data) {
                        $('#container1').html(errorMessage(data));
                    },
                    complete: function () {

                    }
                });
                break;
        }
    });

The controller method looks simplified like this:

[HttpPost]
public PartialViewResult Step1()
{
   TestView model = new TestView();
   return PartialView("Step1", model);
}

So this is basicly just loading the Step1 view into the Container View.

So here is when the issues start. Say that I inn Step.cshtml import the model on top with @model Application.ViewModels.TestView and I use Html helpers on the Step1 page such as checkboxes and Textareas.

When the "Next" button is called again on the wizard the changed method gets called again. (Which is in the Container.cshtml file) I want to pass the Model thats in step1 with Jquery to a controller which takes a ViewModel.

I want the controller to just look like this. Get the model from the View and just pass it on.

So very easily would be just to stringify the Model. This seems to be working in some cases but the problem I am having is that Model is not beeing updated.

$.ajax({
    url: '@Url.Action("Step2", "Alert")',
    datatype: "json",
    data: JSON.stringify('@Model'),
    type: "POST",
    contentType: 'application/json; charset=utf-8'
});

[HttpPost]
public PartialViewResult Step2(TestView model)
{
    return PartialView("Step2", model);
}

This got abit messy but hope it was understandable ;)

EDIT:

Partial Views: What I am thinking about the Partial Views is that I only want to retrieve the ViewModel from the controller. Some Partial Views may change some variables and others may just pass it on.

So on all the partial views I have @model Application.ViewModels.TestView on top. I do not have this on the Container page. (Since its not beeing used here)

Then I can f.ex have a TextArea like this:

<section>
    <div class="textarea textarea-resizable">
        @Html.TextAreaFor(m => m.Text, new { @class = "form-control", rows = 15 })
    </div>
</section>

There is basicly no more code here since the form tags and everything else is in the container view.

From container.cshtml

        <div class="step-content">
            <form class="form-inline" id="fuelux-wizard" method="post">
                <div class="step-pane text-center active" id="step1">
                    <div id="container1"></div>
                </div>
                <div class="step-pane" id="step2">
                    <div id="container2"></div>
                </div>
                <div class="step-pane" id="step3">
                    <div id="container3"></div>
                </div>
                <div class="step-pane" id="step4">
                    <div id="container4"></div>
                </div>
            </form>
        </div>

And the divs are beeing loaded with the change method posted earlier in the success method.

            success: function (data) {
                $('#container1').html(data);
            },
stibay
  • 1,200
  • 6
  • 23
  • 44
  • `data: JSON.stringify('@Model'),` will never pass back your model. It needs to be `data: $('form').serialize(),` –  Jun 09 '15 at 10:48
  • Is this also datatype json? It doesn't seem to understand it. Getting Invalid JSON primitive: Text. And Text is the first variable. – stibay Jun 09 '15 at 11:54
  • `datatype: "json",` is what you receive in the success callback - in you case you don't have one so it can be deleted. You also need to delete `contentType: 'application/json; charset=utf-8',` when using the `serialize()` function. But you need to show the partial view to be able to be sure my comment is correct –  Jun 09 '15 at 11:58
  • Updated the post now. See from EDIT: – stibay Jun 09 '15 at 12:06
  • `data: $('#fuelux-wizard').serialize(),` should work (add a `console.log($('#fuelux-wizard').serialize());` before `ajax(...` to check to its correctly serializing the form controls) –  Jun 09 '15 at 12:20
  • It is serializing it. But it is not adding any quotes around the textfield. So I think that might be the problem? It also seem to be having some issues with the @Html.CheckBoxFor(m => m.BoolA) elements. Since in the HTML it gets rendered twice with a hidden field value. – stibay Jun 09 '15 at 12:53
  • It should not add quotes. And there is no problem with `CheckBoxFor()` - it will all post back and bind correctly (assuming `TestView ` has a property named `Text`) –  Jun 09 '15 at 12:56
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/80060/discussion-between-stibay-and-stephen-muecke). – stibay Jun 09 '15 at 13:02

1 Answers1

2

data: JSON.stringify('@Model') will only post back the fully qualified name of your class, not any values of the model (and even if it did work, it would only post the original values of the model since razor code is parsed on the server before its sent to the client). You need to serialize your form, so the ajax call should be

$.ajax({
    url: '@Url.Action("Step2", "Alert")',
    // datatype: "json",
    data: $('form').serialize(), // update this
    type: "POST",
    // contentType: 'application/json; charset=utf-8'
});

Note that contentType: 'application/json; charset=utf-8' needs to be removed and and datatype specifies the data which is returned by the controller method - which you don't appear to be accessing so it's not necessary

Note also you could also build the form data manually using

data: { Text: $('#Text').val(), AnotherProperty: $('#AnotherProperty').val(), etc },
  • This works great! Thanks so much for your help. Noticed one thing which was really wierd though. If I in create a New ViewModel in step 2 (in the controller) and that method also can reciece the same ViewModel. If i pass inn a ViewModel the model it creates in the return statement (in the controller) doesnt get set. This is as I want it to behave but I find it wierd that the model seems like its beeing set from the controller but doesnt actually gets set in the view. Can show an example of this tomorrow. But wondering if this is inteded behavior. – stibay Jun 09 '15 at 13:50
  • If i understand your comment correctly, that's because the values of `ModelState` have been already set (as part of the binding process) and your html helpers use `ModelState` values (not model values). [This answer](http://stackoverflow.com/questions/26654862/textboxfor-displaying-initial-value-not-the-value-updated-from-code/26664111#26664111) may help to explain it. (If I have misunderstood, then best to ask a new question) –  Jun 09 '15 at 13:56