ASP.NET MVC सापेक्ष पथ


100

अपने अनुप्रयोगों में, मुझे अक्सर रिश्तेदार पथ का उपयोग करना पड़ता है। उदाहरण के लिए, जब मैं JQuery का संदर्भ देता हूं, तो मैं आमतौर पर ऐसा करता हूं:

<script type="text/javascript" src="../Scripts/jquery-1.2.6.js"></script>

अब जब मैं MVC में परिवर्तन कर रहा हूं, तो मुझे रूट के सापेक्ष अलग-अलग रास्तों का हिसाब देना होगा। यह अतीत में URL पुनर्लेखन के साथ एक मुद्दा था, लेकिन मैं लगातार पथों का उपयोग करके इसके चारों ओर काम करने में कामयाब रहा।

मुझे पता है कि मानक समाधान निरपेक्ष पथों का उपयोग करना है जैसे:

<script type="text/javascript" src="/Scripts/jquery-1.2.6.js"></script>

लेकिन यह मेरे लिए काम नहीं करेगा क्योंकि विकास चक्र के दौरान, मुझे एक परीक्षण मशीन पर तैनात करना होगा, जिस पर ऐप एक आभासी निर्देशिका में चलेगा। रूट परिवर्तन के समय रूट सापेक्ष पथ काम नहीं करते हैं। इसके अलावा, रखरखाव के कारणों के लिए, मैं केवल टेस्ट को लागू करने की अवधि के लिए सभी रास्तों को नहीं बदल सकता - यह अपने आप में एक बुरा सपना होगा।

तो सबसे अच्छा उपाय क्या है?

संपादित करें:

चूँकि यह प्रश्न अभी भी विचारों और उत्तरों को प्राप्त कर रहा है, इसलिए मैंने सोचा कि इसे अपडेट करना समझदारी भरा हो सकता है कि रेज़र V2 के रूप में, रूट-रिलेटिव urls के लिए समर्थन बेक किया गया है, इसलिए आप इसका उपयोग कर सकते हैं

<img src="~/Content/MyImage.jpg">

किसी भी सर्वर-साइड सिंटैक्स के बिना, और दृश्य इंजन स्वचालित रूप से बदल देता है ~ / जो भी वर्तमान साइट रूट है।

जवाबों:


93

इसे इस्तेमाल करे:

<script type="text/javascript" src="<%=Url.Content("~/Scripts/jquery-1.2.6.js")%>"></script>

या MvcContrib का उपयोग करें और यह करें:

<%=Html.ScriptInclude("~/Content/Script/jquery.1.2.6.js")%>

1
यह पूछा जाता है कि यह अक्सर पूछे जाने वाले प्रश्न होना चाहिए, मुझे लगता है कि उन्हें टेम्पलेट में एक उदाहरण शामिल करने की आवश्यकता है।
साइमन स्टील

बहुत बढ़िया, यह वास्तव में मुझे एक बंधन से बाहर निकला। धन्यवाद!
जारेड

2
(मुझे पता है कि यह पोस्ट पुरानी है) - <% = Url.Content ("~ / Scripts / jquery-1.2.6.js") का उपयोग नहीं करता है)%> सर्वर को पथ प्रदान करते हैं, जबकि, यदि आपने उपयोग किया है "/ लिपियों / jquery-1.2.6.js ", यह सिर्फ ग्राहक को सीधे परोसा जाएगा, इसलिए, सर्वर को एक और चीज को कम करना होगा? मैंने सोचा कि मैं कहीं और पढ़ता हूँ जितना आप सर्वर प्रक्रिया से बच सकते हैं, बेहतर है - विशेष रूप से * .js पथ जैसे स्थिर सामग्री के साथ? मुझे लगता है कि यह न्यूनतम संसाधनों का उपयोग करता है, लेकिन अगर आपके ऐप में कुछ सौ / हज़ार Url.Content () हैं, तो यह एक युगल नैनोसेकंड मुंडा है, नहीं?
लॉसबियर

