ASP.NET MVC3上使用HTML而不是JSON的IIS响应

ASP.NET MVC3上使用HTML而不是JSON的IIS响应,json,asp.net-mvc-3,error-handling,Json,Asp.net Mvc 3,Error Handling,这个主题是不言自明的。我对开发人员和生产环境进行了测试。开发者环境。是我的本地主机。我在contolers中有一些操作方法,当出现错误(错误发生或逻辑不一致)时,将响应状态代码设置为500,并返回Json应答。我的常用方法如下所示: [HttpPost] public ActionResult DoSomething(int id) { try { // some useful code } catch(Exception ex) {

这个主题是不言自明的。我对开发人员和生产环境进行了测试。开发者环境。是我的本地主机。我在contolers中有一些操作方法,当出现错误(错误发生或逻辑不一致)时,将响应状态代码设置为500,并返回Json应答。我的常用方法如下所示:

[HttpPost]
public ActionResult DoSomething(int id)
{
    try
    {
         // some useful code
    }
    catch(Exception ex)
    {
         Response.StatusCode = 500;
         Json(new { message = "error" }, JsonBehaviour.AllowGet)
    }
}
在生产环境中的客户端。发生此类错误时,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>

500-内部服务器错误。
您正在查找的资源有问题,无法显示。
筛选上下文不是一个选项。我认为这是某种IIS或web.config问题

解决方案:
我们决定在Global.asax的BeginRequest中添加
TrySkipIisCustomErrors
,它解决了我们应用程序中每个方法的问题。

您的IIS是否配置为将
应用程序/json
视为有效的
mime类型?您可以在IIS管理器中检查服务器的属性,然后单击MIME类型。如果没有json,请单击“新建”,输入“json”作为扩展,输入“application/json”作为MIME类型。

我猜IIS提供了一些友好的错误页面。您可以通过在响应上设置
tryskipiiscustomerors
属性来尝试跳过此页面:

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

我通过编写一个自定义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();
        }
    }
}
使用:

试试看
{
返回新的JsonNetResult()
{
Response=“此处的响应数据”
};
}
捕获(例外情况除外)
{
返回新的JsonNetResult(HttpStatusCode.InternalServerError)
{
Response=newjsonresponsemodel
{
Messages=新列表{ex.Message},
成功=错误,
}
};
}

在调用
Json
函数之前是否有
return
?@Zoka,是的,corse return仍然在那里。谢谢。没有:(这种类型实际上没有在我的iis上注册。我添加了它,但没有做任何更改。@Khanh To,试图跳过iis错误似乎是一种黑客行为。不,一点也没有。它不是黑客行为。友好的错误页是ASP.NET中内置的功能。如果你不喜欢它们,就不要使用它们。但是如果你决定使用它们,你应该知道后果。)nces(您不能通过自定义响应设置错误状态代码)而不明确告知IIS。我认为这是一个很好的解决方案,但似乎仍然是IIS的问题。我们决定将
TrySkipIisCustomErrors
添加到BeginRequest in Global.asax中,并解决了应用程序中每个方法的问题。谢谢。
            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,
                    }
                };
            }