2

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.

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

8 Comments

Can you please be more specific? Thanks.
Thanks. And how do I get from these format strings to have my VirtualPathProvider to know where to read the file from?
In other words, if my VirtualPathProvider gets a request for ~/Apps/Administration/Account/LogOn, how do I use the above information to know to look for D:\SomeOtherPath\Apps\Administrations\Views\Account\LogOn.aspx?
That shouldn't be happening. Does your VPP get any other requests?
I'm not sure what you're asking... If I register my VPP before MVC, it gets all requests. If I register it after, MVC handles the request first. Also, please note that the source diredctory I want to read from is OUTSIDE of the actual web-app's base directory...specifically it's in a zip file.
|
0

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

Comments

0

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.

1 Comment

After the first one (which must return false to stop IIS trying to serve it as a static file instead of running the controller action) FileExists gets called with both "~/Views/Account/LogOn.aspx" and "/AppName/Views/Account/LogOn.aspx" - both of these need to return true.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.