【问题标题】:Controller to Return an Error Message Instead of a View?控制器返回错误消息而不是视图?
【发布时间】:2011-12-07 06:54:28
【问题描述】:

我对 ASP.NET MVC 还很陌生,不确定如何最好地处理以下情况。

我的控制器中的一个方法需要根据 ID 参数加载一些数据。在正常情况下,此 ID 参数将设置为我的数据库中实体的有效 ID。我构造了一些数据并将其放在 ViewBag 中,视图使用它来呈现页面。

但是,我想要一些基本的错误处理,以防 ID 参数无效有效。虽然我可以在视图中编写一堆错误处理代码,但如果网站出现严重误用或故障,不显示视图会简单得多。

控制器有没有办法简单地返回“未找到项目”字符串或类似的东西,并显示它而不是普通视图?或者也许有人可以提出更好的主意?

【问题讨论】:

    标签: asp.net-mvc


    【解决方案1】:
    if (itemId == null)
    {
        return Content("Item not found");
    }
    

    或者,如果您想返回 HTTP 404:

    throw new HttpException(404, "Item Not Found");
    

    【讨论】:

    • 我已经忘记了好几次了,很难找到正确的答案,但对于未来的谷歌人来说,这种方式更好:return new HttpStatusCodeResult(404, "Item Not Found");。它不会抛出异常,显然不限于 404 错误。
    • 也适用于未来的谷歌员工:netcore 似乎没有 HttpStatusCodeResult(至少我能找到 8/2017)。因此,另一种方法是将响应更改为适当的代码,然后将具有指定路径的视图返回到错误视图。因此,对于 404,例如:Response.StatusCode = 404;return View("NotFound", "Item Not Found")。其中“NotFound”是 Views 目录中的 404 错误视图。
    【解决方案2】:

    如果从数据库中获取模型(如 Darin 的回答中所述)有点复杂并且不能通用,这就是我处理未找到资源的方式。

    实现你的基本控制器

        public abstract class MyBaseController : Controller
        {
            [NonAction]
            protected virtual void EnsureResourceFound(object resource)
            {
                if (resource == null)
                {
                    HttpStatusCode statusCode = HttpStatusCode.NotFound;
                    throw new HttpException((int)statusCode, statusCode.ToString());
                }
            }
        }
    

    在派生控制器中 - 使用该方法

        [HttpGet]
        public virtual ActionResult Edit(int id)
        {
            SomeModel model = null;
            EnsureResourceFound(model = _someModelService.Get(id));
            return View(question);
        }
    

    您将如何处理产生的 http 异常、返回自定义视图、记录错误,取决于配置的 HandleErrorAttribute

    【讨论】:

      【解决方案3】:

      你可以通过简单地从控制器抛出异常来做到这一点。

      您需要编写以下代码并需要添加ErrorController及其各自的视图。

      全球.asax

      Exception exception = Server.GetLastError();
      
      Response.Clear();
      
      HttpException httpException = exception as HttpException;
      
      //Add controller name
      RouteData routeData = new RouteData();
      routeData.Values.Add("controller", "Error");
      
      //we will add controller's action name 
      routeData.Values.Add("action", "Index");
      
      // Pass exception details to the target error View.
      routeData.Values.Add("error", exception.Message);
      
      // Clear the error on server.
      Server.ClearError();
      
      // Call target Controller and pass the routeData.
      IController errorController = new ErrorController();
      errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
      
      
      //and throw the exception from the Controller ny simply writing
      throw new Exception()
      

      错误控制器:

      public class ErrorController : BaseController
          {
              #region Function Declaration
              /// <summary>
              /// Shows application error
              /// </summary>
              /// <param name="error">error description</param>
              public ActionResult Index(string error)
              {
                  ViewBag.Description = Resources.ErrorMessage.GeneralError;
                  if (string.IsNullOrEmpty(error))
                  {
                      ViewBag.DetailError = error;
                  }
                  else
                  {
                      ViewBag.DetailError = string.Empty;
                  }
      
                  return View("ErrorIndex");
              }
              #endregion
          }
      

      另一种方法:

      如果您想为特定错误编写视图,则必须编写后续代码。您只需添加 DivByZero 视图。

          [HandleError(View = "DivByZero", ExceptionType = typeof(System.DivideByZeroException))]
          public ActionResult About()
          {
              List<Alok> alokList = new List<Alok>();
              var al = from aa in alokList.Distinct()
                       select aa;
      
              ViewData["Errorname"] = "Divide By Zero Exception";
              ViewBag.ErrorName = "Divide By Zero Exception";
              //throw new DivideByZeroException();
      
              return View();
          }
      

      DivByZero 视图:

      @model System.Web.Mvc.HandleErrorInfo
      @{
          ViewBag.Title = "Error";
          Layout = "~/Views/Shared/_Layout.cshtml";
      }
      @*<h2>
          @ViewData["Errorname"].ToString()
          @ViewBag.ErrorName</h2>*@
      <p>
          Controller : @Model.ControllerName
      </p>
      <p>
          Action : @Model.ActionName
      </p>
      <p>
          Error Message : @Model.Exception
      </p>
      

      【讨论】:

        【解决方案4】:
        public ActionResult Foo(int id)
        {
            MyModel model = ...
            if (model == null)
            {
                return HttpNotFound();
            }
            return View(model);
        }
        

        而且由于在您的操作中一遍又一遍地编写相同的代码很快就会变得无聊,一个更好的解决方案是编写一个自定义模型绑定器,该绑定器将从数据库中获取模型,如果没有找到,将简单地抛出一个新的 HttpException 并设置状态码为 404。然后您的控制器操作将如下所示:

        public ActionResult Foo(MyModel model)
        {
            return View(model);
        }
        

        以及模型绑定器本身:

        public class MyModelBinder : IModelBinder
        {
            public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
            {
                var id = bindingContext.ValueProvider.GetValue("id");
                if (id == null)
                {
                    throw new HttpException(404, "Not found");
                }
        
                MyModel model = FetchTheModel(id.AttemptedValue);
                if (model == null)
                {
                    throw new HttpException(404, "Not found");
                }
        
                return model;
            }
        
            private MyModel FetchTheModel(string id)
            {
                throw new NotImplementedException();
            }
        }
        

        这个模型绑定器显然可以更通用。

        【讨论】:

          猜你喜欢
          • 2017-12-30
          • 2020-10-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-03-08
          • 1970-01-01
          • 2021-03-02
          相关资源
          最近更新 更多