Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
513 views
in Technique[技术] by (71.8m points)

asp.net mvc 4 - MVC4 Razor Custom View Locator

I'm working on an MVC4 application that is designed to service two domains. Most of our content will be shared across the domains, but sometimes we will need to render different markup (using Razor) depending on which site the request came from.

Ideally, I want a convention-based approach that allows me to have a folder structure like this:

Views
+ Domain1
    + ControllerName
        View1
        View2
+ Domain2
    + ControllerName
        View1
+ ControllerName
   View1
   View2

When resolving a view, I would like to check the domain-specific folder first, then the general views folder.

My first thoughts were to implement a custom view engine that inherits RazorViewEngine that would swap the ViewLocationFormats strings depending on the request domain. Unfortunately all this stuff is buried in the VirtualPathProviderEngine and can't be overridden.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It turns out that the answer was to create a custom view engine (inherited from RazorViewEngine) for each domain that knows about the domain-specific folders:

public class Domain1ViewEngine() : RazorViewEngine
{
        ...

        ViewLocationFormats = new[]
        {
            "~/Views/Domain1/{1}/{0}.cshtml",
            "~/Views/Domain1/Shared/{0}.cshtml"
        };

        ...
}

I then needed to override the FindView and FindPartialView methods so that it only attempted to find locate views if the request had come from the right domain:

public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
    if ([THIS IS NOT THE RIGHT DOMAIN]) 
    {
        return new ViewEngineResult(new string[] { });
    }

    return base.FindView(controllerContext, viewName, masterName, useCache);
}

To complete the process I registered the view engine in Global.asax.cs in the usual way:

protected void Application_Start()
{
    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new Domain1ViewEngine());
    ViewEngines.Engines.Add(new RazorViewEngine());
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...