What is the best place (which folder, etc) to put view-specific javascript files in an ASP.NET MVC application?
To keep my project organized, I'd really love to be able to put them side-by-side with the view's .aspx files, but I haven't found a good way to reference them when doing that without exposing the ~/Views/Action/ folder structure. Is it really a bad thing to let details of that folder structure leak?
The alternative is to put them in the ~/Scripts or ~/Content folders, but is a minor irritation because now I have to worry about filename clashes. It's an irritation I can get over, though, if it is "the right thing."
The recommended approach is to put in a separate JavaScript file or inside a section defined in Layout page. A section can be added in the MVC Layout page using @RenderSection() directive. For example, we can define a section in Layout page under <head> tag for scripts like below.
To place JavaScript in an HTML file, use the <script>… </script> tag. You can place the <script> tags, containing your JavaScript, anywhere within your web page, but it is normally recommended that you should keep it within the <head> tags.
Go to Views -> Shared -> _Layout. cshtml file and add the render code. Make sure to register the custom javascript file after the jquery bundle since we are going to use jquery inside our js file. Otherwise we will get a jquery error and also register this before the script RenderSection.
Simply open the file in the browser, press "view source" and use the JS path in the URL to see if it opens. Your syntax is (more or less) correct.
Old question, but I wanted to put my answer incase anyone else comes looking for it.
I too wanted my view specific js/css files under the views folder, and here's how I did it:
In the web.config folder in the root of /Views you need to modify two sections to enable the webserver to serve the files:
<system.web> <httpHandlers> <add path="*.js" verb="GET,HEAD" type="System.Web.StaticFileHandler" /> <add path="*.css" verb="GET,HEAD" type="System.Web.StaticFileHandler" /> <add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/> </httpHandlers> <!-- other content here --> </system.web> <system.webServer> <handlers> <remove name="BlockViewHandler"/> <add name="JavaScript" path="*.js" verb="GET,HEAD" type="System.Web.StaticFileHandler" /> <add name="CSS" path="*.css" verb="GET,HEAD" type="System.Web.StaticFileHandler" /> <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" /> </handlers> <!-- other content here --> </system.webServer>
Then from your view file you can reference the urls like you expect:
@Url.Content("~/Views/<ControllerName>/somefile.css")
This will allow serving of .js and .css files, and will forbid serving of anything else.
One way of achieving this is to supply your own ActionInvoker
. Using the code included below, you can add to your controller's constructor:
ActionInvoker = new JavaScriptActionInvoker();
Now, whenever you place a .js
file next to your view:
You can access it directly:
http://yourdomain.com/YourController/Index.js
Below is the source:
namespace JavaScriptViews { public class JavaScriptActionDescriptor : ActionDescriptor { private string actionName; private ControllerDescriptor controllerDescriptor; public JavaScriptActionDescriptor(string actionName, ControllerDescriptor controllerDescriptor) { this.actionName = actionName; this.controllerDescriptor = controllerDescriptor; } public override object Execute(ControllerContext controllerContext, IDictionary<string, object> parameters) { return new ViewResult(); } public override ParameterDescriptor[] GetParameters() { return new ParameterDescriptor[0]; } public override string ActionName { get { return actionName; } } public override ControllerDescriptor ControllerDescriptor { get { return controllerDescriptor; } } } public class JavaScriptActionInvoker : ControllerActionInvoker { protected override ActionDescriptor FindAction(ControllerContext controllerContext, ControllerDescriptor controllerDescriptor, string actionName) { var action = base.FindAction(controllerContext, controllerDescriptor, actionName); if (action != null) { return action; } if (actionName.EndsWith(".js")) { return new JavaScriptActionDescriptor(actionName, controllerDescriptor); } else return null; } } public class JavaScriptView : IView { private string fileName; public JavaScriptView(string fileName) { this.fileName = fileName; } public void Render(ViewContext viewContext, TextWriter writer) { var file = File.ReadAllText(viewContext.HttpContext.Server.MapPath(fileName)); writer.Write(file); } } public class JavaScriptViewEngine : VirtualPathProviderViewEngine { public JavaScriptViewEngine() : this(null) { } public JavaScriptViewEngine(IViewPageActivator viewPageActivator) : base() { AreaViewLocationFormats = new[] { "~/Areas/{2}/Views/{1}/{0}.js", "~/Areas/{2}/Views/Shared/{0}.js" }; AreaMasterLocationFormats = new[] { "~/Areas/{2}/Views/{1}/{0}.js", "~/Areas/{2}/Views/Shared/{0}.js" }; AreaPartialViewLocationFormats = new [] { "~/Areas/{2}/Views/{1}/{0}.js", "~/Areas/{2}/Views/Shared/{0}.js" }; ViewLocationFormats = new[] { "~/Views/{1}/{0}.js", "~/Views/Shared/{0}.js" }; MasterLocationFormats = new[] { "~/Views/{1}/{0}.js", "~/Views/Shared/{0}.js" }; PartialViewLocationFormats = new[] { "~/Views/{1}/{0}.js", "~/Views/Shared/{0}.js" }; FileExtensions = new[] { "js" }; } public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) { if (viewName.EndsWith(".js")) viewName = viewName.ChopEnd(".js"); return base.FindView(controllerContext, viewName, masterName, useCache); } protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath) { return new JavaScriptView(partialPath); } protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath) { return new JavaScriptView(viewPath); } } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With