views:

393

answers:

1

I am attempting to impliment a custom view engine to serve mobile views based on the user agent. I am following Scott Hanselman's approach from this blog post.

I have inherited from the WebFormsViewEngine and overridden the FindView method the same way that Scott describes in his blog.

I then added a few lines to my Global.asax Application_Start method to clear the view engine collection and add a new instance of my view engine.

After some testing it would appear that MVC is ignoring my view engine. When it failed to find my custom views based on the user agent of the browser I resorted to hardcoding the custom path to to append to the view and it still managed to fall back on the default view. I set a breakpoint in my FindView method and sure enough, it's not being called at all.

How can I get my custom view engine to work? Any help will be much appreciated.

My view engine looks like this:

public class MyViewEngine: WebFormsViewEngine
{
    public override ViewEngineResult FindView (ControllerContext controllerContext, string viewName, string masterName, bool useCache)
    {
         ViewEngineResult result = null;

         //Serve a special view for iPhones
         if (UserAgentIs(controllerContext, "iPhone"))
         {
              result = base.FindView(controllerContext, "Mobile/iPhone/" + viewName, masterName, useCache);
         }

         //If no special view is found, fall back to the default view
         if (result == null || result.View == null)
         {
              result = base.FindView(controllerContext, viewName, masterName, useCache);
         }

         return result;
    }

    private bool UserAgentIs(ControllerContext controllerContext, string userAgentToTest)
    {
         return (controllerContext.HttpContext.Request.UserAgent.IndexOf(userAgentToTest, StringComparison.OrdinalIgnoreCase) > 0);
    }
}

And in my Global.asax:

protected void Application_Start()
{
    RegisterRoutes(RouteTable.Routes);
    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new MyViewEngine());
}

When this setup didn't work I even tried to simplify my FindView method to this:

public override ViewEngineResult FindView (ControllerContext controllerContext, string viewName, string masterName, bool useCache)
    {
         ViewEngineResult result = null;
         result = base.FindView(controllerContext, "Mobile/iPhone/" + viewName, masterName, useCache);
         return result;
    }

And that didn't work either. It still returned the default view. And yes, the view page and master page that should be found by that statement do actually exist. I'm pretty stumped as to why this is not working.

+2  A: 

Well this is certainly embarrasing:

When I wrote my view engine I was following the blog post from Scott Hanselman (see my original post for the link). I delcared my view engine class then decided I would just copy and paste Scott's code into my class and modify as needed. I accidentally copied his code WITH the class definition into my class creating a nested class. Therefore my view engine didn't actually contain an override for the FindView method and naturally the one in the nested class would never be called!

The lesson: when using code found online don't copy and paste! Always type it yourself.

Thanks to everyone who check this question out and tried to help me.

I'll go stand in the corner of shame and embarrassment now!

Jeff French
:) I'm glad you solved the issue.
çağdaş