Single Controller with Multiple Views

2019-06-04 23:36发布

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

3条回答
何必那么认真
2楼-- · 2019-06-05 00:04

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.

查看更多
萌系小妹纸
3楼-- · 2019-06-05 00:14

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

查看更多
劳资没心,怎么记你
4楼-- · 2019-06-05 00:18

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.

查看更多
登录 后发表回答