抛出HttpException总是会发回HTTP 500错误?

我正在尝试在客户端返回HTTP 403错误代码。 我已经读过HttpException是实现这一目标最干净的方法,但它并不适用于我。 我从这样的页面中抛出exception:

throw new HttpException(403,"You must be logged in to access this resource."); 

但是,当CustomErrors关闭时,这只会给出标准的ASP.Net堆栈跟踪(500错误)。 如果启用了CustomErrors,则不会重定向到我设置为403错误发生时显示的页面。 我应该忘记HttpException而是自己设置所有HTTP代码吗? 我该如何解决?

我的Web.Config的自定义错误部分是这样的:

    

而不是获得Forbidden.html,我会得到GenericErrorPage.html

您需要覆盖应用程序错误,如下所示:

  protected void Application_Error() { var exception = Server.GetLastError(); var httpException = exception as HttpException; Response.Clear(); Server.ClearError(); var routeData = new RouteData(); routeData.Values["controller"] = "Errors"; routeData.Values["action"] = "General"; routeData.Values["exception"] = exception; Response.StatusCode = 500; if (httpException != null) { Response.StatusCode = httpException.GetHttpCode(); switch (Response.StatusCode) { case 403: routeData.Values["action"] = "Http403"; break; case 404: routeData.Values["action"] = "Http404"; break; } } IController errorsController = new ErrorsController(); var rc = new RequestContext(new HttpContextWrapper(Context), routeData); errorsController.Execute(rc); } 

然后你必须添加errorsController:

 public class ErrorsController : Controller { public ActionResult General(Exception exception) { ViewBag.ErrorCode = Response.StatusCode; ViewBag.Message = "Error Happened"; //you should log your exception here return View("Index"); } public ActionResult Http404() { ViewBag.ErrorCode = Response.StatusCode; ViewBag.Message = "Not Found"; return View("Index"); } public ActionResult Http403() { ViewBag.Message = Response.StatusCode; ViewBag.Message = "Forbidden"; return View("Index"); } } 

最后为errorsController创建一个视图。 我在Views / Errors /中创建了一个名为index的视图。

希望这有用。

问候!

使用此代码包含在Web.config文件的element configuration / system.web中:

     

我设法按预期工作。

您可以在这里找到一个包含示例的好教程(示例3是正确的): http : //aspnetresources.com/articles/CustomErrorPages

或者您可以使用Response.Status执行此操作: Asp Classic返回特定的http状态代码

我实际上最终制作了自己漂亮的小class来解决这个问题。 它不能处理所有内容,我不确定它与MVC有什么关系,但它适用于我的用途。 基本上,它不是依靠ASP.Net输出正确的错误页面和错误代码,而是清除错误,然后进行服务器端传输并显示相应的Web.Config错误页面。 它还识别customErrors模式并做出相应的反应。

 public static class CustomErrorsFixer { static public void HandleErrors(HttpContext Context) { if(RunIt(Context)==false){ return; } HttpException ex = Context.Error as HttpException; if(ex==null){ try{ ex=Context.Error.InnerException as HttpException; }catch{ ex=null; } } if (ex != null){ Context.Response.StatusCode = ex.GetHttpCode(); }else{ Context.Response.StatusCode = 500; } Context.ClearError(); Context.Server.Transfer(GetCustomError(Context.Response.StatusCode.ToString())); HttpContext.Current.Response.End(); } static protected string GetCustomError(string code) { CustomErrorsSection section = ConfigurationManager.GetSection("system.web/customErrors") as CustomErrorsSection; if (section != null) { CustomError page = section.Errors[code]; if (page != null) { return page.Redirect; } } return section.DefaultRedirect; } static protected bool RunIt(HttpContext context){ CustomErrorsSection section = ConfigurationManager.GetSection("system.web/customErrors") as CustomErrorsSection; switch(section.Mode){ case CustomErrorsMode.Off: return false; case CustomErrorsMode.On: return true; case CustomErrorsMode.RemoteOnly: return !(context.Request.UserHostAddress=="127.0.0.1"); default: return true; } } } 

然后激活它,只需向Global.asax添加一个小东西

  protected virtual void Application_Error (Object sender, EventArgs e) { CustomErrorsFixer.HandleErrors(Context); }