如何在ASP.NET MVC中实现自己的错误视图

时间:2014-12-11 12:10:48

标签: asp.net-mvc error-handling

在我的ASP.NET MVC应用程序中,我有一个ErrorController,目前只有一个动作方法,它接收一个名为Error的自定义类,并将其呈现给名为Error.cshtml的视图。目前,Error类中只有2个属性:

public class Error{
   public string UserFriendlyMmessage{get;set;}
   public string ErrorMessage{get;set;}
}

Error.cshtml视图强类型为Error类。每当在action方法中抛出异常时,我都会执行以下操作:

Error error = new Error { UserFriendlyText = "The friendly message", ErrorDescription = "Error to be logged" };
return RedirectToAction("Index", "Error", new System.Web.Routing.RouteValueDictionary(error));

这里是ErrorController的动作方法:

    public ActionResult Index(Error error)
    {
        return View(model: error, viewName:"Error");
    }

虽然这很有效,但这样所有模型属性都会显示在网址中。是否有更好,更常用的方法?

3 个答案:

答案 0 :(得分:5)

除了丑陋的查询字符串之外,您还有可能超出查询字符串限制,特别是如果您的邮件很长并且您向Error添加了更多属性。

一种选择是将Error保留到TempData属性,然后return RedirectToAction("Index", "Error")并在Index()方法中获取TempData的值并渲染观点。

另一种选择是使用HandleErrorAttribute属性根据特定异常呈现视图。例如

[HandleError(ExceptionType = typeof(MyException), View = "MyError")]
[HandleError(ExceptionType = typeof(AnotherException), View = "AnotherError")]
public class BaseController : Controller
{
}

并在/Views/Shared文件夹中添加特定的错误视图(MyError.cshtml)

@model System.Web.Mvc.HandleErrorInfo
....
@Model.Exception.Message // display error message
...

注意HandleErrorInfo使您可以访问控制器和操作名称以及异常详细信息。

然后,在特定方法中,如果抛出异常,将显示关联的视图

public class MyController : BaseController
{
  public ActionResult SomeAction()
  {
    if(someCondition)
    {
      throw new MyException("Some friendly error message");
    }
    return View();
  }
}

MyException是内置异常,或者您拥有源自Exception的自定义异常

请注意,您还需要在web.config

中设置以下内容
<system.web>
  <customErrors mode="On" defaultRedirect="Error" />
</system.web>

答案 1 :(得分:1)

当您在每个操作中填充Error类并且具有相同的视图时,是否需要重定向到特殊错误操作?您可以执行以下操作:

try{
   DoSomeStuff();
}
except (Exception e)
{
    Error error = new Error { UserFriendlyText = "The friendly message", ErrorDescription = "Error to be logged" };
    return View("Error", error);  //error view
}
return View(); //Default way

对于我们自己,我们选择了另一种方法来显示错误。没有特殊视图来显示错误。在这种情况下,用户将丢失发生错误的上下文。我们创建了以下结构,而不是特殊视图。

  1. 我们有BaseController,它有几个有用的功能:

    protected void AddErrorMessage(String errorMessage)
    {
        var errorMessages = TempData["ErrorMessages"] as List<String>;
        if (errorMessages == null)
            errorMessages = new List<String>();
        errorMessages.Add(errorMessage);
        TempData["ErrorMessages"] = errorMessages;
    }
    
    protected void AddSuccessMessage(String successMessage)
    {
        var successMessages = TempData["SuccessMessages"] as List<String>;
        if (successMessages == null)
            successMessages = new List<String>();
        successMessages.Add(successMessage);
        TempData["SuccessMessages"] = successMessages;
    }
    protected void AddWarningMessage(String warningMessage)
    {
        var warningMessages = TempData["WarningMessages"] as List<String>;
        if (warningMessages == null)
            warningMessages = new List<String>();
        warningMessages.Add(warningMessage);
        TempData["WarningMessages"] = warningMessages;
    }
    
  2. 我们修改了_Layout以显示这些消息:

        @if (@TempData.ContainsKey("ErrorMessages"))
        {
            foreach (var errorMessage in TempData["ErrorMessages"] as List<String>)
            {
            <div class="alert alert-error">
                <button type="button" class="close" data-dismiss="alert">&times;</button>
                @(new HtmlString(errorMessage))
            </div>
            }
        }
       //The same stuff for warnings and messages
    
  3. 在控制器中我们按如下方式使用它:

    public ActionResult CreateCustomer(客户客户) {

    if (!ModelState.IsValid)
    {
    
        this.AddErrorMessage("Something wrong with your model");
    
        return View(customer);
    
    }
    

    }

  4. 我们只返回相同的视图,但附加了其他消息。因此,客户可以检查问题或查看某些警告/信息消息而不会丢失上下文。

答案 2 :(得分:1)

我不想使用RedirectToAction进行错误处理的原因之一是它会更改您正在浏览的网页的网址,这不是最好的用户体验。

最简单的方法是将Error.cshtml移到/Views/Shared文件夹中,并确保控制器中存在该文件并不存在错误。然后你可以这样做:

Error error = new Error { UserFriendlyText = "The friendly message", ErrorDescription = "Error to be logged" };
return RedirectToAction("Error", new System.Web.Routing.RouteValueDictionary(error));

默认情况下,它会在MVC约定中搜索&#34; Controller&#34;中的Error.cshtml文件。目录,如果没有找到,则在Shared目录中搜索。

如果您需要自定义该控制器的错误页面,您只需在Controller中创建一个需要自定义错误的新Error.cshtml页面。