Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# webapi和MVC异常处理_C#_Asp.net Mvc_Asp.net Mvc 4_Asp.net Web Api - Fatal编程技术网

C# webapi和MVC异常处理

C# webapi和MVC异常处理,c#,asp.net-mvc,asp.net-mvc-4,asp.net-web-api,C#,Asp.net Mvc,Asp.net Mvc 4,Asp.net Web Api,我们目前正在将我们的web表单系统重新开发为web API和MVC(这对我们来说是一项新技术) 到目前为止,一切似乎都正常,但是我们正在努力将错误从WebAPI应用程序发送回MVC应用程序。我们意识到我们需要捕获任何异常,并将其转换为HTTP响应 Web API产品控制器如下所示: public HttpResponseMessage GetProducts() { BAProduct c = new BAProduct(); var d = c.GetP

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

Web API产品控制器如下所示:

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<T>()

               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<T>().Result;
                        return (T)res;
                    }
            }
然而,我们的httpExecption总是空的

我们已经搜索了etc,到目前为止,还没有找到任何合适的,
希望有人能给我们指出正确的方向。

您的httpException实例为空的原因是
响应。EnsureSuccessStatusCode()
方法不会抛出一个
HttpException
,而您正试图将其强制转换为该异常。它抛出了一个不同的
HttpRequestException
,但是没有简单的方法获取更多细节(例如状态代码)

作为调用此方法的替代方法,您可以测试
issucessstatuscode
boolean属性,并自己抛出
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;
    }
}
在本例中,我假设您有一个带有相应操作的
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,
    };
}

然后在您的
应用程序中处理此自定义异常\u错误

解决上述问题的一篇优秀文章是

它主要有两个主要步骤-

步骤1:反序列化HTTP错误结果中的响应内容,例如

var httpErrorObject = response.Content.ReadAsStringAsync().Result;

// Create an anonymous object to use as the template for deserialization:
var anonymousErrorObject = 
    new { message = "", ModelState = new Dictionary<string, string[]>() };

// Deserialize:
var deserializedErrorObject = 
    JsonConvert.DeserializeAnonymousType(httpErrorObject, anonymousErrorObject);
字符串错误消息添加到apiEx.Errors中,使用deserializedErrorObject


请参见

您好,感谢您的快速响应,它非常有用,刚刚经过测试,现在允许我们将用户引导到适当的错误页面,但是,如何在createErrorResponse中获取自定义错误消息?这是否只有在添加了更新后才可能实现?如果是,在中添加此消息有什么意义?再次感谢您测试时发生了什么?是否达到
应用程序\u错误
?是否执行了
错误控制器
?您是如何定义相应的错误页面的?您是否定义了
错误控制器
?您不应该在web.config中定义任何自定义错误,因为在本例中,所有处理都是在
Application\u Error
中完成的。它将跳过您可能在那里定义的任何自定义错误页面。您好,感谢您的快速响应,它非常有用,刚刚经过测试,现在允许我们将用户引导到相应的错误页面,但是,如何在createErrorResponse中获取自定义错误消息?这是否只有在添加了更新后才可能实现?如果是,在中添加此消息有什么意义?再次感谢您如果使用
HttpException
,则自定义错误消息将出现在
ex.message
中。如果使用
ApiException
,则它将在
ex.Reason
中可用。使用ApiException的目的是,除了错误原因之外,它还允许您捕获响应主体。在HTTP协议中,您可以有状态代码(200,…),原因(状态代码的一些描述)和响应主体。实际上我犯了一个错误。似乎
CreateErrorResponse
方法将消息序列化为响应正文的一部分,而不是原因。我会更新我的答案。您可以使用
抛出新的HttpException((int)response.StatusCode,response.Content.ReadAsStringAync().Result)以便能够将响应正文作为异常消息传递。然后使用
ex.Message
检索它。
if (!response.IsSuccessStatusCode)
{
    throw new ApiException    
    {
        StatusCode = response.StatusCode,
        Reason = response.ReasonPhrase,
        ResponseBody = response.Content.ReadAsStringAync().Result,
    };
}
var httpErrorObject = response.Content.ReadAsStringAsync().Result;

// Create an anonymous object to use as the template for deserialization:
var anonymousErrorObject = 
    new { message = "", ModelState = new Dictionary<string, string[]>() };

// Deserialize:
var deserializedErrorObject = 
    JsonConvert.DeserializeAnonymousType(httpErrorObject, anonymousErrorObject);
foreach (var error in apiEx.Errors)
{
     ModelState.AddModelError("", error);
}