asp.net-mvc 控制器返回错误消息而不是视图?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8411495/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Controller to Return an Error Message Instead of a View?
提问by Jonathan Wood
I'm fairly new to ASP.NET MVC and am not sure how best to handle the following situation.
我对 ASP.NET MVC 相当陌生,不确定如何最好地处理以下情况。
A method in my controller needs to load some data based on an ID argument. Under normal circumstances, this ID argument will be set to a valid ID of an entity within my database. I construct some data and place it in ViewBag, which the view uses to render the page.
我的控制器中的一个方法需要根据 ID 参数加载一些数据。在正常情况下,此 ID 参数将设置为我的数据库中实体的有效 ID。我构造了一些数据并将其放在 ViewBag 中,视图使用它来呈现页面。
However, I would like some basic error handling just in case the ID argument is notvalid. Although I could write a bunch of error handling code in the view, it would be much simpler not to display the view if there is a major misuse or malfunction of the site.
不过,我想一些基本的错误处理,以防万一ID的说法是不是有效。虽然我可以在视图中编写一堆错误处理代码,但如果站点存在重大误用或故障,不显示视图会简单得多。
Is there a way the controller could simply return a "Item not found" string or something like that, and display that rather than the normal view? Or perhaps someone can suggest a better idea?
有没有办法控制器可以简单地返回“找不到项目”字符串或类似的东西,并显示它而不是普通视图?或者也许有人可以提出更好的主意?
回答by Chris Fulstow
if (itemId == null)
{
return Content("Item not found");
}
Or if you want to return an HTTP 404 instead:
或者,如果您想返回 HTTP 404:
throw new HttpException(404, "Item Not Found");
回答by archil
In case fetching model from database (as described in Darin's answer) is somehow complicated and cannot be made generic, this is how I deal with resources not found.
如果从数据库中获取模型(如 Darin 的回答中所述)有些复杂且无法通用,这就是我处理未找到资源的方式。
Implement your base controller
实现你的基本控制器
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());
}
}
}
And in derived controllers - use that method
在派生控制器中 - 使用该方法
[HttpGet]
public virtual ActionResult Edit(int id)
{
SomeModel model = null;
EnsureResourceFound(model = _someModelService.Get(id));
return View(question);
}
And what will you do with resulting http exception, return custom view, log the error, depends on configured HandleErrorAttribute.
您将如何处理由此产生的 http 异常、返回自定义视图、记录错误,这取决于配置的HandleErrorAttribute.
回答by alok_dida
You can do it by simply throwing exception from the Controller.
您可以通过简单地从控制器抛出异常来实现。
You need to write following code and need to add ErrorController and it's respective view.
您需要编写以下代码并需要添加 ErrorController 及其各自的视图。
Global.asax
全球.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()
ErrorController:
错误控制器:
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
}
Another Approach :
另一种方法:
If you want to write a view for a particular error than you have to write followig code. You have to just add DivByZero view.
如果您想为特定错误编写视图,则必须编写以下代码。您只需添加 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 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>
回答by Darin Dimitrov
public ActionResult Foo(int id)
{
MyModel model = ...
if (model == null)
{
return HttpNotFound();
}
return View(model);
}
And since writing this same code over and over again in your actions could quickly become boring a better solution is to write a custom model binder which will fetch the model from the database and if not found will simply throw a new HttpException and set the status code to 404. Then your controller action will simply look like this:
并且由于在您的操作中一遍又一遍地编写相同的代码很快就会变得无聊,一个更好的解决方案是编写一个自定义模型绑定器,它将从数据库中获取模型,如果没有找到,将简单地抛出一个新的 HttpException 并设置状态代码到 404。然后您的控制器操作将如下所示:
public ActionResult Foo(MyModel model)
{
return View(model);
}
and the model binder itself:
和模型绑定器本身:
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();
}
}
This model binder could obviously be made more generic.
这个模型活页夹显然可以变得更通用。

