【问题标题】:Return JSON when Handling error in Web API在 Web API 中处理错误时返回 JSON
【发布时间】:2017-04-01 09:30:27
【问题描述】:

我创建了 Web API,它接受四个输入参数,用于查询 Oracle 数据库并以 JSON 格式返回结果。现在,如果缺少任何输入参数或格式错误,我正在尝试处理 URI 中的任何异常。就像返回 JSON "error":"ROOM cannot be Empty or NULL" 如果 URI 中的 ROOM 是空的,比如 ROOM=&DOB_GT=01-SEP-05&DOB_LT=30-DEC-06&STATUS_TYPE=CMPLT

public class TGSDataController : ApiController
{
[HttpGet]
public HttpResponseMessage Getdetails(string ROOM, DateTime DOB_GT, DateTime DOB_LT, string STATUS_TYPE)
{
    if (string.IsNullOrEmpty(ROOM))
    {
        var resp = new HttpResponseMessage()
        {
            Content = new StringContent("ROOM cannot be Empty or NULL")
        };
        resp.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
        return resp;
    }
    List<OracleParameter> prms = new List<OracleParameter>();
    List<string> selectionStrings = new List<string>();
    prms.Add(new OracleParameter("ROOM", OracleDbType.Varchar2, ROOM, ParameterDirection.Input));
    prms.Add(new OracleParameter("DOB_GT", OracleDbType.Date, DOB_GT, ParameterDirection.Input));
    prms.Add(new OracleParameter("DOB_LT", OracleDbType.Date, DOB_LT, ParameterDirection.Input));
    prms.Add(new OracleParameter("STATUS_TYPE", OracleDbType.Varchar2, STATUS_TYPE, ParameterDirection.Input));

    string connStr = ConfigurationManager.ConnectionStrings["TGSDataBaseConnection"].ConnectionString;
    using (OracleConnection dbconn = new OracleConnection(connStr))
    {
        DataSet userDataset = new DataSet();
        var strQuery = "SELECT * from LIMS_SAMPLE_RESULTS_VW where ROOM = :ROOM and DOB > :DOB_GT and DOB < :DOB_LT and STATUS_TYPE= :STATUS_TYPE ";

        var returnObject = new { data = new OracleDataTableJsonResponse(connStr, strQuery, prms.ToArray()) };
        var response = Request.CreateResponse(HttpStatusCode.OK, returnObject, MediaTypeHeaderValue.Parse("application/json"));
        ContentDispositionHeaderValue contentDisposition = null;
        if (ContentDispositionHeaderValue.TryParse("inline; filename=TGSData.json", out contentDisposition))
        {
            response.Content.Headers.ContentDisposition = contentDisposition;
        }
        return response;
    }

使用我上面的代码,它确实返回 ROOM 不能为 Empty 或 NULL 如何得到 "error":"ROOM cannot be Empty or NULL"。还有什么方法可以处理 URLI 中的错误并将 JSON 响应返回为"error":"Poorly Formed URI"

【问题讨论】:

    标签: c# asp.net json asp.net-web-api


    【解决方案1】:

    首先 WebAPI 可以自动将任何对象序列化为 JSON,无需您手动尝试构建 HttpResponseMessage。

    通过使用

    Content = new StringContent("ROOM cannot be Empty or NULL")`
    

    您只需在响应正文中添加一个普通字符串即可。

    改为使用 Request.CreateResponse 扩展方法来构建一个 HttpResponseMessage,其中的任何对象都被序列化为 JSON。

    return Request.CreateResponse(HttpStatusCode.BadRequest,resp);
    

    默认情况下,WebAPI 将根据请求标头对 XML 或 JSON 上的响应进行序列化。 为了强制 JSON 序列化,只需将其添加到您的 Application_Start()

    GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
    

    现在关于异常。 默认情况下,WebAPI 会自行处理抛出的异常,并返回默认的错误响应。

    如果您想拦截此功能并在异常时返回您自己的自定义响应,您应该实现 ExceptionFilterAttribute

        public class BALExceptionFilterAttribute : ExceptionFilterAttribute
    {
        public override void OnException(HttpActionExecutedContext actionExecutedContext)
         {
            base.OnException(actionExecutedContext);
            actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(HttpStatusCode.BadRequest, new { error = actionExecutedContext.Exception.Message });
        }
    }
    

    并将其添加到您的应用程序启动中

    GlobalConfiguration.Configuration.Filters.Add(new BALExceptionFilterAttribute());
    

    最后,如果您有 WebAPI 2.1,您可以使用 Global ExceptionHandling 处理 URL 错误

    否则这里有一些相关的问题。 custom-error-pages-for-non-existant-directory-file-web-api-not-controllers how-to-handle-webapi-error-404

    【讨论】:

    • 我应该在 App_Start 文件夹下的 FilterConfig.cs 中添加GlobalConfiguration.Configuration.Filters.Add(new BALExceptionFilterAttribute());
    • 我没有在那里添加它。它就在我的 Global.asax Application_Start();
    • GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);GlobalConfiguration.Configuration.Filters.Add(new BALExceptionFilterAttribute()); 都应该进入 Application_Start() ?
    • 没错。这样,WebAPI 配置会在应用程序启动时更改。
    • 我添加了它们并尝试通过为日期提供无效输入来运行应用程序,如 http://localhost:46151/api/TGSData?ROOM=KOMP2&amp;DOB_GT=01--05&amp;DOB_LT=30-DEC-06&amp;STATUS_TYPE=CMPLT 就像 DOB_GT=01--05 它没有返回任何 JSON,而是在浏览器中显示,如 HTTP 400 Bad Request The Web page cannot be found
    【解决方案2】:

    您可以轻松地构建一个带有您想要返回的错误的匿名类型。

    if (string.IsNullOrEmpty(ROOM))
        {
            return this.Request.CreateResponse(
            HttpStatusCode.BadRequest,
            new { error= "ROOM cannot be empty or NULL" });
            resp.Content.Headers.ContentType = 
               new MediaTypeHeaderValue("application/json");
            return resp;
        }
    

    【讨论】:

    • 感谢卡姆布鲁斯。我试图添加 try catch 块。但我试图给出一个无效的输入参数,如 api/TGSData?ROOM=KOMP2&amp;DOB_GT=01--05&amp;DOB_LT=30-DEC-06&amp;STATUS_TYPE=CMPLT 值 DOB_GT 是错误的 (01--05) 它在 HTTP 400 Bad Request The Web page cannot be found 中引发错误,但它不会在 JSON 响应中返回那些异常详细信息
    • 啊,请参阅更新的回复。如果你手动检查你的参数,你可以很容易地建立一个对象来返回你需要的东西
    • Cam Bruce,有没有办法检查 DateTime 是否有有效的输入
    【解决方案3】:

    尝试访问您的 Web 服务的客户端不会收到 JSON 格式的错误;相反,它将在客户端遇到错误。糟糕的 URI 不会让客户端到达返回 JSON 数据的服务器。

    这应该回答你的第二个问题。

    对于第一种,您有两个选择:您可以手动构建 JSON 返回,或者,您可以使用 JSON 库。

    要手动完成,您可以使用以下方法:

        {"error":"ROOM cannot be Empty or NULL"}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-12
      • 2016-12-12
      • 2013-05-21
      • 2018-04-27
      • 2014-05-01
      • 2023-03-26
      • 2018-05-14
      相关资源
      最近更新 更多