0

I'll preface this with I'm still new to JavaScript. So problem is in a larger application, our controller is passing in a list of information to the view where certain JavaScript functions rely on certain ViewModel properties. I've written a simple application to hopefully illustrate what I'm getting at.

Below is a sample controller that's passing in List to the Index page:

    public ActionResult Index() {
        List<int> activeIds = new List<int>();
        SqlConnection sqlConn = new SqlConnection(connection_String);

        sqlConn.Open();

        string sqlStr = "SELECT * FROM dbo.[JS-Test] WHERE Active = 1";
        SqlCommand sqlCmd = new SqlCommand(sqlStr, sqlConn);
        SqlDataReader sqlDR = sqlCmd.ExecuteReader();

        if(sqlDR.HasRows) {
            while (sqlDR.Read()) {
                activeIds.Add((int)sqlDR["ID"]);
            }
        }

        sqlDR.Close();
        sqlCmd.Dispose();
        sqlConn.Close();

        return View(activeIds);
    }

This returns the current "active" items in the database. The (rough) view is as follows...

@model List<int>

@{
    ViewBag.Title = "Index";
}

<p>Current Recognized Count: @Model.Count() </p>
<a href="#" id="printBtn">Print</a>

<script>
$(document).ready(function () {
    $('#printBtn').click(function () {

        var numberOfActiveIds = @Model.Count();

        $.ajax({
            type: "POST",
            url: "/Home/PostResults",
            data: { ids: numberOfActiveIds},
            success: function (results) {
                if(results == "Success") {
                    window.location.href = '/Home/Results';
                }
            }
        });
    });
});
</script>

The issue is getting the current number of active items from the database when the button is clicked. Let's say that the user remains idle on the page after it loads for a few minutes. When their page originally loaded, the model returned 5 items listed as active... but while they've been waiting 3 additional items were switched to active in the database for a total of 8. However, when the user finally clicks the button it'll submit 5 items instead of the current 8.

I'm unable to run the query to get the current number of active items in the "/Home/PostResults" ActionResult due to the nature of how the larger application is set up. Is there a way I could refresh the page (getting the updated model) before the rest of the function carries out using values of the refreshed model?

If you have any additional questions, please let me know and I will gladly comply. I've looked at other questions and answers on SO but I haven't found one that quite works for my situation. Thanks!


Edit #1

So, I've added this function to the Home controller which just returns the list count as Json.

    public ActionResult GetIds(){
        List<int> activeIds = new List<int>();
        SqlConnection sqlConn = new SqlConnection(connection_String);

        sqlConn.Open();

        string sqlStr = "SELECT * FROM dbo.[JS-Test] WHERE Active = 1";
        SqlCommand sqlCmd = new SqlCommand(sqlStr, sqlConn);
        SqlDataReader sqlDR = sqlCmd.ExecuteReader();

        if (sqlDR.HasRows) {
            while (sqlDR.Read()) {
                activeIds.Add((int)sqlDR["ID"]);
            }
        }

        sqlDR.Close();
        sqlCmd.Dispose();
        sqlConn.Close();

        return Json(activeIds.Count());
    }

The view script now looks like this...

<script>
$(document).ready(function () {
    $('#printBtn').click(function () {

        var numberOfActiveIds = @Model.Count();

        $.ajax({
            type: "GET",
            url: "/Home/GetIds",
            success: function(response) {
                numberOfActiveIds = response;

                $.ajax({
                    type: "POST",
                    url: "/Home/PostResults",
                    data: { ids: numberOfActiveIds},
                    success: function (results) {
                        if(results == "Success") {
                            window.location.href = '/Home/Results';
                        }
                    }
                });
            }
        });
    });
});
</script>

I'm currently getting the following error...

Failed to load resource: the server responded with a status of 500 (Internal Server Error)


Edit #2

I had to set the JsonRequestBehavior to AllowGet for it to work properly. Thanks again, everyone!

