问题
I have read dozens of related threads and made my very simple virtual provider from samples.
But it does not render virtual file stream. just showing plan text.
Here is the output.
@inherits System.Web.Mvc.WebViewPage
@{ViewBag.Title = "Hellow World !";}
<h2>Hellow World !</h2>
There are related threads about this, but they are not saying how they solved it or the solution does not work. I can't find what did I wrong.
- VirtualPathProvider not parsing razor markup
- MVC3 Custom VirtualPathProvider not rendering Razor
- Pulling a View from a database rather than a file
- How to specify route to shared views in MVC3 when using Areas
- ASP.NET MVC load Razor view from database
- How to load views from a Class Library project?
and there are a lot more...
What's wrong ?
Here is my test code. (Global.asax and that's all that I changed.)
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(
new MyProvider());
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AuthConfig.RegisterAuth();
}
}
public class MyProvider : VirtualPathProvider
{
public override bool FileExists(string virtualPath)
{
if (Previous.FileExists(virtualPath))
return true;
else
// ~/Infra is the test url
return virtualPath.StartsWith("/Infra") || virtualPath.StartsWith("~/Infra");
}
public override VirtualFile GetFile(string virtualPath)
{
if (Previous.FileExists(virtualPath))
return base.GetFile(virtualPath);
else
return new MyVirtualFile(virtualPath);
}
public class MyVirtualFile : VirtualFile
{
public MyVirtualFile(string virtualPath) : base(virtualPath) { }
public override Stream Open()
{
//Loading stream from seperate dll shows just plain text
//System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFile(
// System.IO.Path.Combine(HttpRuntime.BinDirectory, "Infra.dll"));
//return assembly.GetManifestResourceStream("Infra.Views.Home.Index.cshtml");
//Changed to string but also it shows plain text.
return new System.IO.MemoryStream(System.Text.ASCIIEncoding.UTF8.GetBytes(
"@inherits System.Web.Mvc.WebViewPage \r\n <h2>Hellow World !</h2>"));
}
}
}
回答1:
I can see the question is a bit old but I just encountered the same error. I believe the problem is the test URL. I don't have time to fully investigate but I think that unless the supplied URL is in an expected format (ASP.NET MVC view engine is conventions based) then it might not be using razor as a view engine; I'm not sure if that is the cause but some examples using the 'Infra' string you are using:
New MVC 4 Project in home controller:
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
dynamic x = new ExpandoObject();
return View("Infra-test.cshtml", x);
}
This calls into:
private bool IsPathVirtual(string virtualPath)
with virtualPath
set to '/Views/Home/Infra-test.cshtml.aspx'
. It has added an aspx extension onto the end which leads me to believe it is not using razor to compile the view. A small modification to the virtual path provider will see the links below working:
public override bool FileExists(string virtualPath)
{
if (Previous.FileExists(virtualPath))
return true;
else
// prevent view start compilation errors
return virtualPath.StartsWith("/Infra") && !virtualPath.Contains("_ViewStart");
}
URL's that will work:
return View("/Infra/test.cshtml", x);
return View("/Infra/one/test.cshtml", x);
return View("/Infra/one/two/test.cshtml", x);
these do not work:
return View("/Infra", x);
return View("/Infra/test", x);
For the sample to work you will also need to implement GetCacheDependency
; otherwise, it will throw an exception when it fails to find a file for the virtual path on the disk, below is a simple example. Read the docs to implement properly.
private bool IsVirtualPath(string virtualPath)
{
return virtualPath.StartsWith("/Infra") && !virtualPath.Contains("_ViewStart");
}
public override CacheDependency GetCacheDependency(string virtualPath, System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart)
{
if (IsVirtualPath(virtualPath))
return null;
return Previous.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
}
来源:https://stackoverflow.com/questions/15332247/is-there-any-virtualpathprovider-working-sample-in-mvc4-razor