urnotsam
urnotsam

Reputation: 770

AJAX only works on page refresh

I am writing a web app that allows a user to create questions and assign answers and point values to those answers. I have it set up so the user enters how many questions they want to make and then I pull up all the fields needed for one question. When the user clicks Save & Next button those fields are cleared and they can enter their next question information. I am using AJAX to post the model data to my server each time Save & Next is clicked. My problem is that my AJAX will only run if I allow the page to refresh which I don't want to do.

HTML

<input type="submit" id="next" value="Save & Next" />

Javascript

 $(document).ready(function () {
 $('#next').click(function(e) {

        var model = @Html.Raw(Json.Encode(Model));
        e.preventDefault();

        if (counter <= ques)
        {
            $.ajax({
                url: "/Questions/Create",
                type: "POST",
                data: JSON.serialize(model),
                cache: false,
                success: function (data)
                {

                }
            });
            //counter++;
        }
        else {

        }

    });
});

C# Server-Side

    [HttpPost]
    [ValidateAntiForgeryToken]
    public int Create(QAViewModel qa)
    {
        System.Diagnostics.Debug.WriteLine("madeit");
        if (ModelState.IsValid)
        {
            foreach (var item in qa.questions)
            {
                //add question data into the DB
                db.questions.Add(item);
            }
            foreach (var item in qa.questionAnswers)
            {
                db.answers.Add(item);
            }
            db.SaveChanges();
            return(1);
        }

        return (0);
    }

The real problem comes with e.preventDefault(); If I remove it the code runs and my model data gets added to my database as expected. When e.preventDefault() is added the AJAX code after it is not even executed. I have tried used <input type="button"> since it's default action does not do anything.

Any ideas on why this is happening?

SOLUTION After many hours the solution was to use @Html.AddAntiForgeryToken() on my view. I forgot that I was checking for anti forgery token which did not let the AJAX to post data to my controller action.

Upvotes: 0

Views: 188

Answers (3)

charlietfl
charlietfl

Reputation: 171669

You are using a non existent function JSON.serialize. If you want to convert a javascript object or array to JSON string use JSON.stringify(object)

This issue can easily be found by using your browser console to check for errors thrown

Upvotes: 2

Davide Rossi
Davide Rossi

Reputation: 516

Submit buttons are made to submit content of the form.

When you don't need to submit, you should use a normal button. However, if for any reason you still want to use a submit button, you may want to return false at the end of the method, in order to avoid submit button to do its work.

$(document).ready(function () {
    $('#next').click(function(e) {
        var model = @Html.Raw(Json.Encode(Model));

        if (counter <= ques)
        {
            $.ajax({
                url: "/Questions/Create",
                type: "POST",
                data: JSON.serialize(model),
                cache: false,
                success: function (data)
                {

                }
            });
            //counter++;
        } else {

        }

        return false;
    });
});

DEMO HERE

Upvotes: 1

VRC
VRC

Reputation: 761

A quick and kinda dirty fix is to hold a boolean to use whether u do the prevent default or not.

var preventBoolean = false;
$(document).ready(function () {
$('#next').click(function(e) {

    var model = @Html.Raw(Json.Encode(Model));
    if(preventBoolean)
    {        
         e.preventDefault();
    }
    preventBoolean = true;

    if (counter <= ques)
    {
        $.ajax({
            url: "/Questions/Create",
            type: "POST",
            data: JSON.serialize(model),
            cache: false,
            success: function (data)
            {
                 preventBoolean = false;
            }
        });
        //counter++;
    }
    else {

    }

});
});

I'm not sure where u want to turn it on again but I have set it in the succes. The good solution is binding and unbinding the method but then you have to work with events.

Upvotes: 0

Related Questions