0

I have a form in an Asp.net MVC 5 project which has a Submit button. When the Submit button is clicked, I want to do the following:

  1. Perform client=side validation using jQuery on various fields (required fields have been filled, email format is valid, etc...). That part is working fine.

  2. Make an Ajax call that will perform some server side validation by calling an action from the controller and return a JSON response. The response contains a Success property and Errors property which contains a list of errors.

The Success property will return true if no error are found and the Errors property will be null. If errors are found the Success property is returns false and the Errors property contains a list of relevant errors.

I'm calling '\ApplicationForm\Validate' action from my ApplicationForm controller and this part is working fine.

  1. When no errors are found in part 2, I want my form to be submitted as normal and call the '\ApplicationForm\Index' action so that my data can then be added to my database. I cannot get this part to work!!

The Submit button is defined as follows:

<div class="form-group">
  <div>
    <input type="button" id="btnApply" value="Apply" class="btn btn-primary" />
  </div>
</div>

My JavaScript code is defined as follows:

$('#AppllicationForm').submit(function () {
    if (!$(this).attr('validated')) {
        if ($(this).valid()) {
            $.ajax({
                type: "POST",
                data: $(this).serialize(),
                url: "/ApplicationForm/ValidateForm",
                dataType: 'json',
                success: function (response) {
                    $('validationSummary').show();
                    if (response != null && response.success) {
                        console.log('No Validation errors detected');
                        $('#ApplicationForm').attr('validated', true);
                        $('#ApplicationForm').attr('action', '/ApplicationForm/Index')
                            .submit();
                        return true;
                    }
                    else if (response != null && !response.success) {
                        console.log('Validation errors detected');
                        var errors = response['errors'];
                        displayValidationErrors(errors);
                        window.scrollTo(0, 0);
                    }
                    return false;
                },
                error: function (response) {
                    $('validationSummary').hide();
                    console.log(response);
                    return false;
                }
            });
        }
    }
    return false;
});

The above is using a regular button but I've also tried to define its type as Submit but to no avail.

I know similar questions have been posted in the past but I cannot find one that has actually helped me out to find a resolution to my problem, so please bear with me and do not mark this question as a duplicate unless there is an actual question/answer with an actual resolution to my problem. Much appreciated!

The closest scenario I found to what I'm trying to achieve is can be found from this article on SO: Submit a form from inside an ajax success function that checks the values

I've been trying so many different things at this stage but nothing is working out. I either don't get the Index action to be called after the ValidateForm action, or either one or the other action is called or the only Index action is called or my model gets messed up, and the list goes on.

I'm clearly not doing this correctly or missing something but I'm at a complete stand still for now. I'm hoping that it will be something silly that I've missed and hopefully someone will clarify this for me.

Any help would be greatly appreciated.

Thierry
  • 6,142
  • 13
  • 66
  • 117
  • 1
    What is the point of this. Just make a normal submit and check is `ModelState` is valid. If so, save and redirect and if not just return the view so validation errors are displayed. But if you have correctly implemented client side validation and applied validation attributes to your model properties, then the form will not be submitted anyway (the errors will just be displayed) –  Jun 05 '17 at 02:12
  • what you should submit, is the form. in your example article, it also submit a form with a specific ID. while in your case, `$(this)` is referring to button rather than a form – Mark Jun 05 '17 at 02:16
  • And I'm not sure how you can claim any of this is working - in the first part of you script - `$(this)` is referring to the button, not the form, and inside the ajax call its referring to the ajax function, not the form and `data: $(this).serialize(),` would not be sending anything relating to the form to your `ValidateForm` method. –  Jun 05 '17 at 02:19
  • @StephenMuecke The reason I'm doing it this way is that I'm loading various forms dynamically based on a selection from a dropdown in a PartialView and I could not get my `ModelState` to be displayed within the PartialView. Again, I'm learning and maybe I'm going about it the wrong way. – Thierry Jun 05 '17 at 02:21
  • @StephenMuecke Apologies for the confusion. I've been chopping and changing code all night and I've posted the erroneous code where my button is still being used instead of the actual form. I'll update my answer in a second. – Thierry Jun 05 '17 at 02:23
  • Yes, you going about it the wrong way - your can use partials fine -they just need the correct name attributes for binding, and you need to re-parse the `$.validator` when loaded so that you get client side validation. Your main view would just need to include some conditional statements to load the relevant partials if your did need to return the view in the POST method. –  Jun 05 '17 at 02:28
  • @StephenMuecke ok, I'll read about the $.validator tomorrow and see how I get on. Thanks for the feedback. – Thierry Jun 05 '17 at 02:34
  • @StephenMuecke, I thought I'd give it a quick shot before hitting the sack (4am here), and while I haven't looked at the `$.validator` yet, I thought I'd do the validation in my `Index` action and return the relevant `PartialView` with the relevant `Form` and `Model` but this is actually messing up my entire page where the `PartialView` returns appears to overwrite the main page and it loses all its formatting. Any suggestions? – Thierry Jun 05 '17 at 03:03
  • Refer [this answer](https://stackoverflow.com/questions/31768946/required-field-validations-not-working-in-jquery-popup-mvc-4/31769058#31769058) for an example of re-parsing the validator. And get some sleep! –  Jun 05 '17 at 03:03
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/145833/discussion-between-stephen-muecke-and-thierry). –  Jun 05 '17 at 03:04