7
  • "Is there a way I could refresh the page". Sure but it won't do what you want it to do. If you refresh the page your POST will be canceled. Can't you expose a method on your controller to allow you to GET the current "actives" via an ajax call? Commented Jul 6, 2017 at 13:52
  • @gforce301 I've tried that but I don't think I set that up correctly and wasn't sure if that was good practice or possible. If it is, then I think that's the best route to go. I can try to set it up again and post what I've written to see if any syntax or flow errors are apparent? Thanks for the response! Commented Jul 6, 2017 at 13:56
  • Why do you use AJAX? AJAX is used for asynchronous requests, but in success event handler you use synchronous redirect to another page. Commented Jul 6, 2017 at 14:00
  • @Alexander Unfortunately I don't have a clear answer for that, that's just the way the main application is set up. I'm just tasked with fixing a bug that wasn't posting the current information it needed from the model. Commented Jul 6, 2017 at 14:09
  • The MVC concept is following: data is loaded to model, model is passed to view and view is passed to client. Thus, you need to make the query to database on server-side when user send request to Results action of Home controller. No other way! Commented Jul 6, 2017 at 14:21

2 Answers 2

1

gforce301 mentioned to GET the current actives via an ajax call to an additional, separate method making the query to the database and THEN ajax post the returned "actives". Is that possible?

Yes this is possible. That's why I mentioned it. Irregardless of other peoples opinions on how they think you should do this, I understand that you may be limited on why you can't do it their way even if they don't.

The code below is a restructuring of your code. It chains 2 ajax calls together, with the second one depending on the success of the first. Notice the comment block in the success handler of the first ajax call. Since I don't know what the response will be, I can't fill in the part on how to use it. This accomplishes your goal of having the user only make a single button click.

<script>
$(document).ready(function () {
    $('#printBtn').click(function () {

        var numberOfActiveIds = @Model.Count();

        $.ajax({
            type: 'GET',
            url: '/path/to/get/activeIds',
            success: function(response) {
                /*
                    Since I don't know the structure of response
                    I have to just explain.

                    use response to populate numberOfActiveIds

                    now we just make our post ajax request.
                */

                $.ajax({
                    type: "POST",
                    url: "/Home/PostResults",
                    data: { ids: numberOfActiveIds},
                    success: function (results) {
                        if(results == "Success") {
                            window.location.href = '/Home/Results';
                        }
                    }
                });
            }
        });


    });
});
</script>
Sign up to request clarification or add additional context in comments.

3 Comments

I've edited my post above trying something similar to this to get it working. This is exactly what I'm looking for but it isn't quite working at the moment.
Status 500 is a server error. You need to trace that down and find out whats wrong.
Got it! I had to set the JsonRequestBehavior to AllowGet. Thanks again!
0

I can give you an idea, i hope it can help,

run another ajax 1st on btnclick to get the data(or datat count) again, if the record count is greater then current then update the view and don't PostResults and if its same then just PostResults

on ajax success you can reload the data or view and on failure(when no new record) just do PostResults

6 Comments

I thought about that approach, but it's ideal to have it all be done with one button click rather than having them click it twice if they happened to have an outdated model. Going of what you said, though, is there a way I could get the data count again and pass that to the javascript function to then pass it into the PostResult? That's what I'm looking for directly. Thanks for the input!
one other way is you reload your ajax after some time interval.
either do it on click or run an ajax after every timeinterval (for example 30 seconds) and get the count and update the count, and when the btn is clicked,PostResults it will have the last count . but this is not a good solution because the time between intervals and PostResults can have the same issue again of new active record .
why are you redirecting in ajax, if you are redirecting then you don't need ajax, ajax is used when you don't want to reload or redirect.
As I mentioned above I unfortunately don't have a good answer for that, that's just the way the main application is set up. I'm just tasked with fixing a bug that wasn't posting the current information it needed from the model.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.