53

एक पुराने पोस्ट के दौरान, नए पाठकों को पता होना चाहिए कि रेजर 2 और बाद में (एमवीसी 4+ में डिफ़ॉल्ट) पूरी तरह से इस समस्या का समाधान करता है।

रेजर 1 के साथ पुराना MVC3:

<a href="@Url.Content("~/Home")">Application home page</a>

रेजर 2 के साथ और बाद में नया MVC4:

<a href="~/Home">Application home page</a>

कोई अजीब रेज़र फ़ंक्शन-जैसे सिंटैक्स। कोई गैर-मानक मार्कअप टैग नहीं।

किसी भी HTML विशेषताओं में एक टिल्ड ('~') के साथ एक पथ को वरीयता देते हुए रेज़र 2 को "सही काम करने के लिए" बस इसे काम करने के लिए कहता है। यह बहुत अच्छा है।


हां, और ~ / उपसर्ग को पार्स करने की सरलता को देखते हुए, मुझे आश्चर्य है कि ऐसा कुछ शुरू से ASP.NET में क्यों नहीं बनाया गया था।
क्रिस

4
मैंने अक्सर पाया है कि डिजाइन जितना सरल है, उतना ही अधिक विचार इसमें चला गया है।
चार्ल्स बर्न्स

1
यह उत्तर थोड़ा भ्रामक है। MVC4 के लिए पोस्ट किया गया सिंटैक्स वास्तव में रेजर इंजन पर निर्भर है। यह किसी विशेष मार्कअप का उपयोग नहीं कर सकता है, लेकिन केवल रेजर v2 + इंजन सही रूप से दिखाए गए सिंटैक्स को संभालता है।
क्रिस

1
आप ठीक कह रहे हैं, @ क्रिस। मैंने इसे प्रतिबिंबित करने के लिए उत्तर अपडेट कर दिया है।
चार्ल्स बर्न्स

10

ब्रेकिंग परिवर्तन - एमवीसी 5

MVC 5 ( MVC 5 रिलीज़ नोट से ) में एक परिवर्तन परिवर्तन के लिए बाहर देखो

यूआरएल रिवाइराइट और टिल्ड (~)

ASP.NET रेजर 3 या ASP.NET MVC 5 में अपग्रेड करने के बाद, यदि आप URL rewrites का उपयोग कर रहे हैं, तो tilde (~) संकेतन अब सही ढंग से काम नहीं कर सकता है। URL रीराइट जैसे HTML तत्वों में टिल्ड (~) अंकन को प्रभावित करता है <A/>, <SCRIPT/>, <LINK/>, और एक परिणाम के रूप टिल्ड नहीं रह गया रूट निर्देशिका में मैप करता है।

उदाहरण के लिए, आप के लिए अनुरोध को फिर से लिखने अगर asp.net/content को asp.net , में href विशेषता <A href="~/content/"/>पर ले कर / सामग्री / सामग्री / के बजाय / । इस परिवर्तन को दबाने के लिए, आप IIS_WasUrlRewritten संदर्भ को प्रत्येक वेब पेज में झूठे या Application_eginRequest में Global.asax में सेट कर सकते हैं ।

वे वास्तव में यह नहीं समझाते कि यह कैसे करना है, लेकिन फिर मुझे यह उत्तर मिला :

यदि आप IIS 7 इंटीग्रेटेड पाइपलाइन मोड में चल रहे हैं, तो निम्नलिखित को अपने में रखें Global.asax:

 protected void Application_BeginRequest(object sender, EventArgs e)
 {
     Request.ServerVariables.Remove("IIS_WasUrlRewritten");
 }

नोट: आप Request.ServerVariablesवास्तव में जांचना चाहते हैं कि IIS_WasUrlRewrittenपहले यह सुनिश्चित किया जाए कि आपकी समस्या क्या है।


