1
public ActionResult Foo(int id) 
{ 
    if (someCheckFails) 
    { 
     Log.Error(new SomeTypeOfException()); 
     return View("SomeErrorView"); 
    } 

    return View(); 
} 

上述代码记录错误并在满足失败条件时重定向(未授权,FileNotFound或其他)。MVC全局错误处理模式代码异味

这听起来不太适合我。它违反了DRY,并且我创建了一个除了记录器之外永远都不会去的异常。

同样可以通过设置GlobalFilters登录并重定向不同类型的异常,然后简单地从任何行动

public ActionResult Foo(int id) 
{ 
    if (someCheckFails) 
     throw new SomeTypeOfException(); 

    return View(); 
} 

上面写明更好投掷,是机,实现和似乎是MVC办法。然而,我发现现在真正发生的是使用流量控制例外,大家都知道这很糟糕,对吧?

你对此有何看法?你更喜欢哪个片段?还是有第三种方式我错过了?

回答

1

这取决于你正在检查的内容。如果它是执行Action方法之前的事情,那么您可以编写自己的从ActionFilterAttribute继承的Attribute,重写OnActionExecuting方法并设置filterContext.Result。

我已经包括下面的例子:

public class SecurityAttribute : ActionFilterAttribute 
{ 
    public string Privileges { get; set; } 

    public string FailureUrl { get; set; } 

    public SecurityAttribute() 
    { 
     this.FailureUrl = "~/Home/PermissionDenied"; 
    } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     if (string.IsNullOrEmpty(this.Privileges)) 
     { 
      throw new InvalidOperationException("Privileges must be set."); 
     } 

     if (!SecurityHelper.IsPrivileged(this.Privileges)) 
     { 
      filterContext.Result = new RedirectResult(this.FailureUrl); 
     } 
    } 
} 

然后,您可以使用该属性来装点的操作方法,一个控制器:

[Security(Privileges = "Test")] 
public ActionResult Index() 

甚至包括它在Global.asax中来全球适用:

public static void RegisterGlobalFilters(GlobalFilterCollection filters) 
{ 
    filters.Add(new SecurityAttribute()); 
} 
0

我相信,正如往常一样,答案是“取决于”。

使用异常如果有实际异常行为。如果检查在某些情况下预计会失败,例如在Adrian的回应中显示的访问权限管理,那么例外是不正确的。我会说:在这种情况下检查并重定向,因为它不是一个真正的错误。

但是,如果发生确实有效中断流量的实际例外情况,请使用例外情况。在我看来,处理特殊情况的日志记录是为这种方法编写的一个工具而设计的,而不是每次我抛出异常时都不得不依赖记住写日志条目。第二种方法确实是DRYer。