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);
}
}
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.
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
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.