Размещение 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" />