0

I'm just looking at some Ajax requests in Fiddler whilst testing some exception handling classes and code in my application and I'm not sure my requests are well formed and as they should be.

My Javascript is:

$(function () {
    $('#createentry').submit(function () {
        e.preventDefault();
        $.ajax({
            url: this.action,
            type: this.method,
            dataType: "json",
            data: $(this).serialize(),
            success: function(result) {
                $('#entries-list').append("<li>" + $('#newentry').val() + "</li>");
                $('#newentry').val('').blur();
            },
            error: function (xhr)
            {
                try
                {
                    var json = $.parseJSON(xhr.responseText);
                    alert(json.errorMessage);
                }
                catch (e)
                {
                    alert('something bad happened');
                }
            }
        });
        return false;
    });
});

In Fiddler the request looks like:

Host: localhost:54275
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost:54275/Diary
Cookie: __RequestVerificationToken= <snipped for brevity>
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 216

I would expect the Accept: header to be set to json automatically I guess that's an incorrect assumption on my part, how is this set?

Also if I looks at the result of this in my action method the value is always false:

    [HttpPost, ValidateAntiForgeryToken, JsonExceptionFilter]
    public JsonResult PostNewEntry(DiaryEntryViewModel diaryEntry)
    {
        var req = Request.IsAjaxRequest();

req always = false so my JsonExceptionFilter isn't kicking in and taking care of the error reporting as expected.

Is there also a defined way of forcing only accepting requests correctly setup as Ajax requests in MVC?

0

2 Answers 2

3

I found this bug that is over five years old that says using .ajax() with a dataType of script or JSON would result in the header missing is a feature. But I would imagine Request.IsAjaxRequest() is looking for that exact header.

As a work around you could try doing something like:

$(document).ajaxSend(function (event, request, settings) {
    request.setRequestHeader("X-Requested-With", "XMLHttpRequest");
});

which would append that header to every Ajax call jQuery sends.

Sign up to request clarification or add additional context in comments.

6 Comments

I just tried adding that to my script file and it still isn't appending the header according to Fiddler. I'm also reading elsewhere that dataType: "json", should set the accepts header to "application/json" but that isn't happening either.
I've confirmed that using this header in a request does indeed mean that the Request.IsAjaxRequest() returns true when it finds the X-Requested-With header. Could this be that my JavaSCript actually thinks it's doing some cross-site request so it's pulling this header out?
What is the value of this.action?
Ive just checked the value and it's the fully qualified name of the call action localhost:54275/Diary/PostNewEntry I think this might be what's convincing JQuery it's cross-site. How can I make this relative if my form starts with (Html.BeginForm("PostNewEntry", "Diary", FormMethod.Post, ...
The value will always be an absolute path. The Html.BeginForm() should return a relative path in the HTML. Have you tried a simple $.post() to see if it works? I know it would break some of the JSON responses, but any information is better than nothing.
|
0

After trying pretty much every solution I could find on the web with absolutely no success, I opted to start using the jQuery Form Plugin and I am now getting well formed Ajax requests on the server side.

Download the plugin from the link above and I then replaced my Ajax JavaScript with:

$(document).ready(function () {
    $('#createentry').ajaxForm(function () {
        alert("Thank you for your comment!");
    });
});

After including this script and testing a call to:

Request.IsAjaxRequest();

Now correctly returns true.

Using Firebug to examine the requests being posted the required header that denotes the request as an Ajax request is present:

X-Requested-With XMLHttpRequest

Comments

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.