1

First off, sorry about the vague title but this is an issue which has become nothing short of a nightmare for me over the past few days. From time to time I will encounter this issue but I have never found any SO threads or questions posted anywhere resembling my issue and how to address it.

I'm using an Ajax.BeginForm in my view (with no partial views). Upon submitting the form, the action method on my controller will be hit fine, and code runs until the end before returning a HttpStatusCodeResult.

The action will then be hit repeatedly immediately again (with no consistency of how many times), before the Ajax call stops (it shows ABORTED in Firebug) and the client receives a blank error with the error code being 'error'.

Firebug > Net tab. Ajax call is Aborted

Inspecting the net tab of firebug gives me virtually nothing to go on, and the $(document).ajaxError() global handler also gives me no useful information.

Console output of logging parameters passed to ,ajaxError

I have access to IISExpress trace file logs, but I cannot decipher any useful information (if someone could point me to a location that would be fantastic).

I have updated (via NuGet) the jQuery, unobstrusive ajax, validate, unobtrusive validate packages and the issue persists. There are references to jQuery and the others only once on my page (so no duplicate event handlers).

This is an issue which has happened using MVC 4 and 5, and also across both Firefox and Chrome. Chrome dev tools reveals similar information (nothing useful).

I have no event handlers attached to the form in my Javascript. The only submitting is being done by the Ajax.BeginForm.

For reference, my view:

@using Project.Models
@model LoginInfo

<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Login</title>
<script src="~/Scripts/jquery-2.2.0.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<script src="/Scripts/jquery.validate.min.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.min.js"></script>
<script src="~/Content/Scripts/login.js"></script>
<script>
    $('html').removeClass('nojs');
</script>
</head>
<body>
<div id="container">
    @using (Ajax.BeginForm("Ajax", "Login", new AjaxOptions { OnBegin = "submit", OnComplete = "response" }))
    {
        <img id="logo" src="~/Content/Images/Main.png" alt="" />
        <table>
            <tr>
                <td>
                    @Html.LabelFor(x => x.serverHost)
                </td>
                <td>
                    @Html.TextBoxFor(x => x.serverHost, new { placeholder = "domain", required = "required" })
                </td>
            </tr>
            <tr>
                <td>
                    @Html.LabelFor(x => x.instanceName)
                </td>
                <td>
                    @Html.TextBoxFor(x => x.instanceName, new { placeholder = "company", required = "required" })
                </td>
            </tr>
            <tr>
                <td>
                    @Html.LabelFor(x => x.username)
                </td>
                <td>
                    @Html.TextBoxFor(x => x.username, new { placeholder = "Username", required = "required" })
                </td>
            </tr>
            <tr>
                <td>
                    @Html.LabelFor(x => x.password)
                </td>
                <td>
                    @Html.PasswordFor(x => x.password, new { placeholder = "Password", required = "required" })
                </td>
            </tr>
        </table>
        <table>
            <tr>
                <td id="remembertd">
                    @Html.LabelFor(x => x.remember, "Remember me")
                    @Html.CheckBoxFor(x => x.remember, new { @checked = Model.remember })
                </td>
                <td>
                    <input id="submit" type="submit" value="Connect" />
                </td>
            </tr>
        </table>
    }
</div>
</body>
</html>

My controller / action:

[AllowAnonymous]
    public class LoginController : Controller
    {
        public ActionResult Index()
        {
            return View(new LoginInfo());
        }

        [ValidateInput(true)]
        public ActionResult Ajax(LoginInfo info)
        {
            HttpStatusCodeResult result = new HttpStatusCodeResult(200);

            if (!ModelState.IsValid)
            {
                result = GetFailedResult(new ModelStateInvalidException(), Reason.ModelStateInvalid);
            }
            else
            {
                try
                {
                    var i = 0;

                    var j = 10 / i;

                }
                catch (Exception ex)
                {
                    result = GetFailedResult(ex, Reason.Unhandled);
                }
            }

            return new HttpStatusCodeResult(result.StatusCode, result.StatusDescription);
        }

        private HttpStatusCodeResult GetFailedResult(Exception ex, Reason reason)
        {
            HttpStatusCode httpErrorCode = HttpStatusCode.InternalServerError;
            String errorMessage = String.Empty;

            //Trace
            RemotingHelper.Trace("Login attempt failed with message: " + ex.Message + "\n----------");

            //Get message/code
            switch (reason)
            {
                case Reason.IncorrectInstanceName:
                case Reason.IncorrectServerHost:
                case Reason.IncorrectServerHostPort:
                case Reason.IncorrectUsernameOrPassword:
                    httpErrorCode = HttpStatusCode.Forbidden;
                    errorMessage = "Could not connect using the provided details.";
                    break;

                case Reason.Offline:
                    httpErrorCode = HttpStatusCode.ServiceUnavailable;
                    errorMessage = "Could not establish connection with the server.";
                    break;

                case Reason.LicenseMissing:
                    httpErrorCode = HttpStatusCode.InternalServerError;
                    errorMessage = "There was a problem with your license.\nPlease contact an administrator.";
                    break;

                default:
                    httpErrorCode = HttpStatusCode.InternalServerError;
                    errorMessage = "There was an error attempting to log in.\nPlease contact an administrator.";
                    break;
            }

            //Return
            return new HttpStatusCodeResult(httpErrorCode, errorMessage + ":" + ((Int32)reason).ToString());
        }
    }

