But what if there is an error in the View? For example all actions perform okay with no $c->error() statements being called, then the application is forwarded to a view in which there is some sort of error - perhaps a stash variable has not been tested for and an attempt is made to use it. The result is some rather messy output, useful to the developer but not to a user. With a little overhead we can catch the view's errors and render them in a suitable error page, by overriding the process subroutine in the view:
sub end : Private{
my ( $self, $c ) = @_;
if ( scalar @{ $c->error } ) {
$c->stash->{errors} = $c->error;
$c->stash->{template} = 'mhtml/error.mhtml';
$c->forward('MyApp::View::Mason');
$c->error(0);
}
return 1 if $c->response->status =~ /^3\d\d$/;
return 1 if $c->response->body;
unless ( $c->response->content_type ) {
$c->response->content_type('text/html; charset=utf-8'); #needed for AJAX IE7 prob
}
$c->forward( 'MyApp::View::Mason' ) unless $c->response->body; #forward to this rather than c->$view('Mason') ) gets Netscape working
}
eg lib/MyApp/View/Mason.pm:
sub process {Note that the error page you now forward to should be robust enough, ie best to keep it basic.
my ($self, $c) = @_;
my $component_path = $self->get_component_path($c);
my $output = $self->render($c, component_path);
if (blessed($output) && $output->isa('HTML::Mason::Exception')) {
chomp $output;
my $error = qq/Couldn't render component "$component_path"/;
$c->log->error($error." - error was \"$output\"");
my @errors = ();
push @errors, $error;
$c->stash->{errors} = \@errors;
$c->stash->{template} = 'error.mhtml';
$component_path = $self->get_component_path($c);
$output = $self->render($c, $component_path);
}
unless ($c->response->content_type) {
$c->response->content_type('text/html; charset=utf-8');
}
$c->response->body($output);
return 1;
}
No comments:
Post a Comment