سؤال

currently I'm developing on an older ASP.NET MVC 1 Application, to add theme support. I've looked around the web and was able to build my own ViewEngine which works quit nice so far. Only one problem is banging my had.

I've overwritten following method for WebFormViewEngine:

public override ViewEngineResult FindView(
    ControllerContext controllerContext, 
    string viewName, 
    string masterName, 
    bool useCache)

In this method I'm setting up the location formats for the theme support. Unfortunately the masterName Parameter is always empty! So I need to check

if (string.IsNullOrEmpty(masterName))    
    masterName = "Site";

always by myself to get the engine working. But as I've several master files, this solution sucks, as soon as a view requires another master than "Site". Does anybody know, how I can get the master views name in this Method?

هل كانت مفيدة؟

المحلول

Solved it by myself. After a lot of researching, I've found following snippet, which helped me:

private void RenderViewPage(ViewContext context, ViewPage page)
            {
                if (!String.IsNullOrEmpty(MasterPath)) {
                    page.MasterLocation = MasterPath;
                } else {
                    if (sc.WIP.CarharttIMD.Common.Config.GetStringValue("Theme") != "Default")
                        page.PreInit += new EventHandler(page_PreInit);
                }

                page.ViewData = context.ViewData;
                page.RenderView(context);
            }

void page_PreInit(object sender, EventArgs e)
            {
                ViewPage page = sender as ViewPage;
                //test for Default theme path, and replace with current theme
                string defaultthemepath = string.Format("{0}Content/Default", page.Request.ApplicationPath);
                if (!string.IsNullOrEmpty(page.MasterPageFile) && !page.MasterPageFile.ToLower().StartsWith(defaultthemepath.ToLower()))
                {
                    string masterPagePath = page.MasterPageFile;
                    int lastIndexOfSlash = masterPagePath.LastIndexOf('/');
                    string masterPageName = masterPagePath.Substring(lastIndexOfSlash + 1, masterPagePath.Length - lastIndexOfSlash - 1);
                    string newMaster = string.Format(
                        "~/Content/{0}/Views/Shared/{1}",
                        Common.Config.GetStringValue("Theme"),
                        masterPageName
                    );
                    if (File.Exists(page.Server.MapPath(newMaster)))
                        page.MasterLocation = newMaster;
                }
            }

Had to subclass the WebViewForm and handeling the master File in the PreInit event.

نصائح أخرى

Solved kind of the same problem but the approach was little different.

Suppose you have alternative views tree in Theme folder then you have to set in your class MyViewEngine derived from WebFormViewEngine:

base.MasterLocationFormats =  new[] {
                        "~/Theme/Views/{1}/{0}.master", 
                        "~/Theme/Views/Shared/{0}.master"
                    }
                ).ToArray();

base.ViewLocationFormats = viewLocationFormats.Concat(
                    new[] {
                        "~/Theme/Views/{1}/{0}.aspx", 
                        "~/Theme/Views/Shared/{0}.aspx", 
                    }
                ).ToArray()

and override method:

protected override bool FileExists(ControllerContext controllerContext, string virtualPath)
{
    return System.IO.File.Exists(controllerContext.HttpContext.Server.MapPath(virtualPath));
}

In Application_Start method from Global.asax.cs file add:

System.Web.Mvc.ViewEngines.Engines.Clear();
System.Web.Mvc.ViewEngines.Engines.Add(new WebFormThemeViewEngine());

Alternatively, you could probably use some of the techniques I've described in this answer: how to change the themes in asp.net mvc 2

It's on MVC3 and Razor, but everything except the View should work just fine on MVC 1 as well.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top