पुनश्च। मुझे लगा कि मेरे पास एक ऐसी स्थिति है जहां यह मेरे साथ हो रहा था और मैं src="~/content/..."अपने HTML में URLS जेनरेट कर रहा था - लेकिन यह कुछ ऐसा निकला जो मेरे कोड के संकलित होने पर ताज़ा नहीं था। लेआउट और पेज cshtml फ़ाइलों को संपादित करना और फिर से शुरू करना किसी तरह काम करने के लिए ट्रिगर करता है।


6

ASP.NET में मैं आमतौर पर उपयोग करता हूं <img src='<%= VirtualPathUtility.ToAbsolute("~/images/logo.gif") %>' alt="Our Company Logo"/>। मैं नहीं देखता कि ASP.NET MVC में एक समान समाधान क्यों नहीं काम करना चाहिए।


6
<script src="<%=ResolveUrl("~/Scripts/jquery-1.2.6.min.js") %>" type="text/javascript"></script>

क्या मैंने इस्तेमाल किया है। अपने उदाहरण से मिलान करने के लिए पथ बदलें।


5

इसके लायक होने के लिए, मैं वास्तव में पथों को हल करने के लिए सर्वर टैग्स के साथ अपने ऐप को लेट करने के विचार से घृणा करता हूं, इसलिए मैंने कुछ अधिक शोध किया और कुछ का उपयोग करने का विकल्प चुना, जो मैंने लिंक को फिर से लिखने के लिए कोशिश की थी - एक प्रतिक्रिया फ़िल्टर। इस तरह, मैं एक ज्ञात उपसर्ग के साथ सभी पूर्ण पथों को उपसर्ग कर सकता हूं और इसे रिस्पांस.फिल्टर ऑब्जेक्ट का उपयोग करके रनटाइम पर बदल सकता हूं और अनावश्यक सर्वर टैग के बारे में चिंता करने की आवश्यकता नहीं है। कोड नीचे पोस्ट किया गया है अगर यह किसी और की मदद करेगा।

