Search code examples
jqueryasp.net-mvcerror-handlinghttpresponseajaxform

Detecting error reponse with jQuery Form plugin (ajaxForm)


I'm using the jQuery Form plugin to ajaxify a file upload control. I'm returning html which I want to load into a div.

I'm having trouble detecting the error condition.

I have the following ASP.NET MVC controller method:

public ActionResult UploadDocument(int id)
{
    try
    {
        // ...blah
    }
    catch(Exception e)
    {
        // log e

        // these two lines are what I can't get working
        Response.StatusCode = (int)HttpStatusCode.InternalServerError;
        return null;
    }
    return PartialView("blah", model);
} 

and in jQuery

$documentForm.ajaxForm({
    beforeSubmit: function() { ... },
    success: function(response, status, xhr) {

        if (status == "error") {
            // this doesn't work, status is still "success"
        }

        if (!response || response == '') {
            // this doesn't work either, as the html response
            // seems to get wrapped in a <pre> tag
        }

        // this line is fine if the controller call was a success
        $container.find('.documentHistory').html(response);
    }   

How can I alert the client of an error from my server response?


Solution

  • fear,

    here's my amended implementation of the jquery ajaxform plugin:

    (function($) {
        $.fn.ajaxify = function(options) {
    
            // Defaults and options
            var defaults = {
                method: '',
                action: '',
                dataType: null, // i.e. json, jsonp etc
                target: null, // target div for ajax return data
                errordiv: null,
                // callback functions
                onBeforeSend: function() { },
                onSubmit: function() { return true },
                onSuccess: function() { },
                onError: function() { }
            };
            var opts = $.extend({}, defaults, options);
    
            this.each(function() {
                $(this).bind('submit', function(event) {
    
                    event.preventDefault();
    
                    // Increase readability && scope
                    FORM = $(this);
    
                    // Mimic the normal onSubmit handler
                    if (!opts.onSubmit.call(FORM[0])) { return; }
    
                    // Determine the method && action
                    var method = opts.method || FORM.attr('method') || 'GET';
                    var action = opts.action || FORM.attr('action');
                    var dataType = opts.dataType || "text";
                    var target = opts.target || null;
                    var errordiv = opts.errordiv || null;
    
                    // Submit the form via ajax, with appropriate callback
                    $.ajax({
                        type: method,
                        url: action,
                        data: FORM.serialize(),
                        dataType: dataType,
                        beforeSend: function() {
                            opts.onBeforeSend(FORM[0]);
                        },
                        success: function(data) {
                            if (target != null)
                                opts.onSuccess.call(FORM[0], data, target);
                            else
                                opts.onSuccess.call(FORM[0], data);
                        },
                        error: function(request, status, error) {
                            // Boil the ASP.NET AJAX error down to JSON.
                            //var err = eval("(" + request.responseText + ")");
                            // Display the specific error raised by the server
                            if (request.responseText == '') {
                                var loader = this;
                                setTimeout(function() { $.ajax(loader); }, 150);
                                //console.log(status + " : " + request.statusText + " : " + request.status);
                            }
                            else {
                                if (errordiv != null)
                                    opts.onError.call(FORM[0], request.responseText, errordiv);
                                else
                                    opts.onError.call(FORM[0], request.responseText);
                            }
                        }
                    });
                });
            });
    
            // allow chaining
            return this;
        }
    })(jQuery);
    

    usage (where <form id="ajaxify" method="post" action="<%=Url.Action("Test") %>"> etc..:

    $(document).ready(function() {
        var options = {
            onSubmit: myOnSubmit,
            onBeforeSend: myBefore,
            onSuccess: myOnSuccess,
            onError: myOnError,
            target: "#myDiv",
            errordiv: "#errDiv"
        };
        $('#ajaxify').ajaxify(options);
    });
    
    function myOnSubmit() {
        var valid = true;
        var FORM = $(this);
    
        FORM.find('input').css('border-color', '#F0F0F0');
        // fake validation just to demonstrate
        FORM.find('input').each(function() {
            if ($(this).val() == '') {
                $(this).css('border-color', 'red');
                valid = false;
            }
        });
        return valid;
    }
    
    function myBefore() {
        alert("we");
    }
    
    function myOnSuccess(msg, target) {
        if (target == null) {
            // this could also be a manually entered target
            // i.e. $("#myTargetDiv").html(msg);
            alert("no target");
        }
        else
            //alert($(target).html());
            $(target).html(msg);
    }
    
    function myOnError(errorText, errorDiv) {
        $(errorDiv).html(errorText);
    }
    

    hopefully, this should give food for thought...