रेज़र व्यू इंजन के साथ आंशिक दृश्य ASP.NET MVC 3 से विशिष्ट अनुभागों में सामग्री इंजेक्ट करना




asp.net-mvc asp.net-mvc-3 (14)

मेरे पास इस अनुभाग को मेरे _Layout.cshtml में परिभाषित किया गया है

@RenderSection("Scripts", false)

मैं आसानी से इसे एक दृश्य से उपयोग कर सकता हूं:

@section Scripts { 
    @*Stuff comes here*@
}

मैं इस बात के साथ संघर्ष कर रहा हूं कि आंशिक दृश्य से इस खंड के अंदर कुछ सामग्री कैसे इंजेक्शन दी जाए।

आइए मान लें कि यह मेरा दृश्य पृष्ठ है:

@section Scripts { 

    <script>
        //code comes here
    </script>
}

<div>
    poo bar poo
</div>

<div>
  @Html.Partial("_myPartial")
</div>

मुझे _myPartial आंशिक दृश्य से Scripts अनुभाग के अंदर कुछ सामग्री इंजेक्षन करने की आवश्यकता है।

मैं यह कैसे कर सकता हूँ?


अनुभाग आंशिक विचारों में काम नहीं करते हैं और यह डिजाइन द्वारा है। आप समान व्यवहार प्राप्त करने के लिए कुछ कस्टम सहायकों का उपयोग कर सकते हैं, लेकिन ईमानदारी से आंशिक रूप से आवश्यक स्क्रिप्ट शामिल करना, आंशिक रूप से जिम्मेदारी नहीं है। मैं ऐसा करने के लिए मुख्य दृश्य के @ स्क्रिप्ट अनुभाग का उपयोग करने की अनुशंसा करता हूं और आंशिक चिंता स्क्रिप्ट के बारे में चिंता नहीं करता है।


आंशिक विचारों में अनुभागों को सम्मिलित करने का एक तरीका है, हालांकि यह सुंदर नहीं है। आपको मूल दृश्य से दो चर तक पहुंच की आवश्यकता है। चूंकि आपके आंशिक दृश्य का बहुत ही उद्देश्य उस खंड को बनाना है, इसलिए इन चरों की आवश्यकता होती है।

यहां आंशिक दृश्य में एक अनुभाग डालने जैसा लगता है:

@model KeyValuePair<WebPageBase, HtmlHelper>
@{
    Model.Key.DefineSection("SectionNameGoesHere", () =>
    {
        Model.Value.ViewContext.Writer.Write("Test");
    });
}

और पृष्ठ में आंशिक दृश्य डालने ...

@Html.Partial(new KeyValuePair<WebPageBase, HtmlHelper>(this, Html))

आप किसी भी कक्षा में प्रोग्रामेटिक रूप से किसी सेक्शन की सामग्री को परिभाषित करने के लिए इस तकनीक का उपयोग भी कर सकते हैं।

का आनंद लें!


एमवीसी कोर का उपयोग करके आप नीचे देखे गए एक साफ टैगहेल्पर scripts बना सकते हैं। इसे आसानी से एक section टैग में बदल दिया जा सकता है जहां आप इसे एक नाम भी देते हैं (या नाम व्युत्पन्न प्रकार से लिया जाता है)। ध्यान दें कि IHttpContextAccessor लिए निर्भरता इंजेक्शन सेट अप करने की आवश्यकता है।

स्क्रिप्ट जोड़ते समय (उदाहरण के लिए आंशिक रूप से)

<scripts>
    <script type="text/javascript">
        //anything here
    </script>
</scripts>

स्क्रिप्ट आउटपुट करते समय (उदाहरण के लिए लेआउट फ़ाइल में)

<scripts render="true"></scripts>

कोड

