Размещение js файлов в папке представлений
Я пытаюсь разместить свои файлы javascript с моими представлениями.
У меня есть следующее расположение файла js.
/Views/Home/Home.js
Однако при ссылке с тегом script это приводит к ошибке 404.
В соответствии с следующим вопросом SO: ASP.NET MVC - Где вы помещаете ваши .js файлы, если вы не хотите их хранить в /Scripts?
Я добавил file.js в мои маршруты регистрации. (Не удалось решить проблему)
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{file}.js");
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
}
Как я могу хранить и ссылаться на мои js файлы рядом с моими представлениями?
Ответы
Ответ 1
Проблема заключается в том, что по соображениям безопасности web.config, находящийся внутри папки Views, блокирует все запросы к файлам в этой папке. Это то, что вы найдете в файле конфигурации:
<httpHandlers>
<add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
И для IIS7:
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
Решение
Вы можете изменить подстановочный знак, чтобы поймать только файлы .cshtml.
<httpHandlers>
<add path="*.cshtml" verb="*" type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*.cshtml" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
С этим шаблоном файлы .js не будут заблокированы.
Ответ 2
Я лично не люблю играть с httpHandlers по соображениям безопасности. Я хотел сделать то же самое, чтобы избежать необходимости поддерживать одну и ту же структуру папок дважды (в виде и в папке скриптов). Итак, цель состоит в том, чтобы сохранить .js в той же папке, что и мой .cshtml, и больше не имеет ошибки 404.
Решение
Чтобы достичь этой цели, я использую пользовательский HtmlHelper и контроллер для вызовов javascript.
HtmlHelper
public static MvcHtmlString JScriptBlock<TModel>(
this HtmlHelper<TModel> html
)
{
// Get the physical path of the .js file we are looking for.
string path = ((System.Web.Mvc.RazorView)html.ViewContext.View).ViewPath.Replace(".cshtml", ".js");
path = HostingEnvironment.MapPath(path);
if (!File.Exists(path))
return null;
// We store the physical path in a session variable with GUID as the key
string guid = Guid.NewGuid().ToString();
HttpContext.Current.Session[guid] = path;
// Create the script block where the src points to the JScript controller. We give the GUID as parameter.
return MvcHtmlString.Create("<script src='/JScript/?id=" + guid + "'/>");
}
JScript-контроллер
public ActionResult Index(string id)
{
// id correspond to the guid generated by the MSRJScript helper
// We look if the physical path of the .js is available in the session variables
if(Session[id] == null)
return new HttpStatusCodeResult(HttpStatusCode.Forbidden);
// If the physical path was found, we simply send the file back to the browser.
string path = Session[id].ToString();
Session.Remove(id);
return File(path, "application/javascript");
}
Как только вы закончите, вам просто нужно добавить следующий код в View/PartialView
@Html.JScriptBlock()
Ответ 3
На мой взгляд, это хороший способ: он делает код простым и не затрагивает проблему безопасности с другими типами ресурсов.
Просто добавьте в раздел обработчики следующее:
<add name="JavaScriptHandler" path="*.js" verb="*" preCondition="integratedMode" type="System.Web.StaticFileHandler" />