using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace Demo
{
    public class PathRewriter : Stream
    {
        Stream filter;
        HttpContext context;
        object writeLock = new object();
        StringBuilder sb = new StringBuilder();

        Regex eofTag = new Regex("</html>", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        Regex rootTag = new Regex("/_AppRoot_", RegexOptions.IgnoreCase | RegexOptions.Compiled);

        public PathRewriter(Stream filter, HttpContext context)
        {
            this.filter = filter;
            this.context = context;
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            string temp;

            lock (writeLock)
            {
                temp = Encoding.UTF8.GetString(buffer, offset, count);
                sb.Append(temp);

                if (eofTag.IsMatch(temp))
                    RewritePaths();
            }
        }

        public void RewritePaths()
        {
            byte[] buffer;
            string temp;
            string root;

            temp = sb.ToString();
            root = context.Request.ApplicationPath;
            if (root == "/") root = "";

            temp = rootTag.Replace(temp, root);
            buffer = Encoding.UTF8.GetBytes(temp);
            filter.Write(buffer, 0, buffer.Length);
        }

        public override bool CanRead
        {
            get { return true; }
        }

        public override bool CanSeek
        {
            get { return filter.CanSeek; }
        }

        public override bool CanWrite
        {
            get { return true; }
        }

        public override void Flush()
        {
            return;
        }

        public override long Length
        {
            get { return Encoding.UTF8.GetBytes(sb.ToString()).Length; }
        }

        public override long Position
        {
            get { return filter.Position; }
            set { filter.Position = value; }
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            return filter.Read(buffer, offset, count);
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            return filter.Seek(offset, origin);
        }

        public override void SetLength(long value)
        {
            throw new NotImplementedException();
        }
    }

    public class PathFilterModule : IHttpModule
    {
        public void Dispose()
        {
            return;
        }

        public void Init(HttpApplication context)
        {
            context.ReleaseRequestState += new EventHandler(context_ReleaseRequestState);
        }

        void context_ReleaseRequestState(object sender, EventArgs e)
        {
            HttpApplication app = sender as HttpApplication;
            if (app.Response.ContentType == "text/html")
                app.Response.Filter = new PathRewriter(app.Response.Filter, app.Context);
        }
    }
}

4

MVC 3 के लिए रेज़र व्यू इंजन, वर्चुअल-रूट सापेक्ष पथों का उपयोग करना और भी आसान और स्वच्छ बनाता है जो रन-टाइम पर ठीक से हल हो जाते हैं। बस Url.Content () विधि को href विशेषता मान में छोड़ दें और यह ठीक से हल हो जाएगा।

<a href="@Url.Content("~/Home")">Application home page</a>

1

क्रिस की तरह, मैं वास्तव में अपने क्लीन मार्कअप के अंदर फूला हुआ सर्वर-साइड टैग लगाने के लिए खड़ा नहीं हो सकता हूं, बस शुद्ध रूप से जड़ से ऊपर की ओर देखने के लिए मूर्खतापूर्ण बात बताऊंगा। यह पूछने के लिए एक बहुत ही सरल, उचित चीज होनी चाहिए। लेकिन मुझे इस बात से भी नफरत है कि इस तरह की एक साधारण बात करने के लिए किसी भी कस्टम C # कक्षाएं लिखने के प्रयास में जाने के लिए, मुझे क्यों करना चाहिए? क्या समय की बर्बादी है।

मेरे लिए, मैंने बस "पूर्णता" पर समझौता किया और अपने पथ संदर्भों के अंदर वर्चुअल निर्देशिका के रूट पथ नाम को हार्डकोड किया। तो इस तरह से:

<script type="text/javascript" src="/MyProject/Scripts/jquery-1.2.6.js"></script>

URL को हल करने के लिए सर्वर-साइड प्रोसेसिंग या C # कोड की आवश्यकता नहीं है, जो प्रदर्शन के लिए सबसे अच्छा है, हालांकि मुझे पता है कि यह नगण्य होगा। और मेरी अच्छी साफ मार्कअप में कोई फूला हुआ बदसूरत सर्वर-साइड अराजकता।

मुझे बस यह जानकर जीना होगा कि यह हार्डकोड है और जब http: // MyDevServer / MyProject / के बजाय एक उचित डोमेन पर माइग्रेट हो जाता है, तो उसे निकालना होगा

चियर्स


1
मैंने आपको वापस लाने के लिए मतदान किया। 0. आपकी भावनाओं से सहमत हूं। मैं शुद्ध सी # में 5 साल बाद वेब देवता के लिए नया हूं और स्पेगेटी अराजकता की एक अप्रिय भूमि है।
ल्यूक पुप्लेट ने

यह एक स्वीकार्य समझौते की तरह लगता है जब तक कि आपको किसी नेस्टेड वेब ऐप की तरह कुछ करने की आवश्यकता न हो। रिज़ॉल्वर मार्क-अप का उपयोग करने से यह ठीक हो जाएगा लेकिन आपका स्थिर लिंक टूट जाएगा। उदाहरण: आप बिल्ट-इन वेब सर्वर के खिलाफ स्थानीय रूप से निर्माण करते हैं और फिर ऐप को domain.com/myNewWebApp पर
धकेलते हैं

यह बहुत सारे उत्पादन परिदृश्यों में टूट जाएगा
Oskar Duveborn

मैं इस समाधान को काफी पसंद करता हूं: Thinkstuff.co.uk/2013/02/…
Dion

1

खेल के अंत में, लेकिन इस पोस्ट में ASP.Net रास्तों को संभालने का एक पूरा सारांश है।


1

मैं एक सरल सहायक विधि का उपयोग करता हूं। आप इसे आसानी से व्यूज और कंट्रोलर्स में उपयोग कर सकते हैं।

मार्कअप:

<a href=@Helper.Root()/about">About Us</a>

सहायक विधि:

public static string Root()
{
    if (HttpContext.Current.Request.Url.Host == "localhost")
    {
        return "";
    }
    else
    {
        return "/productionroot";
    }
}

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