Jeff
Jeff

Reputation: 36553

ASP .NET MVC VirtualPathProvider

I am writing a VirtualPathProvider to dynamically load my MVC views, which are located in a different directory. I successfully intercept the call before MVC (in FileExists), but in my VirtualPathProvider, I get the raw, pre-routed url like:

~/Apps/Administration/Account/LogOn

Personally, I know that MVC will look for

~/Apps/Administration/Views/Account/LogOn.aspx

and that I should be reading the file contents from

D:\SomeOtherNonWebRootDirectory\Apps\Administration\Views\Account\LogOn.aspx

but I'd rather not hard code the logic to "add the directory named Views and add aspx to the end".

Where is this logic stored and how can I get it into my virtual path provider?

Thanks. Sorry if I'm not being clear.

Upvotes: 2

Views: 2665

Answers (3)

Jeff
Jeff

Reputation: 36553

The answer was that MVC was not finding my controller properly. If MVC does in fact find your controller properly, there should be two requests processed by the VirtualPathProvider:

  1. An initial request with the acutal url requested (ie. http://.../Account/LogOn).

  2. A subsequent FileExists check for http://.../Views/Account/LogOn.aspx, after the request in 1. returns false calling FileExists. This actually retuns the aspx content.

Upvotes: 0

Praveen
Praveen

Reputation: 772

As SLaks mentioned above, you need to create a Custom View Engine and add your view-finding logic in the FindView method.

public class CustomViewEngine : VirtualPathProviderViewEngine

{

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

    {
        //Set view path
        string viewPath = GetCurrentViewPath();

        //Set master path (if need be)
        string masterPath = GetCurrentMasterPath();

        return base.FindView(controllerContext, viewPath, masterPath, useCache);
    }

}

In the Application_Start, you can register your View Engine like this:

 ViewEngines.Engines.Clear();
 ViewEngines.Engines.Add(new CustomViewEngine());

Upvotes: 0

SLaks
SLaks

Reputation: 887195

Edited

You need to make a class that inherits WebFormViewEngine and sets the ViewLocationFormats property (inherited from VirtualPathProviderViewEngine).

The default values can be found in the MVC source code:

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

    AreaMasterLocationFormats = new[] {
        "~/Areas/{2}/Views/{1}/{0}.master",
        "~/Areas/{2}/Views/Shared/{0}.master",
    };

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

    AreaViewLocationFormats = new[] {
        "~/Areas/{2}/Views/{1}/{0}.aspx",
        "~/Areas/{2}/Views/{1}/{0}.ascx",
        "~/Areas/{2}/Views/Shared/{0}.aspx",
        "~/Areas/{2}/Views/Shared/{0}.ascx",
    };

    PartialViewLocationFormats = ViewLocationFormats;
    AreaPartialViewLocationFormats = AreaViewLocationFormats;
}

You should then clear the ViewEngines.Engines collection and add your ViewEngine instance to it.

Upvotes: 4

Related Questions