Ответы IIS с HTML вместо JSON на ASP.NET MVC3

Субъект является самоочевидным. У меня есть среда разработки и производства. Разработчик env. это моя локальная машина. У меня есть методы действий в contolers, который устанавливает код состояния ответа на 500, когда что-то ошибается (ошибка произошла или логическое несоответствие) и возвращает Json-answer. Мой общий метод выглядит следующим образом:

[HttpPost]
public ActionResult DoSomething(int id)
{
    try
    {
         // some useful code
    }
    catch(Exception ex)
    {
         Response.StatusCode = 500;
         Json(new { message = "error" }, JsonBehaviour.AllowGet)
    }
}

На стороне клиента в производстве env. когда такая ошибка возникла, ajax.response выглядит как HTML-код, а не ожидаемый JSON.

Рассмотрим это:

<div class="content-container">
 <fieldset>
   <h2>500 - Internal server error.</h2>
   <h3>There is a problem with the resource you are looking for, and it cannot be displayed.</h3>
</fieldset>
</div>

Контекст фильтра не является параметром. Я думаю, что это какая-то проблема IIS или web.config.

РЕШЕНИЕ: Мы решили добавить TrySkipIisCustomErrors в BeginRequest в Global.asax и решить проблемы в каждом методе в нашем приложении.

Ответ 1

Я предполагаю, что IIS обслуживает некоторую дружественную страницу ошибок. Вы можете попробовать пропустить эту страницу, установив свойство TrySkipIisCustomErrors в ответе:

catch(Exception ex)
{
     Response.StatusCode = 500;
     Response.TrySkipIisCustomErrors = true;
     return Json(new { message = "error" }, JsonBehaviour.AllowGet)
}

Ответ 2

Является ли ваш IIS настроенным для обработки application/json как допустимого mime-type? Вы можете проверить это в свойствах для сервера в диспетчере IIS и выбрать MIME-типы. Если json не существует, нажмите "Создать", введите "JSON" для расширения и "application/json" для типа MIME.

Ответ 3

Я решил это, написав пользовательский результат json, который использует json.net в качестве сериализатора. Это слишком много для исправления IIS, но это означает, что оно может использоваться повторно.

public class JsonNetResult : JsonResult
{
    //public Encoding ContentEncoding { get; set; }
    //public string ContentType { get; set; }
    public object Response { get; set; }
    public HttpStatusCode HttpStatusCode { get; set; }

    public JsonSerializerSettings SerializerSettings { get; set; }
    public Formatting Formatting { get; set; }

    public JsonNetResult(HttpStatusCode httpStatusCode = HttpStatusCode.OK)
    {
        Formatting = Formatting.Indented;
        SerializerSettings = new JsonSerializerSettings { };
        SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        HttpStatusCode = httpStatusCode;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        HttpResponseBase response = context.HttpContext.Response;

        response.TrySkipIisCustomErrors = true;

        response.ContentType = !string.IsNullOrEmpty(ContentType) ? ContentType : "application/json";

        if (ContentEncoding != null)
            response.ContentEncoding = ContentEncoding;

        response.StatusCode = (int) HttpStatusCode;

        if (Response != null)
        {
            JsonTextWriter writer = new JsonTextWriter(response.Output) { Formatting = Formatting };

            JsonSerializer serializer = JsonSerializer.Create(SerializerSettings);
            serializer.Serialize(writer, Response);

            writer.Flush();
        }
    }
}

Использование:

            try
            {
                return new JsonNetResult()
                {
                    Response = "response data here"
                };
            }
            catch (Exception ex)
            {
                return new JsonNetResult(HttpStatusCode.InternalServerError)
                {
                    Response = new JsonResponseModel
                    {
                        Messages = new List<string> { ex.Message },
                        Success = false,
                    }
                };
            }