Web API和MVC异常处理

 wuyanting67412 发布于 2023-02-07 16:59

我们目前正在将我们的Web表单系统重新开发为Web API和MVC(这对我们来说是新技术)到目前为止,一切似乎都没问题,但我们正在努力将Web API应用程序中的错误发送回MVC应用程序.我们意识到我们需要捕获任何异常,并将这些异常转换为HTTP响应

Web API Product控制器如下所示:

public HttpResponseMessage GetProducts()
    {
        BAProduct c = new BAProduct();
        var d = c.GetProducts();
         if (d == null)
            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "This is a custom error message");
        else
            return Request.CreateResponse(HttpStatusCode.OK, d);
    }

MVC应用程序将通过以下代码调用Web API: -

public T Get()

               using (HttpClient client = new HttpClient())
                    {
                        client.BaseAddress = new Uri(Config.API_BaseSite);

                        client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
                        HttpResponseMessage response = client.GetAsync("api/myapplicaton/products").Result;
                        response.EnsureSuccessStatusCode();
                        T res = response.Content.ReadAsAsync().Result;
                        return (T)res;
                    }
            }

我们想要实现的是当从MVC应用程序中的Web API收到HTTP错误时,用户被重定向到自定义错误页面,或者在当前视图中显示自定义错误消息(取决于错误).我们遇到的问题是: -

    如何访问我们发回的自定义错误消息?(从示例代码中这将是"这是一个自定义错误消息",我们已经通过res中的每个属性并且看不到此消息)

    根据状态代码,我们如何捕获并将用户重定向到各个错误页面,即404页面,500页面,并显示已发回的自定义响应消息.我们一直沿着global.asax路线走下去

    protected void Application_Error(object sender, EventArgs e)
    {
        Exception exception = Server.GetLastError();
        Response.Clear();
        HttpException httpException = exception as HttpException;
    

但是我们的httpExecption总是为NULL

我们搜索过等等,到目前为止,找不到合适的东西,希望有人可以指出我们正确的方向.

1 个回答
  • 您的httpException实例为null的原因是因为该response.EnsureSuccessStatusCode();方法没有抛出HttpException您试图将其强制转换的方法.它抛出的HttpRequestException是一个不同但却没有简单方法来获取更多细节(例如状态代码).

    作为调用此方法的替代方法,您可以测试IsSuccessStatusCodeboolean属性并自行抛出HttpException:

    public T Get()
    {
        using (HttpClient client = new HttpClient())
        {
            client.BaseAddress = new Uri(Config.API_BaseSite);
    
            client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
            HttpResponseMessage response = client.GetAsync("api/myapplicaton/products").Result;
            if (!response.IsSuccessStatusCode)
            {
                string responseBody = response.Content.ReadAsStringAync().Result;
                throw new HttpException((int)response.StatusCode, responseBody);
            }
    
            T res = response.Content.ReadAsAsync<T>().Result;
            return (T)res;
        }
    }
    

    HttpException现在可以夹在你Application_Error和取决于状态代码的处理进行:

    protected void Application_Error()
    {
        var exception = Server.GetLastError();
        var httpException = exception as HttpException;
        Response.Clear();
        Server.ClearError();
    
        var routeData = new RouteData();
        routeData.Values["controller"] = "Errors";
        routeData.Values["action"] = "Http500";
        routeData.Values["exception"] = exception;
    
        Response.StatusCode = 500;
        Response.TrySkipIisCustomErrors = true;
    
        if (httpException != null)
        {
            Response.StatusCode = httpException.GetHttpCode();
            switch (Response.StatusCode)
            {
                case 403:
                    routeData.Values["action"] = "Http403";
                    break;
                case 404:
                    routeData.Values["action"] = "Http404";
                    break;
    
                // TODO: Add other cases if you want to handle
                // different status codes from your Web API
            }
        }
    
        IController errorsController = new ErrorsController();
        var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
        errorsController.Execute(rc);
    }
    

    在这个例子中,我假设你有一个ErrorsController相应的动作(Http500,Http403,Http404,...).将根据状态代码调用相应的操作,您可以返回不同的视图.


    更新:

    您可能希望捕获HTTP请求的其他工件(例如原因短语),以便在错误页面中显示它.在这种情况下,您可以编写自己的异常,其中包含您需要的信息:

    public class ApiException : Exception
    {
        public HttpStatusCode StatusCode { get; set; }
        public string Reason { get; set; }
        public string ResponseBody { get; set; }
    }
    

    你可以抛出:

    if (!response.IsSuccessStatusCode)
    {
        throw new ApiException    
        {
            StatusCode = response.StatusCode,
            Reason = response.ReasonPhrase,
            ResponseBody = response.Content.ReadAsStringAync().Result,
        };
    }
    

    然后在您的Application_Error.中使用此自定义异常.

    2023-02-07 17:02 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有