I also wanted to put the js files related to the view in the same folder as the view.
I could not get the other solutions in this thread to work, not that they broke, but I am too new to MVC to get them working.
Using the information given here and several other stacks, I found a solution that:
- Allows you to place the javascript file in the same directory as the view with which it is associated.
- The script URL does not reveal the basic physical structure of the site
- Script URL must not end with a slash (/)
- Does not interfere with static resources, for example: /Scripts/someFile.js still works
- Does not require running runAllManagedModulesForAllRequests.
Note: I also use HTTP attribute routing. It is possible that the route used in my soul can be changed to work without including this.
The following is an example of a directory / file structure:
Controllers -- Example -- ExampleController.vb Views -- Example -- Test.vbhtml -- Test.js
Using the configuration steps below, combined with the above /Example/Scripts/test.js structure, the URL of the test view will be accessible via: /Example/Test and the javascript file will be referenced via: /Example/Scripts/test.js
Step 1 - Enable Attribute Routing:
Edit the file /App_start/RouteConfig.vb and add routes.MapMvcAttributeRoutes() just above the existing routes. Map:
Imports System Imports System.Collections.Generic Imports System.Linq Imports System.Web Imports System.Web.Mvc Imports System.Web.Routing Public Module RouteConfig Public Sub RegisterRoutes(ByVal routes As RouteCollection) routes.IgnoreRoute("{resource}.axd/{*pathInfo}") ' Enable HTTP atribute routing routes.MapMvcAttributeRoutes() routes.MapRoute( name:="Default", url:="{controller}/{action}/{id}", defaults:=New With {.controller = "Home", .action = "Index", .id = UrlParameter.Optional} ) End Sub End Module
Step 2 -Configure your site to process and process / averagecontroller βΉ/Scripts/*.js as a path to MVC, and not as a static resource
Edit the /Web.config file by adding the following to the system.webServer section β handlers file:
<add name="ApiURIs-ISAPI-Integrated-4.0" path="*/scripts/*.js" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
Here it is again with context:
<system.webServer> <modules> <remove name="TelemetryCorrelationHttpModule"/> <add name="TelemetryCorrelationHttpModule" type="Microsoft.AspNet.TelemetryCorrelation.TelemetryCorrelationHttpModule, Microsoft.AspNet.TelemetryCorrelation" preCondition="managedHandler"/> <remove name="ApplicationInsightsWebTracking"/> <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler"/> </modules> <validation validateIntegratedModeConfiguration="false"/> <handlers> <remove name="ExtensionlessUrlHandler-Integrated-4.0"/> <remove name="OPTIONSVerbHandler"/> <remove name="TRACEVerbHandler"/> <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/> <add name="ApiURIs-ISAPI-Integrated-4.0" path="*/scripts/*.js" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> </handlers> </system.webServer>
Step 3 - Add the following script action result to your controller file
- Be sure to change the route path to match the name {controller} for the controller, for this example it is: <Route (" Example / Scripts / {filename}")>
You will need to copy this to each of your controller files. If you want, there may be a way to do this as a one-time route configuration.
' /Example/Scripts/*.js <Route("Example/Scripts/{filename}")> Function Scripts(filename As String) As ActionResult ' ControllerName could be hardcoded but doing it this way allows for copy/pasting this code block into other controllers without having to edit Dim ControllerName As String = System.Web.HttpContext.Current.Request.RequestContext.RouteData.Values("controller").ToString() ' the real file path Dim filePath As String = Server.MapPath("~/Views/" & ControllerName & "/" & filename) ' send the file contents back Return Content(System.IO.File.ReadAllText(filePath), "text/javascript") End Function
For context, this is my ExampleController.vb file:
Imports System.Web.Mvc Namespace myAppName Public Class ExampleController Inherits Controller ' /Example/Test Function Test() As ActionResult Return View() End Function ' /Example/Scripts/*.js <Route("Example/Scripts/{filename}")> Function Scripts(filename As String) As ActionResult ' ControllerName could be hardcoded but doing it this way allows for copy/pasting this code block into other controllers without having to edit Dim ControllerName As String = System.Web.HttpContext.Current.Request.RequestContext.RouteData.Values("controller").ToString() ' the real file path Dim filePath As String = Server.MapPath("~/Views/" & ControllerName & "/" & filename) ' send the file contents back Return Content(System.IO.File.ReadAllText(filePath), "text/javascript") End Function End Class End Namespace
Final remarks There is nothing special about the javascript files test.vbhtml view / test.js and they are not shown here.
I keep my CSS in a presentation file, but you can easily add to this solution so that you can reference your CSS files in a similar way.