2014-06-16 24 views
9

tôi dường như không thể có được một tùy chỉnh VirtualPathProvider làm việc trong asp.net MVC 5.VirtualPathProvider trong MVC 5

Phương pháp FileExists trả về true nhưng sau đó các phương pháp getfile không được gọi. Tôi tin rằng điều này là do IIS tiếp quản yêu cầu và không cho phép .NET xử lý nó.

Tôi đã thử đặt RAMMFAR và tạo trình xử lý tùy chỉnh, như trong giải pháp https://stackoverflow.com/a/12151501/801189 nhưng vẫn không có may mắn. Tôi nhận được một lỗi 404.

Provider Tuỳ chỉnh của tôi:

public class DbPathProvider : VirtualPathProvider 
{ 
    public DbPathProvider() : base() 
    { 

    } 

    private static bool IsContentPath(string virtualPath) 
    { 
     var checkPath = VirtualPathUtility.ToAppRelative(virtualPath); 
     return checkPath.StartsWith("~/CMS/", StringComparison.InvariantCultureIgnoreCase); 
    } 

    public override bool FileExists(string virtualPath) 
    { 
     return IsContentPath(virtualPath) || base.FileExists(virtualPath); 
    } 

    public override VirtualFile GetFile(string virtualPath) 
    { 
     return IsContentPath(virtualPath) ? new DbVirtualFile(virtualPath) : base.GetFile(virtualPath); 
    } 

    public override CacheDependency GetCacheDependency(string virtualPath, IEnumerable virtualPathDependencies, DateTime utcStart) 
    { 
     return null; 

    } 

    public override String GetFileHash(String virtualPath, IEnumerable virtualPathDependencies) 
    { 
     return Guid.NewGuid().ToString(); 
    } 
} 

My Tuỳ chỉnh tập tin ảo:

public class DbVirtualFile : VirtualFile 
{ 
    public DbVirtualFile(string path): base(path) 
    { 

    } 

    public override System.IO.Stream Open() 
    { 
     string testPage = "This is a test!"; 
     return new System.IO.MemoryStream(System.Text.ASCIIEncoding.ASCII.GetBytes(testPage)); 
    } 
} 

web.config handler Tôi đã cố gắng để sử dụng, nhưng không thành công. Nó hiện đang cung cấp cho lỗi 500:

<system.webServer> 
<modules runAllManagedModulesForAllRequests="true"> 
    <remove name="FormsAuthenticationModule" /> 
</modules> 

<handlers> 
    <add name="ApiURIs-ISAPI-Integrated-4.0" 
path="/CMS/*" 
verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" 
type="System.Web.Handlers.TransferRequestHandler" 
preCondition="runtimeVersionv4.0" /> 
</handlers> 

Nếu tôi cố gắng hướng đến site.com/CMS/Home/Index, phương pháp FileExists được gọi nhưng kỳ lạ, các tham số recieves VirtualPath chỉ ~/CMS/Nhà.

Thêm điểm ngắt, có vẻ như đối với url site.com/CMS/Home/Index, phương pháp FileExists liên tục được gọi. Điều này có thể gây ra một đệ quy vô hạn, gây ra lỗi máy chủ nội bộ.

Trả lời

12

Nó thực sự không liên quan gì đến IIS, và trên thực tế sự nhầm lẫn về thứ tự của các sự kiện. Có vẻ như tôi không hiểu rằng một phương thức hành động định tuyến phải trả về một khung nhìn, VirtualPathProvider sẽ cố gắng giải quyết, thay vì truy cập trực tiếp vào VirtualPathProvider.

tôi có thể tạo một bộ điều khiển đơn giản gọi là ContentPagesController với một hành động GetPage duy nhất:

public class ContentPagesController : Controller 
    { 
     [HttpGet] 
     public ActionResult GetPage(string pageName) 
     { 
      return View(pageName); 
     } 
    } 

sau đó tôi thiết lập tuyến đường của tôi để phục vụ các trang ảo:

routes.MapRoute(
name: "ContentPageRoute", 
url: "CMS/{*pageName}", 
defaults: new { controller = "ContentPages", action = "GetPage" }, 
constraints: new { controller = "ContentPages", action = "GetPage" } 
); 

tôi đăng ký VirtualPathProvider tùy chỉnh của tôi trước khi tôi đăng ký các tuyến đường của tôi, trong globals.asax.cs.

Bây giờ giả sử tôi có một trang trong cơ sở dữ liệu của tôi với url tương đối/CMS/Home/AboutUs. Tham số pageName sẽ có giá trị Home/AboutUs và lệnh return View() sẽ hướng dẫn VirtualPathProvider tìm kiếm các biến thể của tệp ~/Views/ContentPages/Home/AboutUs.cshtml.

Một vài trong số các biến thể nó sẽ được tìm kiếm bao gồm:

~/Views/ContentPages/Home/AboutUs.aspx 
~/Views/ContentPages/Home/AboutUs.ascx 
~/Views/ContentPages/Home/AboutUs.vbhtml 

Tất cả bây giờ bạn cần làm là kiểm tra VirtualPath được truyền cho phương thức GetFiles, sử dụng một cơ sở dữ liệu tra cứu hoặc tương đương. Đây là một cách đơn giản:

private bool IsCMSPath(string virtualPath) 
     { 
      return virtualPath == "/Views/ContentPages/Home/AboutUs.cshtml" || 
       virtualPath == "~/Views/ContentPages/Home/AboutUs.cshtml"; 
     } 

     public override bool FileExists(string virtualPath) 
     { 
      return IsCMSPath(virtualPath) || base.FileExists(virtualPath); 
     } 

     public override VirtualFile GetFile(string virtualPath) 
     { 
      if (IsCMSPath(virtualPath)) 
      { 
       return new DbVirtualFile(virtualPath); 
      } 

      return base.GetFile(virtualPath); 
     } 

Tệp ảo tùy chỉnh sẽ được tạo và trả về trình duyệt theo phương pháp GetFile.

Cuối cùng, một công cụ xem tùy chỉnh có thể được tạo để cung cấp cho các đường dẫn xem ảo khác nhau được gửi đến VirtualPathProvider.

Hy vọng điều này sẽ hữu ích.

+0

Bạn trả lời là hữu ích. Tôi nhận được mã của tôi làm việc, tuy nhiên quan điểm là không để render sau khi "System.IO.Stream Open()". Bạn có gặp phải vấn đề tương tự không? –

+0

Không, tôi không tin tôi đã làm. Bạn đang thấy lỗi gì? –

+0

Chỉ cần một html trống được hiển thị sau khi mở(). Mở() thành công được xem từ DB –

Các vấn đề liên quan