ASP.NET MVC एप्लिकेशन में दृश्य-विशिष्ट जावास्क्रिप्ट फ़ाइलों को कहाँ रखा जाए?


96

ASP.NET MVC एप्लिकेशन में दृश्य-विशिष्ट जावास्क्रिप्ट फ़ाइलों को डालने के लिए सबसे अच्छी जगह (कौन सा फ़ोल्डर, आदि) है?

अपनी परियोजना को व्यवस्थित रखने के लिए, मैं वास्तव में उन्हें .aspx फ़ाइलों के साथ साइड-बाय-साइड रखने में सक्षम होना पसंद करूंगा, लेकिन मुझे ~ / व्यूज़ को उजागर किए बिना ऐसा करने के लिए उन्हें संदर्भित करने का एक अच्छा तरीका नहीं मिला। / कार्रवाई / फ़ोल्डर संरचना। क्या उस फ़ोल्डर संरचना के रिसाव का विवरण देना वास्तव में एक बुरी बात है?

विकल्प उन्हें ~ / लिपियों या ~ / सामग्री फ़ोल्डर में रखना है, लेकिन एक छोटी सी जलन है क्योंकि अब मुझे फ़ाइल नाम क्लैश के बारे में चिंता करनी होगी। यह एक जलन है जो मुझे खत्म हो सकती है, हालांकि, अगर यह "सही बात है।"


2
मैंने इसके लिए वर्गों को उपयोगी पाया। देखें: stackoverflow.com/questions/4311783/…
Frison Alexander

1
यह एक पागल प्रश्न जैसा लगता है, लेकिन एक अत्यंत उपयोगी परिदृश्य है जब आप .cshtml के तहत किसी पृष्ठ की जावास्क्रिप्ट फ़ाइल को घोंसले में रखते हैं। (उदाहरण के लिए, NestIn के साथ )। यह समाधान एक्सप्लोरर के आसपास उछाल नहीं होने में मदद करता है।
डेविड शेरेट

जवाबों:


126

पुराना सवाल है, लेकिन मैं अपना जवाब किसी और को देना चाहता था, जो इसकी तलाश में आ जाए।

मैं भी अपने विचार फ़ोल्डर के तहत विशिष्ट js / css फाइलें चाहता था, और यहां बताया गया है कि मैंने यह कैसे किया:

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.Content("~/Views/<ControllerName>/somefile.css")

यह .js और .css फ़ाइलों की सेवा करने की अनुमति देगा, और किसी और चीज़ की सेवा करने से मना करेगा।


धन्यवाद, davesw। वास्तव में मैं क्या देख रहा था
श्री बेल

1
जब मैं ऐसा करता हूं तो मुझे यह त्रुटि मिलती है कि httpHandlers का उपयोग पाइपलाइन मोड में नहीं किया जा सकता है। यह मुझे सर्वर पर क्लासिक मोड में स्विच करना चाहता है। जब कोई सर्वर क्लासिक मोड का उपयोग नहीं करना चाहता है, तो ऐसा करने का सही तरीका क्या है?
Bjørn

1
@ BjørnØyvindHalvorsen आप एक या दूसरे हैंडलर अनुभाग को हटा सकते हैं या अपने web.config में कॉन्फ़िगरेशन सत्यापन को बंद कर सकते हैं। यहाँ देखें
dvesw

2
अनुभाग के लिए केवल mod <system.webServer> को काम करने के लिए आवश्यक था, <system.web> mods की आवश्यकता नहीं थी।
joedotnot

@joedotnot सही, केवल एक अनुभाग की आवश्यकता है, लेकिन जो आपके वेबसर्वर कॉन्फ़िगरेशन पर निर्भर करता है। वर्तमान में अधिकांश लोगों को system.webServer सेक्शन की आवश्यकता होगी, न कि पुराने सिस्टम की ।web सेक्शन की।
डेव्स

5

इसे प्राप्त करने का एक तरीका अपनी आपूर्ति करना है 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);
        }
    }
}

हालांकि, यह एक अच्छा समाधान लगता है, लेकिन क्या यह कार्रवाई के लिए कॉल समय को प्रभावित करता है?
लिएंड्रो सोरेस

यह अच्छी तरह से काम कर सकता है, लेकिन क्या? मैं कम कोड लिखना चाहता हूं, अधिक नहीं।
joedotnot

1
@joedotnot आप एक बार अधिक कोड लिखें, और हमेशा के लिए कम कोड। एक प्रोग्रामर का मंत्र, नहीं? :)
Kirk Woll

@KirkWoll। वहां कोई असहमति नहीं। बस निराश था कि "सरल विशेषता" क्या होनी चाहिए, यह बॉक्स से बाहर नहीं आया। इसलिए मैंने ड्वेसव के उत्तर (स्वीकृत उत्तर) का चुनाव करना पसंद किया। लेकिन अपने कोड को साझा करने के लिए धन्यवाद, यह दूसरों के लिए उपयोगी हो सकता है।
joedotnot

@KirkWoll मैं MVC में नया हूँ और मैं MVC5 साइट में आपके समाधान को लागू करने का प्रयास कर रहा हूँ। मुझे यकीन नहीं है कि "ActionInvoker = new JavaScriptActionInvoker ()" का उपयोग कहां या "" करना है ??
ड्रयू

3

आप dvesw के सुझाव को उल्टा कर सकते हैं और केवल .cshtml को ब्लॉक कर सकते हैं

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

उत्तम! :) एक अच्छा लघु समाधान! और यह काम करता है! :) मुझे नहीं पता कि यह डिफ़ॉल्ट सेटिंग क्यों नहीं है, क्योंकि यह वास्तविक विचारों के साथ-साथ विचारों से संबंधित लिपियों को रखने में सक्षम होने के लिए बेहतर है। धन्यवाद, वादिम
ब्रूसहिल

24
मैं इस दृष्टिकोण से सतर्क रहूंगा, भले ही यह अच्छा और साफ लगता है। यदि भविष्य में, इस एप्लिकेशन में रेजर (पूर्व वेबफार्म, स्पार्क, आदि) के अलावा अन्य दृश्य इंजन शामिल हैं, तो वे चुपचाप सार्वजनिक होंगे। साथ ही फाइलों को प्रभावित कर रहा है Site.Master। श्वेतसूची में सुरक्षित दृष्टिकोण प्रतीत होता है
arserbin3

मैं @ arserbin3 से सहमत हूं कि श्वेत-सूची सुरक्षित लगती है; एक ही समय में, मैं एक उद्यम के व्यू इंजन परिवर्तन को एक से दूसरे में बदलने की संभावना महसूस नहीं कर सकता। ऐसा करने के लिए कोई पूर्ण स्वचालन उपकरण नहीं है। रूपांतरण को हाथ से करने की आवश्यकता है। एक बार जब मैंने एक बड़े वेब एप्लिकेशन के लिए ऐसा किया; परिवर्तित WebForm viewengine रेजर करने के लिए, और मैं दुःस्वप्न के दिनों को याद करते हैं, कुछ महीनों के लिए, चीजें यहां और वहां काम नहीं कर रही थीं ... कैंट इस तरह की बात फिर से करने के बारे में सोचते हैं :)। अगर मुझे इस तरह का विशाल परिवर्तन करना है, तो, मेरा मानना ​​है कि इस तरह के web.config सेटिंग में बदलाव नहीं होगा।
इमरान हुसैन

1

मुझे पता है कि यह एक पुराना विषय है, लेकिन मेरे पास कुछ चीजें हैं जिन्हें मैं जोड़ना चाहूंगा। मैंने dvesw के उत्तर की कोशिश की, लेकिन स्क्रिप्ट फ़ाइलों को लोड करने की कोशिश करते समय यह 500 त्रुटि फेंक रहा था, इसलिए मुझे इसे web.config में जोड़ना पड़ा:

<validation validateIntegratedModeConfiguration="false" />

to system.webServer यहाँ मेरे पास क्या है, और मैं इसे काम करने में सक्षम था:

<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>

सत्यापन पर अधिक जानकारी यहाँ दी गई है: https://www.iis.net/configreference/system.webserver/validation


0

इस कोड को web.config फ़ाइल के अंदर system.web टैग में जोड़ें

<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>

0

