"通用" MVC5的包装器 - 控制器?

时间:2016-02-19 09:52:26

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

我有一个"泛型"返回我的MVC5-Controllers的返回值,返回类似

的内容
{ Success: true, 
Item: {Id:1, Name:"Oink" },
Error:null,
Message:"Everything works fine"
}

即使发生异常,我也希望保留此结构。所以目前我在我的控制器中使用这样的东西:

try {
    var stuff=new Stuff();
    return ReturnSomeJson(stuff.GetStuff(),"Everything works fine", true, null);
} 
catch (Exception ex)
{
    return ReturnSomeJson(null, "That went wrong!", false, ex);
}

所以这是返回方法:

protected ReturnSomeJson (object item, string message, bool success, exception ex) {
    // more stuff
    return Json (this);
}

由于这是一个非常通用的异常处理,我想避免一遍又一遍地编写这个try-catch。

我已经在MVC中遇到different Exception methods,但所有这些都直接显示错误消息。

但我想保留" ActionResult"使用通用错误处理时的returnvalue。

4 个答案:

答案 0 :(得分:4)

我已经研究了异常处理问题了,我的结论是放置通用错误处理程序的最佳位置是global.asax.cs,Application_Error方法。此外,禁用您可以找到的所有其他错误处理(包括MVC的处理),因为这可以在您不知道的情况下捕获并吞下异常。

我选择了Application_Error,因为它是绝对的最终处理程序。如果这没有发现一个流氓异常(没被吞下),那么什么都不会。例如,如果您使用MVC错误处理,那么仍然可能会遗漏一些错误 - 例如Application_BeginRequest中的异常或丢失的控制器,或DLL加载异常等等。

答案 1 :(得分:3)

如果您不想在每个控制器操作中编写Try Catch语句,则可以创建自己的异常处理程序。通过覆盖OnException的{​​{1}}方法。

您现在不必为每个操作添加HandleErrorAttribute,因为当发生异常时,它会调用try{}catch()的{​​{1}}

我有一个看起来像这样的人:

OnException

我在这里添加ValidationContainer类(因为它在上面使用)

ExceptionHandlerAttribute

然后你可以在Controller中使用它:

public class ExceptionHandlerAttribute : HandleErrorAttribute
{
    private static readonly string[] DefinedException = { "SessionTimeOutException", "UnauthorizedAccessException" };
    public override void OnException(ExceptionContext filterContext)
    {
        if (filterContext.ExceptionHandled)
            return;

        var validationContainer = new ValidationContainer();
        filterContext.ExceptionHandled = true;
        var exceptionName = filterContext.Exception.GetType().Name;
        string exceptionMessage;
        if (DefinedException.Contains(exceptionName))
        {
            exceptionMessage = filterContext.Exception.Message;
        }
        else
        {
            exceptionMessage = "We intentionally allowed to not catch exception to track the root causes. Please note down the steps and include following details in the bug.</br>"
                               + "</br></br>Exception Message: " + filterContext.Exception;
        }
        validationContainer.AddMessage(MessageType.Error, exceptionMessage);

        filterContext.Result = new JsonResult
        {
            Data = validationContainer,
            JsonRequestBehavior = JsonRequestBehavior.AllowGet
        };
    }
}

或行动

public class ValidationContainer
{
    public List<string> ErrorMessages { get; set; }
    public List<string> SuccessMessages { get; set; }
    public List<string> WarningMessages { get; set; }
    public List<string> InformationMessages { get; set; }

    public void AddMessage(MessageType messageType, string message)
    {
        switch (messageType)
        {
            case MessageType.Information:
                InformationMessages.Add(message);
                break;
            case MessageType.Success:
                SuccessMessages.Add(message);
                break;
            case MessageType.Error:
                ErrorMessages.Add(message);
                break;
            case MessageType.Warning:
                WarningMessages.Add(message);
                break;
        }
    }
}

public enum MessageType
{
    Error = 1,
    Success = 2,
    Warning = 3,
    Information = 4,
    Debug = 5,
}

答案 2 :(得分:1)

我这样用它

public abstract class ApiResult
{
    /// <summary>
    /// is success
    /// </summary>
    public bool Success { get; set; }
    /// <summary>
    /// I think you want use a error code here
    /// </summary>
    public string Error{get;set;}

    /// <summary>
    /// message
    /// </summary>
    public string Message { get; set; }

    /// <summary>
    /// error 
    /// </summary>
    /// <param name="message"></param>
    /// <returns></returns>
    public ApiResult Error(string message)
    {
        return new ErrorApiResult(message);
    }

    /// <summary>
    /// Success
    /// </summary>
    /// <param name="data"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public static ApiResult<T> Success<T>(T data)
    {
        return new ApiResult<T>()
        {
            Success = true,
            Message = null,
            Data = data
        };
    }

}
public class ErrorApiResult:ApiResult {
    public ErrorApiResult(string errorCode,string message)
    {
        Message = message;
        Success = false;
        Error = errorCode;
    }
}
public class ApiResult<T>: ApiResult
{

    /// <summary>
    /// the success return data
    /// </summary>
    public T Data { get; set; }
    public static ApiResult<T> Error(string message)
    {
        return new ApiResult<T>() {Message = message, Success = true};
    }
    public static ApiResult<T> Error(bool isSuccess,string message)
    {
        return new ApiResult<T>() {Message = message, Success =isSuccess};
    }
}

你可以在你的方法中使用它:

... ReturnSomeJson (object item, string message, bool success, exception ex) {
    if(success){
       return Json(new ApiResult.....)
    }
    // more stuff
    return Json (this);
}

但我认为差异方法更好:

ActionResult Error(string error,string message,Exception ex){
    var json = new ErrorApiResult(error,message);
    return Json(json);
}
ActionResult Success<T>(T data,string message=null){
    var json = ApiResult<T>.Success(data);
    return Json(json);
}

在ASP.NET MVC中,您可以使用过滤器来捕获操作中的所有异常:

  protected override void OnException(ExceptionContext filterContext)
    {
        base.OnException(filterContext);
        filterContext.Result = Json(new ErrorApiResult("error", filterContext.Exception.Message));
    }

答案 3 :(得分:1)

只是为了澄清(对于其他有相同问题的人),我想“清理”Dawood Awans的答案,这对我的案例有帮助,但其中有太多“真实世界的代码”,这个主题不需要,也是错过了一个关键命令,我的解决方案我终于在这里使用了:

 public class JsonExceptionAttribute:HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        if (filterContext.ExceptionHandled)
        {
            // We alread dealt with it
            return;
        }
        var jsonRet = new JsonReturn();
        filterContext.Result = 
          MyCustomJsonException(filterContext.Exception); // This is my custom method returning a JSON-String
        filterContext.ExceptionHandled = true;
    }
}

没有最后一个命令,这个ASP / MVC仍然会抛出错误