ASP.NET MVC 응용 프로그램에서보기 별 javascript 파일을 어디에 배치합니까?
ASP.NET MVC 응용 프로그램에서보기 별 javascript 파일을 배치하는 가장 좋은 위치 (폴더 등)는 무엇입니까?
내 프로젝트를 체계적으로 유지하기 위해 뷰의 .aspx 파일과 나란히 놓을 수 있기를 정말 좋아하지만 ~ / Views를 노출하지 않고이를 수행 할 때 참조 할 좋은 방법을 찾지 못했습니다. / Action / 폴더 구조. 그 폴더 구조의 세부 사항이 유출되도록하는 것이 정말 나쁜 일입니까?
대안은 ~ / Scripts 또는 ~ / Content 폴더에 넣는 것이지만 이제 파일 이름 충돌에 대해 걱정해야하므로 약간의 짜증이납니다. 그러나 그것이 "옳은 일"이라면 극복 할 수있는 자극이다.
오래된 질문이지만 다른 사람이 찾아올 때를 대비하여 내 대답을 넣고 싶었습니다.
나도보기 폴더 아래에 내보기 특정 js / css 파일을 원했고, 여기에 내가 한 방법이 있습니다.
/ Views 루트의 web.config 폴더에서 웹 서버가 파일을 제공 할 수 있도록 두 섹션을 수정해야합니다.
<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>
그런 다음보기 파일에서 예상 한대로 URL을 참조 할 수 있습니다.
@Url.Content("~/Views/<ControllerName>/somefile.css")
이렇게하면 .js 및 .css 파일을 제공 할 수 있으며 다른 파일의 제공은 금지됩니다.
이를 달성하는 한 가지 방법은 자신의 ActionInvoker
. 아래에 포함 된 코드를 사용하여 컨트롤러의 생성자에 추가 할 수 있습니다.
ActionInvoker = new JavaScriptActionInvoker();
이제 .js
보기 옆에 파일 을 배치 할 때마다 :
직접 액세스 할 수 있습니다.
http://yourdomain.com/YourController/Index.js
다음은 소스입니다.
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);
}
}
}
davesw의 제안을 반전하고 .cshtml 만 차단할 수 있습니다.
<httpHandlers>
<add path="*.cshtml" verb="*" type="System.Web.HttpNotFoundHandler"/>
</httpHandlers>
I know this is a rather old topic, but I have a few things I would like to add. I tried davesw's answer but it was throwing a 500 error when trying to load the script files, so I had to add this to the web.config:
<validation validateIntegratedModeConfiguration="false" />
to system.webServer. Here is what I have, and I was able to get it to work:
<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>
<validation validateIntegratedModeConfiguration="false" />
</system.webServer>
<system.web>
<compilation>
<assemblies>
<add assembly="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</assemblies>
</compilation>
<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>
</system.web>
Here is more information on validation: https://www.iis.net/configreference/system.webserver/validation
add this code in web.config file inside system.web tag
<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>
I also wanted to place js files related to a view in the same folder as the view.
I wasn't able to get the other solutions in this thread to work, not that they are broken but I am too new to MVC to get them working.
Using information given here and several other stacks I came up with a solution that:
- Allows the javascript file to be placed in the same directory as the view it is associated with.
- Script URL's don't give away the underlying physical site structure
- Script URL's don't have to end with a trailing slash (/)
- Doesn't interfere with static resources, eg: /Scripts/someFile.js still works
- Doesn't require runAllManagedModulesForAllRequests to be enabled.
Note: I am also using HTTP Attribute Routing. It's possible that the route's used in my soultion could be modified to work without enabling this.
Given the following example directory/file structure:
Controllers
-- Example
-- ExampleController.vb
Views
-- Example
-- Test.vbhtml
-- Test.js
Using the configuration steps given below, combined with the example structure above, the test view URL would be accessed via: /Example/Test
and the javascript file would be referenced via: /Example/Scripts/test.js
Step 1 - Enable Attribute Routing:
Edit your /App_start/RouteConfig.vb file and add routes.MapMvcAttributeRoutes()
just above the existing routes.MapRoute:
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 treat, and process, /{controller}/Scripts/*.js as an MVC path and not a static resource
Edit your /Web.config file, adding the following to the system.webServer --> handlers section of the 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 scripts action result to your Controller file
- Be sure to edit the route path to match the {controller} name for the controller, for this example it's: <Route("Example/Scripts/{filename}")>
You will need to copy this into each of your Controller files. If you wanted, there is probably a way to do this as a single, one-time, route configuration somehow.
' /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
최종 노트 test.vbhtml view / test.js javascript 파일에는 특별한 것이 없으며 여기에 표시되지 않습니다.
내 CSS를보기 파일에 보관하지만이 솔루션에 쉽게 추가하여 비슷한 방식으로 CSS 파일을 참조 할 수 있습니다.
'Programing' 카테고리의 다른 글
Mac OS에서 Maven의 settings.xml은 어디에 있습니까? (0) | 2020.09.05 |
---|---|
-D_XOPEN_SOURCE의 기능 / 의미는 무엇입니까? (0) | 2020.09.04 |
fmap이있을 때 Haskell에서지도의 요점은 무엇입니까? (0) | 2020.09.04 |
C ++ 11에서 난수 생성 : 생성 방법, 작동 원리 (0) | 2020.09.04 |
구분 기호가있는 String.Split (.net)의 반대 (0) | 2020.09.04 |