簡體   English   中英

如何修改 ASP.NET MVC static 文件根目錄

[英]How to modify ASP.NET MVC static file root

我希望能夠重組我的 ASP.NET MVC 站點結構,以更接近 Rails 的方式(我們在我的公司同時使用 rails 和 ASP.net)。

在 Rails 中,有一個充當站點根目錄的“公共”文件夾。 For example, I could drop in a "test.html" and access the file with the url http://domain.com/test.html which would serve up the static html file.

在 asp.net MVC 中有一個“內容”文件夾,我想作為根文件夾。 So instead of accessing http://domain.com/content/myfile.html , i want to be able to do http://domain.com/myfile.html .

我知道我可以將文件放在項目的根目錄中,但我需要對許多文件執行此操作,包括 css、js、html、圖像等,並且希望跨 rails 和 aspnetmvc 共享一些標准化資產。

有沒有辦法做到這一點?

還有另一種可能的解決方案。 您可以使用重寫規則來為您處理此問題,而不是使用代碼。 如果您使用的是 IIS 7 或更高版本,則可以使用微軟的 URL Rewrite Module。

像下面這樣的規則可能會做到這一點:

<rule name="Rewrite static files to content" stopProcessing="true">
  <match url="^([^/]+(?:\.css|\.js))$" />
  <conditions>
      <add input="{APPL_PHYSICAL_PATH}content{SCRIPT_NAME}" matchType="IsFile" />
  </conditions>
  <action type="Rewrite" url="/content/{R:1}" />
</rule>

該規則檢查對 css 或站點根目錄下的 js 文件的請求。 然后它檢查文件是否存在於內容文件夾中。 如果存在,則重寫將返回內容文件夾中的文件。 我只測試了一點,但它似乎工作。 它當然需要更多的測試和可能的改進。

我能想到的唯一解決方案是使用自定義 controller 和路由為您執行此操作。 但這不是一個干凈的解決方案。

首先,您需要一個帶有 GetFile 操作方法的 PublicController class。 這假定所有文件都直接位於 public/content 文件夾中。 處理文件夾會使事情變得更加復雜。

public class PublicController : Controller
{
    private IDictionary<String, String> mimeTypes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
                                                        {{"css", "text/css"}, {"jpg", "image/jpg"}};

    public ActionResult GetFile(string file)
    {
        var path = Path.Combine(Server.MapPath("~/Content"), file);

        if (!System.IO.File.Exists(path)) throw new HttpException(404, "File Not Found");
        var extension = GetExtension(file); // psuedocode
        var mimetype = mimeTypes.ContainsKey(extension) ? mimeTypes[extension] : "text/plain";
        return File(path, mimetype);
    }
}

現在,您只需要一條靠近路線列表底部的路線,如下所示:

routes.MapRoute("PublicContent", "{file}", new {controller = "Public", action = "GetFile"});

問題是,現在當您只輸入 controller 名稱(如“Home”)而不是默認為 HomeController 上的 Index 操作方法時,它假定您要從內容目錄下載一個名為“Home”的文件。 因此,在文件路徑上方,您需要為每個 controller 添加一個路徑,以便它知道獲取索引操作。

routes.MapRoute("HomeIndex", "Home", new { controller = "Home", action = "Index" });

因此,解決此問題的一種方法是將路線更改為:

routes.MapRoute("PublicContent", "{file}.{extension}", new {controller = "Public", action = "GetFile"});

以及對此的操作方法:

    public ActionResult GetFile(string file, string extension)
    {
        var path = Path.Combine(Server.MapPath("~/Content"), file + "." + extension);

        if (!System.IO.File.Exists(path)) throw new HttpException(404, "File Not Found");

        var mimetype = mimeTypes.ContainsKey(extension) ? mimeTypes[extension] : "text/plain";
        return File(path, mimetype);
    }

就像我說的,這假設所有文件都在內容目錄中,而不是在子文件夾中。 但是,如果您想做 Content/css/site.css 之類的子文件夾,您可以像這樣添加您的路線:

        routes.MapRoute("PublicContent_sub", "{subfolder}/{file}.{extension}", new { controller = "Public", action = "GetFileInFolder" });
        routes.MapRoute("PublicContent", "{file}.{extension}", new { controller = "Public", action = "GetFile"});

現在動作方法也必須改變。

    public ActionResult GetFile(string file, string extension)
    {
        return GetFileInFolder("", file, extension);
    }

    public ActionResult GetFileInFolder(string subfolder, string file, string extension)
    {
        var path = Path.Combine(Server.MapPath("~/Content"), subfolder, file + "." + extension);

        if (!System.IO.File.Exists(path)) throw new HttpException(404, "File Not Found");

        var mimetype = mimeTypes.ContainsKey(extension) ? mimeTypes[extension] : "text/plain";
        return File(path, mimetype);
    }

如果您開始在文件夾結構中深入多個級別,這將變得越來越丑陋。 但也許這對你有用。 我確定您希望項目屬性中有一個復選框,但如果有,我不知道。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM