我有一个"泛型"返回我的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。
答案 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仍然会抛出错误