L'unica soluzione a cui riesco a pensare è quella di utilizzare un controller personalizzato e instradarlo per farlo. Ma non è una soluzione pulita.
Per prima cosa è necessaria una classe PublicController con un metodo di azione GetFile. Ciò presuppone che tutti i file si trovino direttamente nella cartella pubblica/di contenuto. Gestire le cartelle rende le cose più complicate.
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);
}
}
Ora, basta un percorso vicino al fondo della lista dei percorsi che assomiglia a questo:
routes.MapRoute("PublicContent", "{file}", new {controller = "Public", action = "GetFile"});
Il problema è, ora, quando hai appena messo in un nome di controllo come la 'casa 'invece di eseguire il default al metodo di azione Index sul HomeController, si presuppone che si desideri scaricare un file chiamato "Home" dalla directory dei contenuti. Quindi, sopra il percorso del file, è necessario aggiungere una route per ciascun controller in modo che sappia ottenere l'azione Index.
routes.MapRoute("HomeIndex", "Home", new { controller = "Home", action = "Index" });
Così, un modo per aggirare questo è quello di cambiare il percorso migliore per raggiungere:
routes.MapRoute("PublicContent", "{file}.{extension}", new {controller = "Public", action = "GetFile"});
E il metodo di azione a questo:
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);
}
Come ho detto, questo presuppone che tutti i i file si trovano nella directory del contenuto e non nelle sottocartelle. Ma se si voleva fare sottocartelle come Content/css/site.css si potrebbe aggiungere i percorsi come questo:
routes.MapRoute("PublicContent_sub", "{subfolder}/{file}.{extension}", new { controller = "Public", action = "GetFileInFolder" });
routes.MapRoute("PublicContent", "{file}.{extension}", new { controller = "Public", action = "GetFile"});
ora il metodo di azione deve cambiare troppo.
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);
}
Se si avvia sempre più livelli di profondità nella struttura di cartelle, questo diventa più brutto e più brutto. Ma forse questo funzionerà per te. Sono sicuro che speravi in una casella di controllo nelle proprietà del progetto, ma se ce n'è una, non ne so nulla.
Questa è una buona idea. Pensiero molto intelligente. – NerdFury
Questo sembra essere il modo più efficiente per farlo in termini di sforzo e prestazioni. Darò una prova. Grazie! – AlbertVo