2012-03-08 19 views
10

Estoy tratando de colocar mis archivos javascript con mis vistas.Colocación de archivos js en la carpeta de vistas

Tengo la siguiente ubicación de archivo js. /Views/Home/Home.js

Sin embargo, cuando se hace referencia a una etiqueta de secuencia de comandos, se produce un error 404.

De acuerdo con la siguiente pregunta SO: ASP.NET MVC - Where do you put your .js files if you dont want to store them in /Scripts?

he añadido a mis rutas file.js Registro. (No resolvió el problema)

public static void RegisterRoutes(RouteCollection routes) 
    { 
     routes.IgnoreRoute("{file}.js"); 
     routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 
    } 

¿Cómo puedo almacenar y hacer referencia a mis archivos js junto a mis vistas?

Respuesta

24

El problema es que, por razones de seguridad, el archivo web.config que está dentro de la carpeta de Vistas bloquea todas las solicitudes de archivos en esa carpeta. Esto es lo que encontrará en el fichero de configuración:

<httpHandlers> 
    <add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/> 
</httpHandlers> 

Y para IIS7:

<handlers> 
    <remove name="BlockViewHandler"/> 
    <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" /> 
</handlers> 

Solución

Puede cambiar el comodín atrapar solo t los archivos .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> 

Con este comodín, los archivos .js no se bloquearán.

+1

Esto funciona, pero yo creo que es una mejor idea de no poner los archivos js en la carpeta Vistas. – ErikE

+2

Es indudablemente más seguro incluir en la lista blanca los archivos que explícitamente desea permitir según la respuesta en http://stackoverflow.com/questions/604883/where-to-put-view-specific-javascript-files-in-an-asp -net-mvc-application en lugar de solo solicitudes de filtro para los archivos cshtml. – pwdst

+1

Para mí, he creado una configuración MVC que hace un uso intensivo de angular. También he AMD'd todo con require js, por lo que solo las vistas que usan ciertas piezas de JavaScript hacen que esos archivos Java script se carguen. Como tal compartimenté todo y tenía mucho sentido colocar el controlador angular asociado a una carpeta mvc en la carpeta con la vista. Así que tengo algo como views \ ControllerName \ ControllerName.cshtml y views \ Controller \ ControllerName-controller.js. –

2

Personalmente, no me gusta jugar con httpHandlers por razones de seguridad. Quería hacer exactamente lo mismo para evitar tener que mantener la misma estructura de carpetas dos veces (a la vista y en la carpeta de scripts). Entonces, el objetivo es almacenar .js en la misma carpeta que mi .cshtml y ya no tener el error 404.

Solución

Para alcanzar ese objetivo, utilizo un HtmlHelper personalizada y un controlador para llamadas 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 + "'/>"); 

    } 

controlador 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"); 
    } 

Una vez hecho esto, sólo tiene que añadir el siguiente código en su Vista/PartialView

@Html.JScriptBlock() 
+0

En realidad, me gusta este, pero ¿no es más lento obtener esos archivos estáticos ya que pasa por muchos invocadores y métodos de mvc hasta llegar al archivo real? –

1

En mi opinión, esto es una buena manera: mantiene el código simple y no toca el problema de seguridad con otros tipos de recursos.

Sólo añadir lo siguiente en los controladores de sección:

<add name="JavaScriptHandler" path="*.js" verb="*" preCondition="integratedMode" type="System.Web.StaticFileHandler" /> 
Cuestiones relacionadas