public ActionResult GetAccount(int id) { ... }
然后我想要返回一个404如果说如果遇到这样的URL:
/GetAccount /GetAccount/notanumber
即我想要捕获抛出的ArgumentException.
我知道我可以使用可空类型:
public ActionResult GetAccount(int? id) { if(id == null) throw new HttpException(404,"Not found"); }
但这很漂亮,重复.
我希望我可以在必要时将其添加到我的控制器中:
[HandleError(View="Error404",ExceptionType = typeof(ArgumentException))] public class AccountsController : Controller { public ActionResult GetAccount(int id) { ... } }
但这看起来不好运
我看到this post和this answer几乎解决了我的问题:
在这个答案中,创建一个抽象的BaseController,从中派生所有其他控制器:
public abstract class MyController : Controller { #region Http404 handling protected override void HandleUnknownAction(string actionName) { // If controller is ErrorController dont 'nest' exceptions if (this.GetType() != typeof(ErrorController)) this.InvokeHttp404(HttpContext); } public ActionResult InvokeHttp404(HttpContextBase httpContext) { IController errorController = ObjectFactory.GetInstance<ErrorController>(); var errorRoute = new RouteData(); errorRoute.Values.Add("controller","Error"); errorRoute.Values.Add("action","Http404"); errorRoute.Values.Add("url",httpContext.Request.Url.OriginalString); errorController.Execute(new RequestContext( httpContext,errorRoute)); return new EmptyResult(); } #endregion }
这很好用于处理未知操作404,但不允许我将无效数据作为404处理.
我可以安全地覆盖Controller.OnException(ExceptionContext filterContext)
吗?
protected override void OnException(ExceptionContext filterContext) { if(filterContext.Exception.GetType() == typeof(ArgumentException)) { filterContext.ExceptionHandled = true; this.InvokeHttp404(filterContext.HttpContext); } else { base.OnException(filterContext); } }
在表面看来,它似乎工作,但是我通过这样做来存储任何问题?
这个语义正确吗?
解决方法
为了实际避免可空的方法参数,我建议你编写一个Action Method Selector属性,实际上只有当id被提供时才匹配你的动作方法.它不会说没有提供参数,但是它不能匹配给定请求的任何动作方法.
我会调用此操作选择器RequireRouteValuesAttribute并将这样工作:
[RequireRouteValues("id")] public ActionResult GetAccount(int id) { ... }
为什么这是您的问题的最佳解决方案?
如果您查看代码,您希望返回一个与名称匹配的操作404,但参数绑定失败(由于未提供或任何其他原因).你所说的动作需要特别的动作参数,否则返回404.
所以当添加动作选择器属性添加动作的需求,所以它必须匹配名称(这是由MVC给出),并且还需要特定的操作参数.每当没有提供id时,此操作不匹配.如果有另一个动作匹配不是这里的问题,因为该特定操作将被执行.主要的事情是完成的.操作与无效路由请求不匹配,而返回404.
有一个应用程序代码!
检查my blog post,实现这种属性,您可以开箱即用.它完全符合您的要求:如果提供的路径数据不包含所有必需的值,则它将与您的操作方法不匹配.