Маршрутизация и множественные представления в Asp.Net MVC
У меня есть метод действия контроллера, который должен иметь возможность обслуживать несколько представлений. Эти представления генерируются XSLT.
Теперь в представлениях есть изображения (по сотни), и у каждого вида должна быть своя папка с изображениями, на которые можно сослаться. Как это должно работать?
Если у изображений в исходном XML есть ссылка, представляющая собой простой относительный путь ("images/image.svg"), как я могу получить этот путь для разрешения в представлении в приложении?
Если бы я мог поместить папку с изображениями в ту же папку, что и представление, и использовать там относительный путь, это было бы легко, но это не сработало, потому что я обслуживаю несколько представлений из действия. Вот маршрутизация:
routes.MapRoute(
"Parameter",
"{controller}/{action}/{lang}/{prod}",
new { controller = "Manuals", action = "Product", lang = "en-US", prod = "sample" }
);
Поэтому, если я попытаюсь использовать относительный путь для атрибута img src, он разрешится примерно так: "/Manuals/Product/en-US/images/image.svg"
И на самом деле, если я поставлю его относительно вида, изображение будет находиться в "/Views/Manuals/en-US/images/image.svg"
Так нет ли способа иметь относительные пути к изображениям в Asp.Net MVC? Или я неправильно понимаю маршрутизацию MVC?
1 ответ
Это то, что я сделал раньше:
public class MvcApplication : HttpApplication
{
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
MapRoute(routes, "", "Home", "Index");
/* other routes */
MapRoute(routes, "{*url}", "Documentation", "Render");
}
}
Теперь любые несоответствующие маршруты передаются в DocumentationController
, Контроллер моей документации выглядит следующим образом:
public class DocumentationController : Controller
{
public ActionResult Render(string url)
{
var md = new MarkdownSharp.Markdown();
// The path is relative to the root of the application, but it can be anything
// stored on a different drive.
string path = Path.Combine(Request.MapPath("~/"), GetAppRelativePath().Replace('/', '\\')) + ".md";
if (System.IO.File.Exists(path))
{
string html = md.Transform(System.IO.File.ReadAllText(path));
return View("Render", (object)html);
}
// return the not found view if the file doesn't exist
return View("NotFound");
}
private string GetAppRelativePath()
{
return HttpContext.Request.AppRelativeCurrentExecutionFilePath.Replace("~/", "");
}
}
Все, что нужно сделать, - это найти файлы уценки и соответствующим образом отобразить их. Чтобы обновить это для вашего случая, вы можете сделать следующее:
routes.MapRoute(
"Parameter1",
"{controller}/{action}/{lang}/{*url}",
new { controller = "Manuals", action = "Download", lang = "en-US", prod = "sample" }
);
Убедитесь, что это после {controller}/{action}/{lang}/{prod}
маршрут. Это должно вызвать URL, такой как /Manuals/Product/en-US/images/image.svg
или даже images/image.svg
(если браузер находится в /Manuals/Product/en-US/sample
ссылаться на Download
действие. Затем вы можете адаптировать код, который я написал, для сопоставления этого URI с физическим местоположением. Проблема, с которой вы можете столкнуться, заключается в том, что "изображения" считаются продуктом и что /Manuals/Product/en-US/images
Казалось бы, это продукт.
Действие "Изображения" может выглядеть следующим образом.
public ActionResult Download(string url)
{
/* figure out physical path */
var filename = /* get filename form url */
var fileStream = [...];
Response.Headers.Remove("Content-Disposition");
Response.Headers.Add("Content-Disposition", "inline; filename=" + filename);
string contentType = "image/jpg";
return File(fileStream, contentType, filename);
}
Вы можете получить больше информации о FileResult на MSDN.