views:

106

answers:

1

Hell,

I have error handling for my mvc app configured in the simplified way below (globals.asax):

protected void Application_Error(object sender, EventArgs e)
      {
         Exception exception = Server.GetLastError();

         Response.Clear();         
         RouteData routeData = new RouteData();
         routeData.Values.Add("controller", "Error");
         routeData.Values.Add("action", "General");            
         routeData.Values.Add("exc", exception);
         Server.ClearError();
         using (ErrorController errorController = new ErrorController())
         {
            ((IController)errorController).Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
         }         
      }

Above, I'm dynamically creating route for the controller. It is useful, because I can pass the Exception object to controller action. This is just simplified version shown above, because normally I'm creating different routes for various exception types. I have NO static route defined especially for error handling in function RegisterRoutes. This function is untouched:

 public static void RegisterRoutes(RouteCollection routes)
 {
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.MapRoute(
            "Default",
            "{controller}/{action}/{id}",
            new {controller = "Home", action = "Index", id = ""}
            );
 }

My simplified controller looks like that:

public class ErrorController : Controller
   {
      public ActionResult General(Exception exc)
      {
         ViewData["ErrorDetails"] = exc.ToString();
         return View("Error");
      }
}

Suppose, I have an error prone site:

http://localhost/app/site/wtf.

When I'm testing error handling locally, everything is fine. ErrorController is invoking General action, and this action renders Error view.

But when I'm invoking this error prone site from another host, for example, the application is deployed on nice.host.org server:

http://nice.host.org/app/site/wtf,

I'm getting such exception:

System.InvalidOperationException: The view 'Error' or its master was not found. The following locations were searched:
~/Views/DynamicPage/Error.aspx
~/Views/DynamicPage/Error.ascx
~/Views/Shared/Error.aspx
~/Views/Shared/Error.ascx
~/Views/DynamicPage/Error.cshtml
~/Views/Shared/Error.cshtml
   at System.Web.Mvc.ViewResult.FindView(ControllerContext context)
   at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
   at System.Web.Mvc.Controller.ExecuteCore()
   at System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<>c__DisplayClassb.<BeginProcessRequest>b__5()
   at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0()
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

What is going on ? How to make this work as expected ?

UPDATE

I'll provide some additional info just in case.

I'm using razor view engine. In the properties window of Error.cshtml view file, I've tried to set Build Action to None or to Content, but the behaviour of the app is still broken, despite which option is selected.

When it comes to pages section in main web.config file, it looks following:

<pages>
  <namespaces>
    <add namespace="System.Web.Mvc" />
    <add namespace="System.Web.Mvc.Ajax" />
    <add namespace="System.Web.Mvc.Html" />
    <add namespace="System.Web.Routing" />
    <add namespace="MvcSiteMapProvider.Web.Html" />
  </namespaces>
</pages>

and in the second web.config:

<pages
        validateRequest="false"
        pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <controls>
        <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
      </controls>
</pages>

I'll appreciate any clue.

Regards

A: 

I've found the problem. I had to add such entry to web.config

<customErrors mode="Off" /> 

There are three error modes in customErrors configuration: On, Off and RemoteOnly. The mode attribute specifies whether custom errors are enabled, disabled, or shown only to remote clients.

On - Specifies that custom errors are enabled. If no defaultRedirect attribute is specified, users see a generic error. The custom errors are shown to the remote clients and to the local host.

Off - Specifies that custom errors are disabled. The detailed ASP.NET errors are shown to the remote clients and to the local host.

RemoteOnly - Specifies that custom errors are shown only to the remote clients, and that ASP.NET errors are shown to the local host.

By default, the mode value is set to RemoteOnly.

Previously I had no config entry for customErrors in web.config, so default mode was turned on. When there was an error in a view itself, it was resulting in a redirect to default customErrors url - Error.aspx, which was in turn resulting in previously shown exception:

System.InvalidOperationException: The view 'Error' or its master was not found. The following locations were searched:
~/Views/DynamicPage/Error.aspx
~/Views/DynamicPage/Error.ascx
~/Views/Shared/Error.aspx
~/Views/Shared/Error.ascx
~/Views/DynamicPage/Error.cshtml
~/Views/Shared/Error.cshtml

This exception was next handled by ErrorController and shown to user.

Now it's ok.

Jarek Waliszko