views:

314

answers:

3

I am trying to create an MVC application with multiple view, but using a single controller. I started by creating a second route with another property that I could use to redirect to a second folder.

        public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "xml",                                              // Route name
            "xml/{controller}/{action}/{id}",                           // URL with parameters
            new { mode = "xml", controller = "Home", action = "Index", id = "" }  // Parameter defaults
        );

        routes.MapRoute(
            "Default",                                              // Route name
            "{controller}/{action}/{id}",                           // URL with parameters
            new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
        );
    }
    protected void Application_Start()
    {
        RegisterRoutes(RouteTable.Routes);
        SessionManager.Instance.InitSessionFactory("acstech.helpWanted");
        ViewEngines.Engines.Clear();
        ViewEngines.Engines.Add(new ModeViewEngine()); 
    }

I followed that by descending from WebFormViewEngine and changed the path from ~/View to ~/{mode}View. This worked and ran rendered the pages properly. The problem that I ran into is that the Html.ActionLink always uses the mode version no matter what the view rendered. Is this the proper direction for accomplishing my goal, if so what am I missing to get the Action Link to work properly. Below is the ViewEngine. This is a lab test, so some liberties have been taken.

public class ModeViewEngine : WebFormViewEngine
{
    public ModeViewEngine()
    {

    }

    protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
    {
        string mode = String.Empty;
        if (controllerContext.RouteData.Values["mode"] != null)
            mode = controllerContext.RouteData.Values["mode"] as string;
        return new WebFormView(partialPath.Replace("~/Views", "~/" + mode + "Views"), null);
    }

    protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
    {
        string mode = String.Empty;
        if (controllerContext.RouteData.Values["mode"] != null)
            mode = controllerContext.RouteData.Values["mode"] as string;
        return new WebFormView(viewPath.Replace("~/Views", "~/" + mode + "Views"), masterPath);
    }
}
A: 

Why not have your controller just pick a different view based on the mode? Then you can return your Home view or Home_Xml.

I guess your way moves this decision out of the controller and centralizes the logic, but it also requires you to create a matching view in each Mode you have.

JoshBerke
That would work and I could centralize the view by creating a base ApplicationController, but the desire is to have 2 separate view structures.
Thad
A: 

Well the great thing about the Asp.Net framework is that is that is is very extensible. I think you should check out this link. It will have exactly what you are looking for. My opion, along with the authors is to create a ActionFilter and decorate your views in the controller needing XML or even JSON views. I have even seen cases where all the serialization to XML happens in the Filter and that is returned, thus not needing a ViewEngine.

http://jesschadwick.blogspot.com/2008/06/aspnet-mvc-using-custom-view-engines.html

Kyle LeNeau
+1  A: 

Have you tried adding mode="" in the defaults array in the default route? That is, as I understand it, how the "Index" action gets omitted from URLs, so that should in theory make it match your default route I believe.