public class ScriptsTagHelper : TagHelper
    {
        private static readonly object ITEMSKEY = new Object();

        private IDictionary<object, object> _items => _httpContextAccessor?.HttpContext?.Items;

        private IHttpContextAccessor _httpContextAccessor;

        public ScriptsTagHelper(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
        {
            var attribute = (TagHelperAttribute)null;
            context.AllAttributes.TryGetAttribute("render",out attribute);

            var render = false;

            if(attribute != null)
            {
                render = Convert.ToBoolean(attribute.Value.ToString());
            }

            if (render)
            {
                if (_items.ContainsKey(ITEMSKEY))
                {
                    var scripts = _items[ITEMSKEY] as List<HtmlString>;

                    var content = String.Concat(scripts);

                    output.Content.SetHtmlContent(content);
                }
            }
            else
            {
                List<HtmlString> list = null;

                if (!_items.ContainsKey(ITEMSKEY))
                {
                    list = new List<HtmlString>();
                    _items[ITEMSKEY] = list;
                }

                list = _items[ITEMSKEY] as List<HtmlString>;

                var content = await output.GetChildContentAsync();

                list.Add(new HtmlString(content.GetContent()));
            }
        }
    }

खैर, मुझे लगता है कि अन्य पोस्टर्स ने आपको अपने आंशिक (तीसरे पक्ष के एचटीएमएल हेल्पर्स का उपयोग करके) में सीधे @section शामिल करने का साधन प्रदान किया है।

लेकिन, मुझे लगता है कि, यदि आपकी स्क्रिप्ट कड़ाई से आपके आंशिक रूप से मिलती है, तो बस अपने आंशिक के भीतर अपनी जावास्क्रिप्ट सीधे इनलाइन <script> टैग के अंदर रखें और इसके साथ किया जाए (यदि आप आंशिक उपयोग करने का इरादा रखते हैं तो बस स्क्रिप्ट डुप्लिकेशन से सावधान रहें एक बार में एक से अधिक बार);


पहला समाधान जो मैं सोच सकता हूं, प्रस्तुत करने वाले मानों को संग्रहीत करने के लिए व्यूबैग का उपयोग करना है।

अगर मैंने आंशिक दृश्य से यह काम किया है, तो मैंने कभी कोशिश नहीं की, लेकिन इसे इमो करना चाहिए।


प्लूटो का विचार एक अच्छे तरीके से:

CustomWebViewPage.cs:

    public abstract class CustomWebViewPage<TModel> : WebViewPage<TModel> {

    public IHtmlString PartialWithScripts(string partialViewName, object model) {
        return Html.Partial(partialViewName: partialViewName, model: model, viewData: new ViewDataDictionary { ["view"] = this, ["html"] = Html });
    }

    public void RenderScriptsInBasePage(HelperResult scripts) {
        var parentView = ViewBag.view as WebPageBase;
        var parentHtml = ViewBag.html as HtmlHelper;
        parentView.DefineSection("scripts", () => {
            parentHtml.ViewContext.Writer.Write(scripts.ToHtmlString());
        });
    }
}

दृश्य \ web.config:

<pages pageBaseType="Web.Helpers.CustomWebViewPage">

राय:

@PartialWithScripts("_BackendSearchForm")

आंशिक (_BackendSearchForm.cshtml):

@{ RenderScriptsInBasePage(scripts()); }

@helper scripts() {
<script>
    //code will be rendered in a "scripts" section of the Layout page
</script>
}

लेआउट पेज:

@RenderSection("scripts", required: false)

मुझे इसी तरह की समस्या हल हुई थी:

@section ***{
@RenderSection("****", required: false)
}

मुझे लगता है कि इंजेक्ट करने के लिए एक सुंदर तरीका है।


मुझे एक ही समस्या थी, जहां मेरे पास एक मास्टर पेज था:

@section Scripts {
<script>
    $(document).ready(function () {
        ...
    });
</script>
}

...

@Html.Partial("_Charts", Model)

लेकिन आंशिक दृश्य स्क्रिप्ट अनुभाग में कुछ जावास्क्रिप्ट पर निर्भर था। मैंने इसे आंशिक दृश्य को JSON के रूप में एन्कोड करके हल किया, इसे एक जावास्क्रिप्ट चर में लोड किया और फिर इसका उपयोग div को पॉप्युलेट करने के लिए किया, इसलिए:

@{
    var partial = Html.Raw(Json.Encode(new { html = Html.Partial("_Charts", Model).ToString() }));
}

@section Scripts {
<script>
    $(document).ready(function () {
        ...
        var partial = @partial;
        $('#partial').html(partial.html);
    });
</script>
}

<div id="partial"></div>

मैंने इसे एक पूरी तरह से अलग मार्ग हल किया (क्योंकि मैं जल्दी में था और एक नया एचटीएमएलहेपर लागू नहीं करना चाहता था):

मैंने अपने आंशिक दृश्य को एक बड़े में लपेट लिया यदि अन्य कथन:

@if ((bool)ViewData["ShouldRenderScripts"] == true){
// Scripts
}else{
// Html
}

फिर, मैंने कस्टम व्यूडेटा के साथ आंशिक दो बार बुलाया:

@Html.Partial("MyPartialView", Model, 
    new ViewDataDictionary { { "ShouldRenderScripts", false } })

@section scripts{
    @Html.Partial("MyPartialView", Model, 
        new ViewDataDictionary { { "ShouldRenderScripts", true } })
}

यदि आपके पास partial से कुछ js चलाने की वैध आवश्यकता है, तो यहां आप यह कैसे कर सकते हैं, jQuery आवश्यक है:

<script type="text/javascript">        
    function scriptToExecute()
    {
        //The script you want to execute when page is ready.           
    }

    function runWhenReady()
    {
        if (window.$)
            scriptToExecute();                                   
        else
            setTimeout(runWhenReady, 100);
    }
    runWhenReady();
</script>

यह मेरे लिए काम करता है जो मुझे उसी फ़ाइल में आंशिक दृश्य के लिए जावास्क्रिप्ट और एचटीएमएल को सह-पहचानने की इजाजत देता है। समान आंशिक दृश्य फ़ाइल में एचटीएमएल और संबंधित भाग देखने के लिए विचार प्रक्रिया के साथ मदद करता है।

व्यू में जो आंशिक दृश्य का उपयोग करता है जिसे "_MyPartialView.cshtml" कहा जाता है

<div>
    @Html.Partial("_MyPartialView",< model for partial view>,
            new ViewDataDictionary { { "Region", "HTMLSection" } } })
