Skip to main content
 首页 » 编程设计

c#之Web API Controller 中的异常处理并抛出自定义错误消息

2024年01月31日31luoye11

对于我的一个项目,我正在使用具有某种 SOA 架构的 Web API。在 Controller 中,我想捕获异常(由 Repository 抛出)并返回 HttpResposeMessage。

我想要的是应该有一个继承 ApiController (class BaseController : ApiController) 的 BaseController,并且我的每个 Controller 都应该由 baseController
继承,例如class TaskController : BaseController 如果我的 Controller 中发生任何异常,则应由 BaseController 处理。 演示:

以下是我们 VS 解决方案中的项目:(项目结构)

XYZ.Model 
XYZ.Repository 
XYZ.WebServices 
XYZ.Exception 
XYZ.UI 

代码: XYZ.型号

public class Error 
{ 
    public string Code { get; set; } 
    public string Message { get; set; } 
 
} 

XYZ.异常

// To create the custom exception as per our need 
public class BaseException : Exception 
{ 
    private Error _error; 
    public Error Error 
    { 
        get { return _error; } 
    } 
 
    public BaseException() 
    { 
        _error = new Error(); 
    } 
 
    public void SetErrorCode(string code) 
    { 
        _error.Code = code; 
    } 
 
    public void SetErrorMessage(string message) 
    { 
        _error.Message = message; 
    } 
} 
 
 
public class TaskNotFoundException : BaseException 
{ 
    public TaskNotFoundException() 
    { 
        string errorCode = "T0001"; 
        base.SetErrorCode(errorCode); 
        base.SetErrorMessage((new ExceptionMessage()).GetExceptionMessage(errorCode)); 
    } 
} 

XYZ.Repository

public Task UpdateTaskDetails(Task task) 
{ 
    try 
    { 
        //--Task updating logic--// 
    } 
    catch (Exception ex) 
    { 
        throw new TaskUpdateFailedException(); 
    } 
    return task; 
} 

XYZ.Web 服务

public class BaseController : ApiController 
{ 
    public HttpResponseMessage CreateResponseMessage() 
    { 
        try 
        { 
            GetTasksByUserIdAndProjectId(new TaskQuery()); 
        } 
        catch(BaseException exception) 
        { 
            return Request.CreateResponse(HttpStatusCode.InternalServerError, exception.Error); 
        } 
    } 
 
    public virtual  List<Task> GetTasksByUserIdAndProjectId(TaskQuery query) 
    { 
        Console.WriteLine("I can be overridden"); 
    } 
} 
 
 
public class TaskController : BaseController 
{ 
    [HttpPost] 
    public override List<Task> GetTasksByUserIdAndProjectId(TaskQuery query) 
    { 
        return _taskRepo.GetTasksByUserIdAndProjectId(query.UserId, query.ProjectId); 
    } 
 
} 

在 TaskController 中,如果 GetTasksByUserIdAndProjectId 方法中发生任何异常,它应该将异常抛给 BaseController CreateReponseMessage() 并在那里返回HttpResponseMessage 到客户端。

注意:在每个 Controller 中有多个 Get/Put/Post 方法,因此不可能在 BaseController 中声明所有方法(web Service 方法)来捕获当前结构中子类的异常我的项目。

有没有更好的方法来处理 Web API 中的异常,并且很容易适合我的项目?

请您参考如下方法:

我们使用这样的异常过滤器:

首先我们创建自己的异常:

public class UserFriendlyException: Exception 
    { 
        public UserFriendlyException(string message) : base(message) { } 
        public UserFriendlyException(string message, Exception innerException) : base(message, innerException) { } 
    } 

然后我们创建一个过滤器:

public class UserFriendlyExceptionFilterAttribute: ExceptionFilterAttribute 
    { 
        public override void OnException(HttpActionExecutedContext context) 
        { 
            var friendlyException = context.Exception as UserFriendlyException; 
            if (friendlyException != null) 
            { 
                context.Response = context.Request.CreateResponse(HttpStatusCode.BadRequest, new {Message = friendlyException.Message});  
            } 
        } 
    } 

最后,在 WebApi 的配置中,我们添加了该过滤器。

public static class WebApiConfig 
    { 
        public static void Register(HttpConfiguration config) 
        { 
            ... 
 
 
            config.Filters.Add(new UserFriendlyExceptionFilterAttribute()); 
 
            ... 
        } 
    } 

使用此解决方案,您可以在代码中的任何位置抛出 UserFriendlyException,响应将根据过滤器进行。