2012-05-25 3 views
3

У меня есть действие, которое возвращает PartialView:Как правильно обрабатывать исключения ребенка действий

[ChildActionOnly] 
public ActionResult TabInfo(int id, string tab) 
{ 

    ViewBag.Jobid = id; 
    ViewBag.Tab = tab; 

    var viewModel = _viewModelManager.GetViewModel(tab, id); 

    return 
     PartialView(string.Format("~/Views/{0}/Index.cshtml", tab), viewModel); 

} 

_viewModelManager возвращает вид из словаря. Если пользователь запрашивает вкладку, которая не exsist то KeyNotFound будет сгенерировано исключение, однако, на мой взгляд, я получаю следующее исключение:

Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'

@using MyApplication.UI.Helpers.Html 
@model MyApplication.UI.Models.MyJobModel 

@{ 
    ViewBag.Title = "Details"; 
} 

<p>@Model.Blah</p> 

... 

*@ HttpException occurs here -- renders default error view *@ 
@Html.Action("TabInfo", new { id = ViewBag.Jobid, tab = ViewBag.Tab }) 

According to MS...

HandleErrorAttribute атрибут по методу дочернего действия игнорируется, если в самом дочернем действии возникает исключение. Поэтому дочернее действие должно обрабатывать собственные исключения. Если дочернее действие имеет атрибут AuthorizeAttribute, атрибут будет выполняться и возвращать код состояния Unauthorized 401 HTTP.

Я не могу использовать этот [HandleError(ExceptionType = typeof(KeyNotFoundException), View="myError")], и я не могу перенаправлять с помощью try/catch либо потому, что перенаправления для дочерних действий не поддерживаются.

Каков наилучший способ обработки дочерних исключений?

Bottomline: Я хочу обработать исключение и вернуть страницу пользовательской ошибки.

ответ

0

В случае, если кто-либо еще сталкивается с этим вопросом.

Я закончил использование блока try/catch, чтобы поймать исключение KeyNotFound. Я регистрирую ошибку, а затем перенаправляю пользователя в ErrorView. В представлении ошибки я перенаправляю пользователя в соответствующее представление с помощью javascript.

[ChildActionOnly] 
    public ActionResult TabInfo(int id, string tab, string jobno) 
    { 
     try 
     { 
      var viewModel = _viewModelManager.GetViewModel(tab, id); 

      ViewBag.Jobid = id; 
      ViewBag.Tab = tab; 

      return PartialView(string.Format("~/Views/{0}/Index.cshtml", tab), viewModel); 
     } 
     catch (Exception ex) 
     { 
      return View("Error"); 
     } 

    } 

Ошибка Посмотреть

@model System.Web.Mvc.HandleErrorInfo 

@{ 
    Layout = null; 
} 

<!DOCTYPE html> 
<html> 
<head> 
    <title></title> 
</head> 
<body> 
    <script type="text/javascript"> 
     window.location.href = '@Url.Content("~/400.htm")'; 
    </script> 
</body> 
</html> 
3
  1. Если исключение в методе GetViewModel тогда ваше возвращение заявления даже не будет обрабатываться, на самом деле это, как нет никакого подвоха заявления вы в конечном итоге в Application_Error в global.asax (если вы конечно, есть).

  2. Вы правы, вы должны сделать проверку ContainsKey, а затем, если она неверна, верните страницу с ошибкой.

  3. Просто поместите результат на ContainsKey в переменную и Assert, чтобы переменная была правдой? Или вы можете проверить переменную viewModel и Assert, что если ContainsKey было ложным, убедитесь, что ваше имя просмотра ошибки на самом деле находится в viewModel.

trycatch не будет действительно большая практика, как в общих чертах, если вы можете избежать этого, вы должны предотвратить исключение происходит с использованием дополнительной логики (например, ContainsKey в данном случае). Исключения составляют исключительные обстоятельства :).

+0

Ну метод возвращает ViewModel базового типа, который я создал, так что я не смогу вернуть вид - я думаю, я бы бросить ошибку и пусть атрибут HandleError позаботится. Любая идея, почему атрибут HandleError не возвращает мое собственное представление об ошибке? – Rich

+0

Ah okay, HandleError не возвращает его локально? По умолчанию HandleError ничего не делает при запуске под локальным сервером разработки. Цель состоит в том, чтобы показать разработчикам более полезную информацию – mattytommo

+0

+1 для просмотра и предоставления ответа. Можете ли вы подтвердить обновление моего вопроса и обновить свой ответ или дать мне знать, как я могу устранить неполадки? – Rich

1

В моем случае я добавляю ошибку ModelState в дочернем действии (с пользовательским сообщением, а не сообщением об исключении), и помещаю ValidationSummary в частичное представление для дочернего действия. Поскольку резюме родительского действия не получает ошибок, оно не дублирует ошибки. Конечно, это все еще отображает страницу. В моем случае это было прекрасно.

Но вы должны убедиться, что вы не делаете что-то подобное в действии ребенка return PartialView(modelContainingPotentiallySensitiveInfo).Я не могу представить конкретные сценарии, но, как правило, причина, по которой вы направляетесь на совершенно другую страницу ошибок, заключается в предотвращении ошибок безопасности, связанных с ошибкой, в первую очередь. Поэтому, если вы используете мою технику, убедитесь, что вы создали новую пустую модель, которую вы не запросили из базы данных, чтобы перейти к частичной странице.

Конечно, если в вызове PartialView возникает исключение, что-то вроде ошибки в cshtml, то вы не можете вернуть действие и отобразить ошибку. Таким образом, это не идеальное решение, но может быть достаточно для других.

+0

Спасибо. Я забыл об этом. Я предоставил свой собственный ответ обходным путем, который я использовал. – Rich

Смежные вопросы