1

I have two sites quite similar that shares lot in common in some places but some other places are totally different. So i created three mvc4 applications MainSiteA, MainSiteB, SharedUI and using RazorGenerated for precompiling (and share) views among two sites. Current problem is my SharedUI view takes priority from a compiled or non-compiled view on the MainSiteA and I want it to make it vice-versa.

Having:

SiteA:
    Views/Index.cshtml (a)

SiteB:
    Views/Index.cshtml (b)
    Views/Header.cshtml (b)

SharedUI:
    Views/Index.cshtml (s)
    Views/Header.cshtml (s)
    Views/Footer.cshtml (s)

How can i make to access specific pages depending on site in this way:

SiteA
Index.cshtml (a)
Header.cshtml (s)
Footer.cshtml (s)

SiteB
Index.cshtml (b)
Header.cshtml (b)
Footer.cshtml (s)

I want MVC to look first on it's own MVC Application, if view is not found go a look on the shared library (SharedUI) for the view.

Bart Calixto
  • 19,210
  • 11
  • 78
  • 114
  • 1
    I've implemented a similar solution here: http://stackoverflow.com/questions/9838766/implementing-a-custom-razorviewengine – Liam Oct 18 '12 at 13:31

1 Answers1

5

RazorGenerator.Mvc 2.1.0 includes CompositePrecompiledMvcEngine class. If you use RazorGenerator to precompile your views within each project, you could now use following engine registration for the site A:

var engine = new CompositePrecompiledMvcEngine(
    PrecompiledViewAssembly.OfType<SomeSharedUIClass>(),
    PrecompiledViewAssembly.OfType<SomeSiteAClass>(
        usePhysicalViewsIfNewer: HttpContext.Current.IsDebuggingEnabled));

ViewEngines.Engines.Insert(0, engine);
VirtualPathFactoryManager.RegisterVirtualPathFactory(engine);

And similar code for the Site B:

// ...
    PrecompiledViewAssembly.OfType<SomeSiteBClass>(
// ...

When you are registering assemblies in engine's constructor, it builds hash table where each element contain mapping between view's virtual path (key) and compiled view type (value). If such key was already registered with one of previous assembly, it simply overrides this mapping with the type from the current assembly.

So, after SharedUI assembly registration, the hash table would contain following mappings:

"~/Views/Index.cshtml"   -> SharedUI.Index
"~/Views/Header.cshtml"  -> SharedUI.Header
"~/Views/Footer.cshtml"  -> SharedUI.Footer

When you put SiteA assembly registration, hash table would contain:

"~/Views/Index.cshtml"   -> SiteA.Index
"~/Views/Header.cshtml"  -> SharedUI.Header
"~/Views/Footer.cshtml"  -> SharedUI.Footer

And if you put another assembly with views "~/Views/Footer.cshtml" and "~/Views/Sidebar.cshtml", hash table would contain:

"~/Views/Index.cshtml"   -> SiteA.Index
"~/Views/Header.cshtml"  -> SharedUI.Header
"~/Views/Footer.cshtml"  -> Another.Footer
"~/Views/Sidebar.cshtml" -> Another.Sidebar
odinserj
  • 954
  • 9
  • 21
  • I don't understand, do you need to register an engine in each project, or just once in the project that has the shared views (and RazorGenerator)? – h bob Jan 25 '15 at 10:26
  • 1
    @hbob, yep, you should register an engine in each project that wants to use those shared views. – odinserj Jan 26 '15 at 09:59
  • OK, so each "shared" MVC project will register the default `PrecompiledMvcEngine`, but each "child" MVC project will register the `CompositePrecompiledMvcEngine`? – h bob Apr 19 '15 at 19:21