4 Answers4

0

Try it out :

$('#btnApply').click(function (e) {
alert('submit');
e.preventDefault();
var form  = $('form'); // change selector your form
if (!form.attr('validated')) {
    if (form.valid()) {
        $.ajax({
            type: "POST",
            data: form.serialize(),
            url: "/ApplicationForm/ValidateForm",
            dataType: 'json',
            success: function (response) {
                console.log('response received.');
                if (response != null && response.success) {
                    console.log('No validation errors detected.');
                    form.attr('validated', true);
                    form.attr('action', '/ApplicationForm/Index')
                        .submit();
                } else if (response != null && !response.success) {
                    console.log('Validation errors detected.');
                    var errors = response['errors'];
                    displayValidationErrors(errors);
                    window.scrollTo(0, 0);
                }

            },
            error: function (response) {
                console.log(response);
                $('validationSummary').hide();
            }
        });
    }

}

});

Le Hung
  • 51
  • 1
  • 3
  • I've tried what you suggested before, but this doesn't call my `ValidateForm` at all. It jumps straight into the `Index` action which is the action assigned to my `BeginForm`. – Thierry Jun 05 '17 at 02:37
0

Please try it out:

    $('#btnApply').on('click', function (e) {
    e.preventDefault();
    var form = $( "#AppllicationForm" );
    if (!form.attr('validated')) {
        if (form.valid()) {
            $.ajax({
                type: "POST",
                data: $(this).serialize(),
                url: "/ApplicationForm/ValidateForm",
                dataType: 'json',
                success: function (response) {
                    $('validationSummary').show();
                    if (response != null && response.success) {
                        console.log('No Validation errors detected');
                        form.attr('validated', true);
                        form.submit();
                        return true;
                    }
                    else if (response != null && !response.success) {
                        console.log('Validation errors detected');
                        var errors = response['errors'];
                        displayValidationErrors(errors);
                        window.scrollTo(0, 0);
                    }
                    return false;
                },
                error: function (response) {
                    $('validationSummary').hide();
                    console.log(response);
                    return false;
                }
            });
        }
    }
    return false;
});

Your form action attribute will be '/ApplicationForm/Index'. When you click on the button, you make the validation and if everything is OK, then submit the form.

  • Didn't work. Don't understand why as you would think it would but as I said to @NikunjPatel, it jumps straight into the Index and skips the 'ValidateForm' action altogether. – Thierry Jun 05 '17 at 15:15
0

Please check below solution :

  $('#btnApply').on('click', function (event) {
        if ($('form').valid()) {
            event.preventDefault();
            $.ajax({
                type: "POST",
                data: $(this).serialize(),
                url: "/ApplicationForm/ValidateForm",
                dataType: 'json',
                success: function (response) {
                    $('validationSummary').show();
                    if (response != null && response.success) {
                        console.log('No Validation errors detected');
                        $('#ApplicationForm').attr('validated', true);
                        $('form').submit(); // Here form will be submmited to Index action.
                        return true;
                    }
                    else if (response != null && !response.success) {
                        console.log('Validation errors detected');
                        var errors = response['errors'];
                        displayValidationErrors(errors);
                        window.scrollTo(0, 0);
                    }
                    return false;
                },
                error: function (response) {
                    $('validationSummary').hide();
                    console.log(response);
                    return false;
                }
            });
    });

And decorate your ValidateForm method with [HttpPost] attribute.

Nikunj Patel
  • 249
  • 3
  • 13
0

I thought I'd share my solution as I ended up hiring a freelancer to have a look at it as I was under time constraint and could not afford to spend any more time on this.

How did it fix it? He added a second ajax call from within the first one. The annoying (and costly!) part is that I did try this but I had one important missing line i.e. var formValidated = $('#AppllicationForm').serialize();.

After these changes were made, I just had to rejig some of my logic regarding which div should be displayed and/or hidden but bar that it was pretty standard stuff.

Here's the final code that worked as expected:

$('#AppllicationForm').submit(function () {
    if ($(this).valid()) {
        $.ajax({
            type: "POST",
            data: $(this).serialize(),
            url: "/ApplicationForm/ValidateForm",
            dataType: 'json',
            success: function (response) {
                if (response != null && response.success) {
                    var formValidated = $('#AppllicationForm').serialize();
                    $.ajax({
                        url: '/ApplicationForm/Index',
                        data: formValidated,
                        type: 'POST',
                        success: function (result) {
                            $('#mainDiv').hide();
                            $('#Congrats').show();
                        }
                    });
                    return true;
                }
                else if (response != null && !response.success) {
                    var errors = response['errors'];
                    displayValidationErrors(errors);
                    window.scrollTo(0, 0);
                }
                return false;
            },
            error: function (response) {
                $('validationSummary').hide();
                return false;
            }
        });
    }
    return false;
});

Hope this helps others.

Thierry
  • 6,142
  • 13
  • 66
  • 117