79

I would like to control when to reply an error message and when a success message but I am always get the error message:

here is what I am trying to do:

 $.ajax({
                type: "POST",
                data: formData,
                url: "/Forms/GetJobData",
                dataType: 'json',
                contentType: false,
                processData: false,

                success: function (response) {                    
                   alert("success!") 
                },
                error: function (response) {
                   alert("error") // I'm always get this.
                }

            });

Controller:

         [HttpPost]
            public ActionResult GetJobData(Jobs jobData)
            {

              var mimeType = jobData.File.ContentType;
              var isFileSupported = AllowedMimeTypes(mimeType);

             if (!isFileSupported){        
                     //  Error
                    Response.StatusCode = (int)HttpStatusCode.BadRequest;
                    return Content("The attached file is not supported", MediaTypeNames.Text.Plain);    
             }
            else
              {
                    //  Success
                    Response.StatusCode = (int)HttpStatusCode.OK;
                    return Content("Message sent!", MediaTypeNames.Text.Plain);     

               }   

            }
Eyal
  • 4,653
  • 9
  • 40
  • 56
  • Add an `if` condition... I'm not sure what answer you're expecting here. – Rory McCrossan Oct 28 '14 at 09:45
  • Your hitting error because the code after the first return statement is not being run. You may want to move the code after the comment for success, before the previous return statement. – Collins Oct 28 '14 at 09:49
  • I fixed the question. now my question is clear. – Eyal Oct 28 '14 at 09:50
  • It's been years since this was asked, but the reason you're probably getting an error is the `datatype` parameter in your Ajax request. You're telling Ajax to expect a JSON, but you're returning plain text: `Ajax: "datatype": The type of data that you're expecting back from the server` – Lovethenakedgun Jan 14 '19 at 14:05

5 Answers5

142
 $.ajax({
    type: "POST",
    data: formData,
    url: "/Forms/GetJobData",
    dataType: 'json',
    contentType: false,
    processData: false,               
    success: function (response) {
        if (response.success) {
            alert(response.responseText);
        } else {
            // DoSomethingElse()
            alert(response.responseText);
        }                          
    },
    error: function (response) {
        alert("error!");  // 
    }

});

Controller:

[HttpPost]
public ActionResult GetJobData(Jobs jobData)
{
    var mimeType = jobData.File.ContentType;
    var isFileSupported = IsFileSupported(mimeType);

    if (!isFileSupported){        
         //  Send "false"
        return Json(new { success = false, responseText = "The attached file is not supported." }, JsonRequestBehavior.AllowGet);
    }
    else
    {
        //  Send "Success"
        return Json(new { success = true, responseText= "Your message successfuly sent!"}, JsonRequestBehavior.AllowGet);
    }   
}

---Supplement:---

basically you can send multiple parameters this way:

Controller:

 return Json(new { 
                success = true,
                Name = model.Name,
                Phone = model.Phone,
                Email = model.Email                                
            }, 
            JsonRequestBehavior.AllowGet);

Html:

<script> 
     $.ajax({
                type: "POST",
                url: '@Url.Action("GetData")',
                contentType: 'application/json; charset=utf-8',            
                success: function (response) {

                   if(response.success){ 
                      console.log(response.Name);
                      console.log(response.Phone);
                      console.log(response.Email);
                    }


                },
                error: function (response) {
                    alert("error!"); 
                }
            });
Eyal
  • 4,653
  • 9
  • 40
  • 56
  • 2
    `contentType: 'application/json; charset=utf-8'` or `false`? And why? – Jack Jun 22 '15 at 00:18
  • me added contentType: 'application/json; charset=utf-8', processData: false and it worked for me. – Anjan Kant Oct 19 '16 at 10:53
  • @ClintEastwood contentType is the type of data you're sending, so it needs to be set to json, a very common one is 'application/json; charset=utf-8'. – Paul Zahra Mar 24 '17 at 16:57
  • 3
    It will always hit the success event of ajax call. What I want is to trigger the fail/error handler of the ajax call when something isn't available or is erroneous. – Jamshaid K. Oct 20 '18 at 00:51
  • 1
    This is a good solution, but doesn't really explain why it's good. According to Ajax spec from JQuery docs: `"error": A function to be called if the request fails.` In the OP's example, the request hit the server & was processed, it produced a predictable state which couldn't be resolved at that moment; rather than an unexpected error (I.e. Bad HTTP Verb, 404, etc). So by managing this in the `success` function, you can distinguish normal behaviour from unexpected server errors. I.e. Server request successful, returned with "bad file state" message. – Lovethenakedgun Jan 14 '19 at 14:13
39

Use Json class instead of Content as shown following:

    //  When I want to return an error:
    if (!isFileSupported)
    {
        Response.StatusCode = (int) HttpStatusCode.BadRequest;
        return Json("The attached file is not supported", MediaTypeNames.Text.Plain);
    }
    else
    {
        //  When I want to return sucess:
        Response.StatusCode = (int)HttpStatusCode.OK; 
        return Json("Message sent!", MediaTypeNames.Text.Plain);
    }

Also set contentType:

contentType: 'application/json; charset=utf-8',
SBirthare
  • 5,117
  • 4
  • 34
  • 59
15

When you return value from server to jQuery's Ajax call you can also use the below code to indicate a server error:

return StatusCode(500, "My error");

Or

return StatusCode((int)HttpStatusCode.InternalServerError, "My error");

