2

Here is my requirement :

I am designing a page to add a vehicle to the database :

Normal vehicle information [Model - Inventory]

Some other features [Model - IList]

Here is my index.cshtml page

@model Model.ViewModel.VehicleViewModel

<div>
    <div class='col-md-12'>
        <div class="form-group">
            <input id="mainFormSubmit" type="button" value="Save" class="btn btn-default" />
        </div>
    </div>

    @{Html.RenderPartial("~/Views/Shared/_InventoryPartial.cshtml", Model.InventoryVM);}
    @{Html.RenderPartial("~/Views/Shared/_StandardFeaturePartial.cshtml", Model.StandardFeatures);}

</div>


<script type="text/javascript">
    $('#mainFormSubmit').click(function () {
        $('#InventoryForm').submit();
        $("#StandardFeatureForm").submit();
    });
</script>

This is my view model class

public class VehicleViewModel
    {
        public InventoryViewModel InventoryVM { get; set; }
        public IList<StandardFeature> StandardFeatures { get; set; }
    }

The Inventory partial view [_InventoryPartial.cshtml]

@model Model.ViewModel.InventoryViewModel

@{
    var options = new AjaxOptions() { HttpMethod = "Post" };
}

<div class="container">
    <div class="row">
        <div class="col-md-12">

            @using (Ajax.BeginForm("InventorySave", "AddVehicle", options, new { id = "InventoryForm" }))
            {
                <fieldset>
                <legend>Inventory Info</legend>

                    <div class='col-md-6'>
                        <!-- VIN input-->
                        <div class="form-group">
                           @Html.LabelFor(x => x.VIN, new { @class = "col-md-4 control-label" })
                            <div class="col-md-7">
                                @Html.TextBoxFor(x => x.VIN, new { @class = "form-control", @placeholder = "VIN" })
                            </div>
                        </div>
                    </div>
                </fieldset>
            }

The standard feature partial view [_StandardFeaturePartial.cshtml]

==

@model IEnumerable<Model.DomainModel.StandardFeature>

@{
    var options = new AjaxOptions() { HttpMethod = "Post" };
}

<div class="container">
    <div class="row">
        <div class="col-md-12">
            @using (Ajax.BeginForm("StandardFeatureSave", "AddVehicle", options, new { id = "StandardFeatureForm" }))
            {           

When I am clicking on index page SAVE button, only

$('#InventoryForm').submit(); $("#StandardFeatureForm").submit();

last one(StandardFeatureForm) is executing.

Please let me know if this process is correct, and what could be the reason of this issue.

Tech
  • 129
  • 1
  • 1
  • 12

2 Answers2

2

You should not call the submit method twice. Depending of the browser you can face different issues :

  • the form submission causes the browser to navigate to the form action and the submission of the first may prevent the submission of the second
  • The browser could detected there are two requests and discards the first submit.

In your case it will be easier to wrap your two partial views inside a unique form.

@using (Ajax.BeginForm("InventorySave", "AddVehicle", FormMethod.Post, new { id = "InventoryForm" }))
{
    @{Html.RenderPartial("~/Views/Shared/_InventoryPartial.cshtml", Model.InventoryVM);}
    @{Html.RenderPartial("~/Views/Shared/_StandardFeaturePartial.cshtml", Model.StandardFeatures);}
}

However when the partial views render they are not generating the correct name attributes for the larger modelModel.ViewModel.VehicleViewModel you want to use :

public void InventorySave(VehicleViewModel vehicleViewModel)         {}

In this case you should use EditorTempmlate instead of partial views. It's simple to do from your partial views and this post should help you :Post a form with multiple partial views

Basically, drag your partials to the folder ~/Shared/EditorTemplates/ and rename them to match the model name they are the editor templates for.

Finally something like :

@model Model.ViewModel.VehicleViewModel

@using (Html.BeginForm("InventorySave", "AddVehicle", FormMethod.Post, new { id = "InventoryForm" }))
{
   @Html.EditorFor(m => m.InventoryVM);
   @Html.EditorFor(m => m.StandardFeatures});
}
Community
  • 1
  • 1
NicoD
  • 1,179
  • 8
  • 19
  • I tried this, and it makes sense--but why the model I am receiving is null `public void InventorySave(VehicleViewModel vehicleViewModel) {}` – Tech Jul 10 '14 at 13:03
  • This is another issue. When the partial views render they are not generating the correct name attributes for the larger model. I update the post. – NicoD Jul 10 '14 at 13:11
  • I did exactly like that..It is not working..The page is coming blank with that – Tech Jul 10 '14 at 14:01
  • no error ? did you check the network traffic with your browser developpers tools ? (http error ? ) try with a "regular" post instead of ajax like in sample : Html.BeginForm ... – NicoD Jul 10 '14 at 14:16
0

The Ajax.BeginForm helper already has a submit event associated to it which creates an Ajax POST request. When you are manually submitting your form using $('#InventoryForm').submit();, you're calling both and the submit events which can have strange side effects.

There are a few ways around this. Here is one solution

Change your forms to a regular HTML form using the Html.BeingForm helper.

Amend your script to create ajax requests and use the form data

$('#InventoryForm').submit(function(e) {
    e.preventDefault();
    $.post($(this).attr("action"), $(this).serialize(), function(r) {

       //Do something

    });
});

$('#StandardFeatureForm').submit(function(e) {
    e.preventDefault();
    $.post($(this).attr("action"), $(this).serialize(), function(r) {

       //Do something

    });
});

Hope this helps

heymega
  • 9,215
  • 8
  • 42
  • 61