0

I have this ajax call here in a script tag at the bottom of my page. Everything works fine! I can set a breakpoint inside the 'updatestatus' action method in my controller. My server gets posted too and the method gets called great! But when I put the javascript inside a js file the ajax call doesn't hit my server. All other code inside runs though, just not the ajax post call to the studentcontroller updatestatus method.

<script>
$(document).ready(function () {
    console.log("ready!");
    alert("entered student profile page");
});

var statusdropdown = document.getElementById("enumstatus");
statusdropdown.addEventListener("change", function (event) {

    var id = "@Model.StudentId";
    var url = '@Url.Action("UpdateStatus", "Student")';
    var status = $(this).val();
    $.post(url, { ID: id, Status: status }, function (data) {
        // do something with the returned value e.g. display a message?
        // for example - if(data) { // OK } else { // Oops }
    });

    var e = document.getElementById("enumstatus");
    if (e.selectedIndex == 0) {
        document.getElementById("statusbubble").style.backgroundColor = "#3fb34f";
    } else {
        document.getElementById("statusbubble").style.backgroundColor = "#b23f42";
    }
}, false);
</script>

Now I put this at the bottom of my page now.

@section Scripts {
    @Scripts.Render("~/bundles/studentprofile")
}

and inside my bundle.config file it looks like this

bundles.Add(new ScriptBundle("~/bundles/studentprofile").Include(
            "~/Scripts/submitstatus.js"));

and submitstatus.js looks like this. I know it enters and runs this code because it I see the alert message and the background color changes. So the code is running. Its just not posting back to my server.

$(document).ready(function () {
console.log("ready!");
alert("submit status entered");

var statusdropdown = document.getElementById('enumstatus');
statusdropdown.addEventListener("change", function (event) {

    var id = "@Model.StudentId";
    var url = '@Url.Action("UpdateStatus", "Student")';
    var status = $(this).val();
    $.post(url, { ID: id, Status: status }, function (data) {
        // do something with the returned value e.g. display a message?
        // for example - if(data) { // OK } else { // Oops }
    });

    var e = document.getElementById('enumstatus');
    if (e.selectedIndex == 0) {
        document.getElementById("statusbubble").style.backgroundColor = "#3fb34f";
    } else {
        document.getElementById("statusbubble").style.backgroundColor = "#b23f42";
    }
}, false);

});

In the console window I'm getting this error message.

POST https://localhost:44301/Student/@Url.Action(%22UpdateStatus%22,%20%22Student%22) 404 (Not Found)

9
  • 2
    Razor code is not parsed in external files so things like var url = '@Url.Action("UpdateStatus", "Student")'; wont work. You need to define those variables in the main view or store the results in an elements data-* attributes so they can be read in the external file Commented Feb 21, 2015 at 0:00
  • the only place I'm using the id is in a hidden field that I'm setting so that I can obtain the value again on a post. I see that you can't getelementbyid on a hidden field. Any suggestions? Can I pass viewmodel data to my javascript event listener change function? Commented Feb 21, 2015 at 0:14
  • It has nothing to do with hidden fields (although since your using jquery why not use var statusdropdown = $('#enumstatus');). If the script is in a separate file the values of id and url will not be set correctly (as you can see its the text value, not the calculated value) because they include razor code (which is not parsed when the page is loaded) Commented Feb 21, 2015 at 0:20
  • Ok I understand! I can replace the url value with '/Student/updatestatus' no problem because it was hardcoded to begin with. But I need the id that's coming from model.studentid and the only place I'm using it in my view is in a hidden field. So I can't just call document.getelementbyid to get the value, doesn't work on a hidden field. Maybe I don't understand something you're telling me? Commented Feb 21, 2015 at 0:26
  • It does work on a hidden field, and you should not be hard coding the url. Use '@Url.Action("UpdateStatus", "Student")'; as you have done, but put that line in the main view (ditto for var id = "@Model.StudentId";) or assign them to the elements data- attributes. But why are you mixing vanilla javascript and jquery like that - its very difficult to follow. Commented Feb 21, 2015 at 0:32

1 Answer 1

1

Razor code is not parsed in external files so using var id = "@Model.StudentId"; in the main view will result in (say) var id = 236;, in the external script file it will result in var id = '@Model.StudentId'; (the value is not parsed)

You can either declare the variables in the main view

var id = "@Model.StudentId";
var url = '@Url.Action("UpdateStatus", "Student")';

and the external file will be able to access the values (remove the above 2 lines fro the external script file), or add them as data- attributes of the element, for example (I'm assuming enumstatus is a dropdownlist?)

@Html.DropDownListFor(m => m.enumStatus, yourSelectList, "Please select", new { data_id = Model.StudentId, data_url = Url.Action("UpdateStatus", "Student") })

which will render something like

<select id="enumStatus" name="enumStatus" data-id="236" data-url="/Student/UpdateStatus">

Then in the external file script you can access the values

var statusbubble = $('#statusbubble'); // cache this element
$('#enumStatus').change(function() {
  var id = $(this).data('id');
  var url = $(this).data('url');
  var status = $(this).val();
  $.post(url, { ID: id, Status: status }, function (data) {
    ....
  });
  // suggest you add/remove class names instead, but if you want inline styles then
  if (status == someValue) { // the value of the first option?
    statusbubble.css('backgroundColor', '#3fb34f');
  } else {
    statusbubble.css('backgroundColor', '#b23f42');
  };
});
Sign up to request clarification or add additional context in comments.

1 Comment

Yes, either that or add the script just before the closing </body> tag (i.e after the html for all your controls have been rendered)

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.