</div>

@section scripts{

    @Html.Partial("_MyPartialView",<model for partial view>, 
                  new ViewDataDictionary { { "Region", "ScriptSection" } })

 }

आंशिक दृश्य फ़ाइल में

@model SomeType

@{
    var region = ViewData["Region"] as string;
}

@if (region == "HTMLSection")
{


}

@if (region == "ScriptSection")
{
        <script type="text/javascript">
    </script">
}

वेब के बारे में सोचने के तरीके में विशेष रूप से एमवीसी का उपयोग करते समय एक मौलिक दोष है। दोष यह है कि जावास्क्रिप्ट किसी भी तरह से दृश्य की ज़िम्मेदारी है। एक दृश्य एक दृश्य है, जावास्क्रिप्ट (व्यवहार या अन्यथा) जावास्क्रिप्ट है। सिल्वरलाइट और डब्ल्यूपीएफ के एमवीवीएम पैटर्न में हमें "पहले देखें" या "मॉडल पहले" का सामना करना पड़ रहा है। एमवीसी में हमें हमेशा मॉडल के दृष्टिकोण से तर्क करने की कोशिश करनी चाहिए और जावास्क्रिप्ट कई तरीकों से इस मॉडल का हिस्सा है।

मैं AMD पैटर्न का उपयोग करने का सुझाव RequireJS (मैं खुद को आवश्यकताजेएस की तरह)। जावास्क्रिप्ट को लोड करने के दृश्य पर भरोसा करने के बजाय जावास्क्रिप्ट से अपनी जावास्क्रिप्ट को अलग करें, अपनी कार्यक्षमता को परिभाषित करें और जावास्क्रिप्ट से अपने एचटीएमएल में हुक करें। यह आपके कोड को साफ करेगा, आपकी चिंताओं को अलग करेगा और जीवन को आसान बना देगा, सब एक झुकाव में गिर जाएगा।


unobtrusive सिद्धांत के बाद, स्क्रिप्ट अनुभाग में सामग्री को इंजेक्ट करने के लिए "_myPartial" के लिए यह आवश्यक नहीं है। आप उन आंशिक दृश्य स्क्रिप्ट को अलग .js फ़ाइल में जोड़ सकते हैं और उन्हें मूल दृश्य से @ स्क्रिप्ट अनुभाग में संदर्भित कर सकते हैं।


आप इन एक्सटेंशन विधियों का उपयोग कर सकते हैं : (PartialWithScript.cs के रूप में सहेजें)

namespace System.Web.Mvc.Html
{
    public static class PartialWithScript
    {
        public static void RenderPartialWithScript(this HtmlHelper htmlHelper, string partialViewName)
        {
            if (htmlHelper.ViewBag.ScriptPartials == null)
            {
                htmlHelper.ViewBag.ScriptPartials = new List<string>();
            }

            if (!htmlHelper.ViewBag.ScriptPartials.Contains(partialViewName))
            {
                htmlHelper.ViewBag.ScriptPartials.Add(partialViewName);
            }

            htmlHelper.ViewBag.ScriptPartialHtml = true;
            htmlHelper.RenderPartial(partialViewName);
        }

        public static void RenderPartialScripts(this HtmlHelper htmlHelper)
        {
            if (htmlHelper.ViewBag.ScriptPartials != null)
            {
                htmlHelper.ViewBag.ScriptPartialHtml = false;
                foreach (string partial in htmlHelper.ViewBag.ScriptPartials)
                {
                    htmlHelper.RenderPartial(partial);
                }
            }
        }
    }
}

इस तरह प्रयोग करें:

उदाहरण आंशिक: (_MyPartial.cshtml) एचटीएमएल को अगर और अन्य में जेएस डाल दें।

@if (ViewBag.ScriptPartialHtml ?? true)
    <p>I has htmls</p>
}
else {
    <script type="text/javascript">
        alert('I has javascripts');
    </script>
}

आपके _Layout.cshtml में, या जहां भी आप आंशिक से स्क्रिप्ट को प्रस्तुत करना चाहते हैं, निम्न (एक बार) डालें: यह इस स्थान पर वर्तमान पृष्ठ पर केवल सभी आंशिकों की जावास्क्रिप्ट प्रस्तुत करेगा।

@{ Html.RenderPartialScripts(); }

फिर अपने आंशिक का उपयोग करने के लिए, बस यह करें: यह केवल इस स्थान पर HTML प्रस्तुत करेगा।

@{Html.RenderPartialWithScript("~/Views/MyController/_MyPartial.cshtml");}




partial-views