0

I create a survey. For whole survey I have only View and for every question partial view. Also I have a pagination. All these demonstrated in the picture below. enter image description here
Now people can post the form (whole question) to server using GetAnswersMulti method. (I need the form be posted asynchronously). I want to add a feature - when person see the last not answered question - button changes from Answer to Answer and exit. I suppose to do it by removing one button and add another with specific Url. The problem is - server should check if this question is last. I try to call corresponding method in controller asynchronously and get the returned value. I tried much from SO and there is what I came to:
View

<script>
    function isLast(data) {
        $.ajax({
            type: "POST",
            url: "@Url.Action("Survey", "IsLastQuestion")",
            data: { idQuestion: data },
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (msg) {
                alert("success");
                if (msg == "True") {
                    $(".submitbutton").remove();
                }
            },
            error: function (e) {
                alert("Fail");
            }
        });
    }
</script>

@using (Html.BeginForm("GetAnswersMulti", "Survey", FormMethod.Post))
{
    <input value="Ответить" type="submit"
           class="btn btn-default submitbutton"
           onclick="isLast(@Model.FirstOrDefault().IdQuestion);" />
}

Controller

[HttpPost]
public ActionResult IsLastQuestion(int idQuestion)
{
    Question question = Manager.GetQuestion(idQuestion);
    List<Question> questions = Manager.SelectQuestions(question.idAnketa);
    if (questions.Count == Manager.GetCountQuestionsAnswered(question.idAnketa, SessionUser.PersonID))
        return new JsonResult() { Data = true };
    else
        return new JsonResult() { Data = false };
}
[HttpPost]
public void GetAnswersMulti(List<PossibleAnswerVM> possibleAnswers)
{
    List<Answer> answers = new List<Answer>();
    foreach (PossibleAnswerVM possibleAnswer in possibleAnswers)
    {
        Answer answer = new Answer();
        answer.datetimeAnswer = DateTime.Now;
        answer.idOption = possibleAnswer.IdOption;
        answer.idPerson = SessionUser.PersonID;
        if (possibleAnswer.IsChecked)
        {
            if (IsValid(answer))
                answers.Add(answer);
        }
    }
        Manager.SaveAnswers(answers,possibleAnswers.FirstOrDefault().IdQuestion, SessionUser.PersonID);
}

Now method in controller is called and idQuestion is passed. Method in controller returns true (when it IS the last question). Then I get fail in js code. Help me with this please. I searched 2 days through SO but didn't find anything that works for me.