मैं js फ़ाइलों को दृश्य के समान फ़ोल्डर में दृश्य से संबंधित रखना चाहता था।

मैं काम करने के लिए इस धागे में अन्य समाधान प्राप्त करने में सक्षम नहीं था, यह नहीं कि वे टूट गए हैं, लेकिन मैं उन्हें काम करने के लिए एमवीसी के लिए बहुत नया हूं।

यहाँ दी गई जानकारी और कई अन्य ढेरों का उपयोग करके मैं एक समाधान के साथ आया:

  • जावास्क्रिप्ट फ़ाइल को उसी निर्देशिका में रखने की अनुमति देता है जिस दृश्य से वह संबद्ध है।
  • स्क्रिप्ट URL अंतर्निहित भौतिक साइट संरचना को दूर नहीं करता है
  • स्क्रिप्ट URL को अनुगामी स्लैश (/) के साथ समाप्त नहीं करना है
  • स्थिर संसाधनों के साथ हस्तक्षेप नहीं करता है, जैसे: /Scripts/someFile.js अभी भी काम करता है
  • सक्षम होने के लिए runAllManagedModulesForAllRequests की आवश्यकता नहीं है।

नोट: मैं HTTP Attribute Routing का भी उपयोग कर रहा हूँ। यह संभव है कि मार्ग का मेरी आत्मा में उपयोग किए बिना इसे सक्षम किए बिना काम करने के लिए संशोधित किया जा सके।

निम्नलिखित उदाहरण निर्देशिका / फ़ाइल संरचना को देखते हुए:

Controllers
-- Example
   -- ExampleController.vb

Views
-- Example
   -- Test.vbhtml
   -- Test.js

नीचे दिए गए कॉन्फ़िगरेशन चरणों का उपयोग करके, ऊपर दिए गए उदाहरण संरचना के साथ संयुक्त, परीक्षण दृश्य URL के माध्यम से पहुँचा जाएगा: /Example/Testऔर जावास्क्रिप्ट फ़ाइल के माध्यम से संदर्भित किया जाएगा:/Example/Scripts/test.js

चरण 1 - रूटिंग विशेषता सक्षम करें:

अपनी /App_start/RouteConfig.vb फ़ाइल संपादित करें और routes.MapMvcAttributeRoutes()मौजूदा मार्गों के ऊपर जोड़ें । 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

चरण 2-अपनी साइट को इलाज के लिए कॉन्फ़िगर करें, और प्रक्रिया करें, / जटिलताओं कॉन्ट्रास्ट्रोलरलाइड्स / स्क्रिप्ट्स / m.js को एक एमवीसी पथ के रूप में और एक स्थिर संसाधन न करें।

अपनी /Web.config फ़ाइल को संपादित करें, निम्न को जोड़ते हुए system.webServer -> फ़ाइल के हैंडलर अनुभाग:

<add name="ApiURIs-ISAPI-Integrated-4.0" path="*/scripts/*.js" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />

यहाँ यह फिर से संदर्भ के साथ है:

  <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>  

चरण 3 - निम्न स्क्रिप्ट कार्रवाई परिणाम को अपनी नियंत्रक फ़ाइल में जोड़ें

  • कंट्रोलर के लिए {कंट्रोलर} नाम से मिलान करने के लिए रूट पथ को संपादित करना सुनिश्चित करें, इस उदाहरण के लिए: <मार्ग (" उदाहरण " / लिपियों / {फ़ाइल नाम}")>
  • आपको अपनी प्रत्येक नियंत्रक फ़ाइल में इसे कॉपी करना होगा। यदि आप चाहते थे, तो एक एकल, एक बार, मार्ग कॉन्फ़िगरेशन के रूप में किसी भी तरह से ऐसा करने का एक तरीका है।

        ' /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

संदर्भ के लिए, यह मेरी ExampleController.vb फ़ाइल है:

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 जावास्क्रिप्ट फ़ाइलों के बारे में कुछ खास नहीं है और यहाँ नहीं दिखाया गया है।

मैं अपने सीएसएस को व्यू फाइल में रखता हूं लेकिन आप आसानी से इस समाधान में जोड़ सकते हैं ताकि आप अपनी सीएसएस फाइलों को इसी तरह से संदर्भित कर सकें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.