[英]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.