Vitalii Isaenko
  • 941
  • 1
  • 14
  • 37
  • What are you trying to do? Why are you combining both `Ajax.BeginForm()` and jquery ajax? You `$.ajax` calls the `Survey` method in `IsLastQuestionController` (you have the parameters the wrong way around) and it does not even pass a value for `idQuestion` And what is your `GetAnswersMulti()` method in `SurveyController`? –  May 27 '16 at 06:17
  • @StephenMuecke Sorry, I edited answer and now pass parameter to function. I tried to do all things in controller method (called by submit) and couldn't cope with it too. I asked the question [here](http://stackoverflow.com/questions/37439006/why-i-can-not-call-method-from-another-one-in-the-same-controller) and people adviced me to follow this method as far as I understood. – Vitalii Isaenko May 27 '16 at 06:24
  • Your not passing anything - all you have is `data: "{}",` And I have never seen that question you linked to let alone give you any advice on it. Its impossible to understand what your trying to do here. (and you edit now calls a `isLast2()` function which does not even exist) –  May 27 '16 at 06:28
  • @StephenMuecke they adviced by sending a link to another question. I need to post form via ajax and at the same time to check if this question is last one. If so - remove the button. – Vitalii Isaenko May 27 '16 at 06:31
  • You need to edit your question to explain what your trying to do (nothing in your code makes any sense) –  May 27 '16 at 06:33
  • @StephenMuecke I have specified, thank you. – Vitalii Isaenko May 27 '16 at 06:40
  • I gues that your condition will always fail, cause you run ajax request and it works async. Just use your debug and check is your method in controller are calling and than put break point in browser and check how your js-method works. In this case I update my answer again )) – dantey89 May 27 '16 at 06:49
  • @dantey89 Thanks) Controller is called and `idQuestion` is passed. Method in controller returns true. Then I get fail in js code. Why can it fail? Can't it get the `msg`? – Vitalii Isaenko May 27 '16 at 07:05
  • 1
    @VitaliiIsaenko, You have not explained anything in the question. Sorry to be harsh, but almost every line of code in you question has errors and nothing could possibly work. If you do not clearly explain what is is that view is for and what is is that you trying to achieve, no one can give you a correct answer. –  May 27 '16 at 07:11
  • @VitaliiIsaenko did you put your condition in "success:" block? – dantey89 May 27 '16 at 07:11
  • @dantey89 yes, I will edit the question and show my current code. But I see Fail in `alert()`. – Vitalii Isaenko May 27 '16 at 07:20
  • try this **return new JsonResult() { Data = true}** and than **if (msg == "True") {$(".submitbutton").remove();** – dantey89 May 27 '16 at 07:28
  • @dantey89 also didn't help.. I try to reach success block any way but nothing helps. Maybe something wrong in `IsLastQuestion()` method? – Vitalii Isaenko May 27 '16 at 07:45
  • @VitaliiIsaenko _Maybe something wrong in IsLastQuestion() method?_ Yes **EVERYTHING** (and all the other code as well). Edit your question to explain what your wanting do do so these and other users stop wasting their time –  May 27 '16 at 07:49
  • you can write **error: function (e) {console.log(e);}** to check what is your error – dantey89 May 27 '16 at 07:51
  • Why are you using the `WebMethod` attribute on your action? – Dennis Wanyonyi May 27 '16 at 07:57
  • @DennisWanyonyi found that at some SO answer. Suppose for saying that this method can be used by js. – Vitalii Isaenko May 27 '16 at 07:59
  • `[WebMethod]` attribute is used to expose a method as part of an XML Web Service, [see here](https://msdn.microsoft.com/en-us/library/byxd99hx%28v=vs.90%29.aspx). You instead need the `[HttpPost]` attribute since you are making an ajax post. – Dennis Wanyonyi May 27 '16 at 08:03
  • @StephenMuecke I tried to explain the problem deeply, hope it will help – Vitalii Isaenko May 27 '16 at 08:17
  • @VitaliiIsaenko, I have just seen your edit and its a bit clearer now. But its late here and I will add an answer in the morning. But your need to show your `GetAnswersMulti()` method also. –  May 27 '16 at 10:26
  • @StephenMuecke thank you, I will surely add. – Vitalii Isaenko May 27 '16 at 10:39
  • @VitaliiIsaenko, Your code is still not making any sense and you have changed the code so may times based on various comments (many of them wrong) that its hard to understand what you trying to do. Previously you had a `Ajax.BeginForm()` to call a method which I assume you wanted to save the question/answer and return a partial view of the next question/answer. –  May 28 '16 at 03:11
  • But the `GetAnswersMulti()` method does not even return anything, not to mention that the data you submit does not even have a relationship to the question (`PossibleAnswerVM ` should not contain a property `QuestionId` so even your view models are wrong). You need to re-think every thing your doing here, and there is no need to make a separate ajax call to check if this is the last question (when you load the 'next' question, you can check it then and pass back a value to the client indicating if its the last one). –  May 28 '16 at 03:19
  • @StephenMuecke You are right about view model, I was forced to do it because could not send this data from controller back to view (because of ajax). Yes I would like to use `Ajax,BeginForm()` and you are right I removed it due to some answers. The [post](http://stackoverflow.com/questions/37439006/why-i-can-not-call-method-from-another-one-in-the-same-controller) that I sent you has the original question but nobody could help me (or understand) and I changed the route. If I could send form asynchronously to `GetAnswersMulti()` and return data I would chose this way but I can not cope with it. – Vitalii Isaenko May 28 '16 at 07:14
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/113201/discussion-between-stephen-muecke-and-vitalii-isaenko). –  May 28 '16 at 07:17

4 Answers4

1

Maybe better to use Html.Beginform() and use this script:

       <script>
            function isLast(data) {

                $.ajax({
                    type: "POST",
                    url: "@Url.Action("Survey", "IsLastQuestion")",
                    data: { idQuestion : data},
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: function (msg){
                        alert($.parseJSON(msg.d));
                        if (msg == "True") {
                           $(".submitbutton").remove();
                }
                    },
                    error: function (e) {
                        alert("Fail");
                    }
                });

            }
        </script>

@using (Html.BeginForm("GetAnswersMulti", "Survey", FormMethod.Post)
<input type="text" id="commentText" placeholder="Введите коментарий"/>
        <input value="Ответить" type="submit"
               class="btn btn-default submitbutton"
               onclick="isLast(@Model.FirstOrDefault().IdQuestion);" />
    }
dantey89
  • 2,167
  • 24
  • 37
1

In order for your action to return Json, then the return type of the action needs to be Json. Since the action returns a boolean value (true or false), then it is not considered as an action method. It needs to return an ActionResult type like so

public ActionResult IsLastQuestion(int idQuestion)
 {
Question question = Manager.GetQuestion(idQuestion);
List<Question> questions = Manager.SelectQuestions(question.idSurvey);
if (questions.Count == Manager.GetCountQuestionsAnswered(
    question.idSurvey,SessionUser.PersonID))
    return Json(new{ d = true});
else
    return Json(new{ d = false});
}

Notice that when I return Json like so return Json(new{ d = true});, there is an anonymous variable d which is the boolean value you will check in your success function like this

success: function (msg){
                    alert($.parseJSON(msg.d));
                    if (msg.d === true) {
                       $(".submitbutton").remove();
            }
                    else if(msg.d == false){
      // Do something if false retured.
     }
    }
Dennis Wanyonyi
  • 368
  • 1
  • 5
  • 18
1

Can you try like this?

[HttpGet]
public ActionResult IsLastQuestion(int idQuestion)
{
    Question question = Manager.GetQuestion(idQuestion);
    List<Question> questions = Manager.SelectQuestions(question.idSurvey);
    if (questions.Count == Manager.GetCountQuestionsAnswered(question.idSurvey, SessionUser.PersonID))
        return Content("True", "application/json" );
    else
        return Content("False", "application/json" );
}

In your ajax call-

    function isLast(data) {
    $.ajax({
        type: "GET",
        url: "@Url.Action("Survey", "IsLastQuestion")",
        data: { idQuestion: data },
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (result)
        {
            //check the value inside result here..
        },
        error: function (e) {
            alert("Fail");
        }
    });
}
Souvik Ghosh
  • 4,456
  • 13
  • 56
  • 78
  • Do you mean with `bool` method type? I tried, didn't help. And with `[HttpPost]` attribute too. – Vitalii Isaenko May 27 '16 at 08:21
  • Looks like some problem with the parameter. Can you check if your isLast() function gets hit by the button click? Can you try removing the data property and the method parameters (just try calling the function without parameters)? – Souvik Ghosh May 27 '16 at 08:26
  • Parameter is passed and the function also calls method in controller with corresponding value of parametr. But, probably it can't take the `msg` from method in controller or something else. – Vitalii Isaenko May 27 '16 at 08:31
  • Again I have alert with Fail. – Vitalii Isaenko May 27 '16 at 09:26
  • Since you are just querying your Controller by passing a single parameter value, you can do it by 'GET'. I have edited my answer. Please check if the value from Controller Action method is passed to ajax success. – Souvik Ghosh May 27 '16 at 12:34
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/113150/discussion-between-vitalii-isaenko-and-souvik-ghosh). – Vitalii Isaenko May 27 '16 at 13:22
  • Hi.. Sorry I came back after the weekend. I did not see your comments meanwhile. Let me know if you are still facing the issue and we can go through this over a chat today.. – Souvik Ghosh May 30 '16 at 04:23
0

Parameter is needed in IsLastQuestion function and you dont pass it in script.

function isLast(parameter) {
    $.ajax({
        type: "POST",
        url: "@Url.Action("Survey", "IsLastQuestion")",
        data: "{parameter}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (msg){
            alert($.parseJSON(msg.d));
        },
        error: function (e) {
            alert("Fail");
        }
    });
    if (isLast2 == true) {
        $(".submitbutton").remove();
    }
}
Tuto
  • 36
  • 5