AJAX Call to MVC5 ActionResult

2019-06-10 07:57发布

问题:

I am trying to figure out what is wrong with the following code:

$(".ReportScore").click(function () {
    $.ajax({
        type: "GET",
        url: "/events/Tournaments/ReportScore",
        success: function() {
            location.reload();
        },
        error: function() {
            alert("The scores were not recorded");
        }
    });
});

When I type the url in the bar, it works without problems, however when I try to do an ajax call I get 404 Page not found error.

To clarify, when I click on the button I Get a popup saying "The scores were not recorded" and on developer tools I get a script error saying Page not found.

I also have a breakpoint in visusal studio on the method itself, but the point is never hit as the method is never called.

Server Side Code:

public async Task<ActionResult> ReportScore()
{
    var a = "abc"
}

var a line is never hit.

EDIT:

I have another ajax call from the same script that works without problems:

$("#InvitedMember").autocomplete({
    source: function (request, response) {
        $.ajax({
            type: "POST",
            url: "/events/Teams/Members",
            data: { id: $("#InvitedMember").val() },
            success: function (data) {
                response($.map(data, function (item) {
                    return {
                        label: item.CustomUrl, value: item.CustomUrl
                    };
                }));
            }
        });
    },
    create: function () {
        $(this).data('ui-autocomplete')._renderItem = function (ul, item) {
            return $('<li>')
                .append("<a><div>" + item.label + "</div></a>")
                .appendTo(ul);
        };
    },
    select: function (event, ui) {
        //you can access ui.item to get the selected item object.
        $("#InvitedMember").val(ui.item.value);
        return false;
    }
});

回答1:

It is not a good idea to hardcode your url's like that. You should always use the Url.Action or Url.RouteUrl html helper methods to build the relative url to the action methods/endpoints you are accessing. These helper methods will take care of correctly building the url regardless of your current page/path.

Also, from your comment,it seems like events is the name of your virtual directory/application name in your IIS. You should not use those in your code to build the urls as it might change based on your deployment. What if you want a a copy of your code deployed to "http://staging.yourSite.com" ?

As long as you use the Url.Action helper method,it will build the correct relative url to your app and you do not need to worry about your IIS virutal directory/application name.

var url = "@Url.Action("ReportScore","Tournaments")";

$.ajax({
    type: "GET",
    url:url,
    success: function (res) {
        alert('success happened');
        //location.reload();
    },
    error: function () {
        alert("The scores were not recorded");
    }
});

The above code will work if you have it in a razor view. But if your ajax call code is in external js file, You may build the relative url to the app root and pass that to your js file and use that to build the url. You can use the @Url.Content("~") to build the url to app root. If you want, you can build the url to specific action method itself.

<script>
    var myApp = myApp || {};  
    myApp.Urls = myApp.Urls || {};
    myApp.Urls.baseUrl = '@Url.Content("~")';   
    myApp.Urls.reportScoreUrl=  '@Url.Action("ReportScore","Tournaments")';  
</script>
<script src="~/Scripts/PageSpecificExternalJsFile.js"></script>

And in your PageSpecificExternalJsFile.js file, you can read it like

var myUrlToUser = myApp.Urls.reportScoreUrl;
alert(myUrlToUser);

or build using the base url.

var myUrlToUser= myApp.Urls.baseUrl+"Tournaments/ReportScore";
alert(myUrlToUser);


回答2:

The problem seems not in your javascript code but your controller action method (if it is indeed how it is written)

public async Task<ActionResult> ReportScore() { var a = "abc" } Your code block doesn't show any return statement, make sure your return value is awaited. i.e. return await "abc"