Relevant models:

public enum Reason
    {
        Network = 10,
        Offline = 11,
        LicenseMissing = 12,
        LicenseFileMissing,
        NullChannel = 14,
        ModelStateInvalid = 15,
        Unhandled = 16,
        IncorrectServerHost = 17,
        IncorrectServerHostPort = 18,
        IncorrectInstanceName = 19,
        IncorrectUsernameOrPassword = 20
    }

    public class LoginInfo
    {
        public LoginInfo()
        {
            serverHost = string.Empty;
            instanceName = string.Empty;
            username = string.Empty;
            password = string.Empty;
            remotingPassword = null;
            remember = false;
        }

        [Required]
        [Display(Name = "Server Host")]
        public string serverHost { get; set; }

        [Required]
        [Display(Name = "Instance Name")]
        public string instanceName { get; set; }

        [Required]
        [Display(Name = "Username")]
        public string username { get; set; }

        [Required]
        [Display(Name = "Password")]
        public string password { get; set; }

        [Display(Name = "Remoting Password")]
        public string remotingPassword { get; set; }

        [Display(Name = "Persistent")]
        public bool remember { get; set; }
    }

Is there any not-so-obvious limit I may be breaking? (Like HttpStatusCodeResult.StatusDescription has a max limit of 512 chars - note: this is not happening in my example).

Hopefully somebody can shed some light on this issue, like I mentioned it's been horrible to troubleshoot and I'm getting nowhere. Any help would be incredibly appreciated. Thank you.

Update (11/02/16): JS response function (failure and success are simply animation functions):

function response(data) {
    setTimeout(function () {
        if (data.status == 200) {
            success();
        }
        else {
            var info = data.statusText.split('|');
            var message = info[0];
            var code = info[1];

            console.log("Login failed with error code: " + code);
            failure(message);
        }
    }, 1000);
}

Update (15/02/16): Installed Fiddler, and error doesn't occur anymore with Fiddler running (I'm guessing it intercepts the empty response and returns with a code of it's own?). Although Fiddler is reporting the following:

HTTP/1.1 504 Fiddler - Receive Failure
Date: Mon, 15 Feb 2016 12:36:05 GMT
Content-Type: text/html; charset=UTF-8
Connection: close
Cache-Control: no-cache, must-revalidate
Timestamp: 12:36:05.548

[Fiddler] ReadResponse() failed: The server did not return a complete response for this request. Server returned 0 bytes.

As a temporary work-around I am returning a JSONResult from the action. Not a fix, but a workaround until I find something more revealing on the internet (no luck so far after ~7 days of searching.)

Zollistic
  • 98
  • 1
  • 8
  • In the browser tools, can you verify that only one request is actually sent to the server? – pnm Feb 11 '16 at 17:39
  • what does your response function look like in javascript? (i'm referring to the function that runs onComplete of the ajax request) – Abdul Ahmad Feb 11 '16 at 17:44
  • Yes, only one request is being sent. I will update the original question with the response function. – Zollistic Feb 11 '16 at 18:15
  • @Zollistic what does your `submit` javascript function look like? I'm guessing it...submits? if so, then you are submitting twice - once with `function submit()` and once with `Ajax.BeginForm("Ajax", "Login", ...` – ethorn10 Feb 15 '16 at 16:25
  • @ethorn10 The `submit` function is for animation only, no extra form submissions are happening. – Zollistic Feb 16 '16 at 11:53
  • @Zollistic fair enough - any chance you've added `jquery.unobtrusive-ajax.min.js` in two separate views (this one and potentially a master layout page?) [as mentioned in this answer](http://stackoverflow.com/a/15041642/746045)? – ethorn10 Feb 16 '16 at 15:29
  • Add `` in web config. And add the following `jquery.validate.min.js, jquery.validate.unobtrusive.min.js, jquery.unobtrusive-ajax.min.js` scripts in view – Abdul Haseeb Jul 25 '22 at 10:51

0 Answers0