Or

Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return Json(new { responseText = "my error" });

Codes other than Http Success codes (e.g. 200[OK]) will trigger the function in front of error: in client side (ajax).

you can have ajax call like:

$.ajax({
        type: "POST",
        url: "/General/ContactRequestPartial",
        data: {
            HashId: id
        },
       success: function (response)  {
            console.log("Custom message : " + response.responseText);
        }, //Is Called when Status Code is 200[OK] or other Http success code
        error: function (jqXHR, textStatus, errorThrown)  {
            console.log("Custom error : " + jqXHR.responseText + " Status: " + textStatus + " Http error:" + errorThrown);
        }, //Is Called when Status Code is 500[InternalServerError] or other Http Error code
        })

Additionally you can handle different HTTP errors from jQuery side like:

$.ajax({
        type: "POST",
        url: "/General/ContactRequestPartial",
        data: {
            HashId: id
        },
        statusCode: {
            500: function (jqXHR, textStatus, errorThrown)  {
                console.log("Custom error : " + jqXHR.responseText + " Status: " + textStatus + " Http error:" + errorThrown);
            501: function (jqXHR, textStatus, errorThrown)  {
                console.log("Custom error : " + jqXHR.responseText + " Status: " + textStatus + " Http error:" + errorThrown);
            }
        })

statusCode: is useful when you want to call different functions for different status codes that you return from server.

You can see list of different Http Status codes here:Wikipedia

Additional resources:

  1. Returning Server-Side Errors from AJAX Calls
  2. Returning a JsonResult within the Error function of JQuery Ajax
  3. Handling Ajax errors with jQuery
Tekin
  • 554
  • 7
  • 17
1

When you return a bad request from Controller a global exception is triggered. Probably a error page is displayed in the client, so jquery get 200 response.

Solution 1:

Controller

[HttpPost]
public ActionResult FooAction(string id, string[] orderFields)
{
    bool hasError = true; //TODO: Validation

    if (hasError)
    {
       Response.Clear();
       Response.TrySkipIisCustomErrors = true; //the magic
       Response.StatusCode = (int)HttpStatusCode.InternalServerError;

       return Json(new { success = false, message = "test error", status = 500 });
    }
    else
    {
       return Json(new { success = true, message = "ok", status = 200 });
    }
}

View:

<script type="text/javascript">
    $.ajax({
        type: "POST",
        url: url,
        data: { orderFields: order },
        success: function (response) {
            if (response.success) {
                alert("Ok");
            }
        },
        error: function (xhr, status, error) {
            if (xhr.responseText != "") {
                var err = JSON.parse(xhr.responseText);
                if (err.status == 440) {
                    alert("Session expired");
                }
                else {
                    alert(err.message);
                }
            }
            else {
                alert("Crash");
            }
        }
    });
</script>



Solution 2: (More Elegant)
Create a custom attribute

using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Net;
using System.Web.Mvc;

public class ExceptionJsonMvcAttribute : FilterAttribute, IExceptionFilter
{
    public virtual void OnException(ExceptionContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        if (context.Exception == null)
            return;

        int status;
        string message;
        var ex = context.Exception;
        var exceptionType = ex.GetType();
        if (exceptionType == typeof(UnauthorizedAccessException))
        {
            var exAccess = (UnauthorizedAccessException)ex;
            message = exAccess.Message;
            status = (int)HttpStatusCode.Unauthorized;
        }
        else if (exceptionType == typeof(SqlException))
        {
            var exSql = (SqlException)ex;
            message = GetDbMessage(exSql);
            status = (int)HttpStatusCode.BadRequest;
        }
        else if (exceptionType == typeof(KeyNotFoundException))
        {
            var exNotFound = (KeyNotFoundException)ex;
            message = exNotFound.Message;
            status = (int)HttpStatusCode.NotFound;
        }
        else
        {
            message = ex.Message;
            status = (int)HttpStatusCode.InternalServerError;
        }


        string json = ""; // TODO: Json(new { success = false, message = message, status = status });
        context.ExceptionHandled = true;
        context.HttpContext.Response.Clear();
        context.HttpContext.Response.TrySkipIisCustomErrors = true;
        context.HttpContext.Response.StatusCode = status;
        context.HttpContext.Response.ContentType = "application/json";
        context.HttpContext.Response.Write(json);
    }

    private string GetDbMessage(SqlException exSql)
    {
        //TODO: Remove generic from database

        return "DataBase Error see log";
    }
}

pay attention for ApiController use System.Net.Http instead of System.Web.Mvc


Controller:

[ExceptionJsonMvc]
[HttpPost]
public ActionResult FooAction(string id, string[] orderFields)
{
    bool hasError = true; //TODO: Validation

    if (hasError)
    {
       throw new Exception("test error");
    }
    else
    {
       return Json(new { success = true, message = "ok" });
    }
}
Lucio Pelinson
  • 430
  • 5
  • 7
0

.Net Core version, which use the status code to represent server error

C# Code

public string methodName(int param1)
   {
   try{
        Response.StatusCode = 200;
        return "";
    }
   catch {
        Response.StatusCode = 400;
        return "";
        }
   }

ajax call:

 $.ajax({
 type: 'get',
 url: 'your url',
 data: {"param1":value1},
 success: function (data) {
    alert("success");
    },
  error: function () {
    alert("failed");
    }
 });
PrashSE
  • 177
  • 1
  • 4