Есть ли рабочий образец VirtualPathProvider в mvc4 razor?

Я прочитал десятки связанных тем и сделал своего очень простого виртуального провайдера из образцов.

Но он не отображает поток виртуальных файлов. просто отображается текст плана.

Вот результат.

@inherits System.Web.Mvc.WebViewPage 
@{ViewBag.Title = "Hellow World !";}
<h2>Hellow World !</h2>

Есть связанные темы по этому поводу, но они не говорят, как они решили это или решение не работает. Я не могу найти, что я сделал не так.

и многое другое ...

Что случилось ?

Вот мой тестовый код. (Global.asax и это все, что я изменил.)

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>"));
        }
    }
}

person whangsy    schedule 11.03.2013    source источник


Ответы (1)


Я вижу, что вопрос немного устарел, но я столкнулся с той же ошибкой. Я считаю, что проблема в тестовом URL. У меня нет времени на полное исследование, но я думаю, что, если предоставленный URL-адрес не находится в ожидаемом формате (механизм представления ASP.NET MVC основан на соглашениях), он может не использовать razor в качестве механизма представления; Я не уверен, что это причина, но несколько примеров с использованием строки Infra, которую вы используете:

Новый проект MVC 4 в домашнем контроллере:

public ActionResult Index()
{
    ViewBag.Message = "Welcome to ASP.NET MVC!";

    dynamic x = new ExpandoObject();

    return View("Infra-test.cshtml", x);
}

Это требует:

private bool IsPathVirtual(string virtualPath)

с virtualPath, установленным на '/Views/Home/Infra-test.cshtml.aspx'. Он добавил расширение aspx в конец, что наводит меня на мысль, что он не использует бритву для компиляции представления. Небольшая модификация поставщика виртуального пути приведет к тому, что приведенные ниже ссылки будут работать:

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-адреса, которые будут работать:

return View("/Infra/test.cshtml", x);
return View("/Infra/one/test.cshtml", x);
return View("/Infra/one/two/test.cshtml", x);

они не работают:

return View("/Infra", x);
return View("/Infra/test", x);

Чтобы образец работал, вам также необходимо реализовать GetCacheDependency; в противном случае он выдаст исключение, если не сможет найти файл для виртуального пути на диске, ниже приведен простой пример. Прочтите документацию для правильной реализации.

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);
}
person Ian Gibson    schedule 06.09.2013
comment
Не забудьте ПЕРЕЗАГРУЗИТЬ IIS Express после каждого изменения или настройки, потому что он кэширует местоположения, файлы и, по-видимому, результаты, даже если я не слишком его установил, и все такое. Я ударил головой, а затем после перезапуска IIS понял, что все работает без существующего имени файла, без встроенного ресурса, если у него есть '.cshtml', и убедился, что я тоже переопределил бит каталога. Спасибо, что помогли мне частично создать мои решения. Фух! - person Piotr Kula; 14.07.2014