views:

1165

answers:

3

Not even sure if this is the right way to title the question. I know I'm making my AJAX calls all wrong... here's what I'm doing right now (I'm using ASP.NET MVC backend by the way):

I use jQuery.ajax to post some data to an action, which will load a view that I capture in the response. It's basically providing some data to an action, and taking some HTML back.

Let's say I wanted to create an ajax call that is validated. How do I get back the validation messages on error? For example, an ajax login form. If the user cannot be validated, I'd like to tell them that... instead of simply doing nothing.

Sorry for the naive question, I just don't know how to word it right to find the solutions on Google.

Thank you in advance!

+4  A: 

First of all if you want AJAX call to return the data you are planning to use in your scripts (and by use I mean something more complicated then displaying that data in a div), you should probably return JSON data instead of HTML from your server. JSON is actually a JS object so it can be used in JS the moment it is received.

So if you return the data i.e.

{id: 1, status: 'ok'}

You can use something like this to use that data.

$.ajax({
    url: "your/script/url",
    type: "POST",
    data: {login : 'foo', pass: 'bar'}, // whatever the data is
    dataType: "json",
    success: function(data){
        if (data.status === 'ok') {
            console.log('success');
        } else {
            console.log('error');
        }
    }

});

RaYell
Why don't you use $.getJSON() ?
kay.herzam
Thanks, I was already building a JSON response. Adding a status field will be easy. Don't know why I didn't think of that sooner.
Chad
A: 

I'm not sure whether I fully understood what you mean. But your example of a validation message on an error, wouldn't that work like the following:

  1. User clicks on some button/link whatever which causes an action
  2. An asynchronouse post is done back to the server, transmitting the user id (you should be aware of security here)
  3. On the server the necessary validation is done and a response send back (in XML, Json, directly the message encoded as HTML)
  4. Back on the client side you get your response in your JavaScript code and place it appropriately on the page

Hope that helps.

Juri
+4  A: 

You'll need to return multiple pieces of information for your response. Luckily, you can do that easily using JSON, and jQuery will automatically handle it for you if you tell it the response type is json. The object that you get into your ajax callback function will contain all the pieces of data you need as different properties.

I would suggest getting into the habit of returning a status code of "success" or "failure" with each ajax call, and a collection of errors with it. See this awesome blog post for more information on what I mean.

The reason for this is that an ajax call will always fundamentally "succeed", unless the server actually couldn't process the request and returned a failure http status code. If the result of the request is something like a validation error, but the server still returns some kind of text response, then the ajax call is still considered to have succeeded, even though the application operation failed.

So if, in your action method, instead of returning your html data in an action result, if you returned an object like this:

public class AjaxResponse
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="AjaxResponse"/> class.
        /// This creates an AjaxResponse that by default indicates SUCCESS.
        /// </summary>
        public AjaxResponse()
        {
            Success = true;
            Data = new List<object>();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="AjaxResponse"/> class.
        /// This creates an AjaxResponse that indicates FAILURE.
        /// </summary>
        /// <param name="exception">The exception.</param>
        public AjaxResponse(Exception exception)
            : this()
        {
            Success = false;
            Errors = new [] { exception.Message };
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="AjaxResponse"/> class.
        /// This creates an AjaxResponse that indicates SUCCESS.
        /// </summary>
        /// <param name="data">The data.</param>
        public AjaxResponse(object data)
            : this()
        {
            Data = data;
        }

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="AjaxResponse"/> is success.
        /// </summary>
        /// <value><c>true</c> if success; otherwise, <c>false</c>.</value>
        public bool Success
        {
            get; set;
        }

        /// <summary>
        /// Gets or sets the data.
        /// </summary>
        /// <value>The data.</value>
        public object Data
        {
            get; set;
        }

        /// <summary>
        /// Gets or sets the errors.
        /// </summary>
        /// <value>The errors.</value>
        public string[] Errors
        {
            get; set;
        }
    }

This will translate into a javascript object that has properties ".Success", ".Data" and ".Errors".

So if your validation code had populated the Errors array with all the validation errors, it would be easy for your ajax callback function to

  1. determine that the intended purpose of the call had failed, because the SUCCESS property was set to "failure".

  2. Get all the relevant error strings.

You could do this easily with this kind of pattern in your action methods:

    try
    {
        instance.Validate();
        return Json(new AjaxResponse(myHtmlData));
    }
    catch(Exception ex)
    {
        var response = new AjaxResponse(ex);

        // Get your validation errors here, put them into
        // your ajax response's Errors property.

        return Json(response);
    }
womp
I like the concept, but it's too much for what I need for this project. Definitely going to keep it in mind. Thank you!
Chad
Just to clarify, the .NET function should return JsonResult
pbz