web-dev-qa-db-ger.com

Einfügen von Inhalten in bestimmte Abschnitte aus einer Teilansicht von ASP.NET MVC 3 mit Razor View Engine

Ich habe diesen Abschnitt in meinem _Layout.cshtml definiert.

@RenderSection("Scripts", false)

Ich kann es leicht aus einer Sicht verwenden: 

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

Ich habe Schwierigkeiten damit, wie man aus einer Teilansicht Inhalte in diesen Abschnitt injiziert.

Nehmen wir an, dies ist meine Ansichtsseite: 

@section Scripts { 

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

<div>
    poo bar poo
</div>

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

Ich muss etwas Inhalt aus der _myPartial-Teilansicht in den Abschnitt Scripts einfügen.

Wie kann ich das machen?

293
tugberk

Abschnitte funktionieren nicht in Teilansichten und das ist beabsichtigt. Sie können einige benutzerdefinierte Helfer verwenden, um ein ähnliches Verhalten zu erreichen, aber ehrlich gesagt liegt es in der Verantwortung der Ansicht, die erforderlichen Skripts einzubeziehen, nicht die Verantwortung des Teils. Ich würde empfehlen, den @scripts-Abschnitt der Hauptansicht zu verwenden, um dies zu tun, und sich nicht die Teilaspekte um Skripte kümmern zu müssen.

214
Darin Dimitrov

Dies ist eine sehr beliebte Frage, deshalb werde ich meine Lösung posten.
Ich hatte das gleiche Problem und obwohl es nicht ideal ist, denke ich, dass es wirklich gut funktioniert und das partielle nicht von der Ansicht abhängig macht.
Mein Szenario war, dass eine Aktion für sich selbst zugänglich war, aber auch in eine Ansicht eingebettet werden konnte - eine Google-Map.

In meinem _layout habe ich: 

@RenderSection("body_scripts", false)

In meiner index-Ansicht habe ich:

@Html.Partial("Clients")
@section body_scripts
{
    @Html.Partial("Clients_Scripts")
}

In meiner clients-Ansicht habe ich (alle map und assoc. Html):

@section body_scripts
{
    @Html.Partial("Clients_Scripts")
}

Meine Clients_Scripts-Ansicht enthält das Javascript, das auf der Seite dargestellt werden soll

Auf diese Weise wird mein Skript isoliert und kann bei Bedarf in die Seite gerendert werden, wobei das body_scripts-Tag nur beim ersten Vorkommen gerendert wird, das von der Razor-View-Engine gefunden wird.

Damit kann ich alles getrennt haben - es ist eine Lösung, die für mich ganz gut funktioniert, andere haben vielleicht Probleme damit, aber sie behebt die Lücke "von Design".

78
dan richardson

Von den Lösungen in diesem Thread habe ich die folgende, wahrscheinlich überkomplizierte Lösung gefunden, mit der Sie das Rendern von HTML (Skripts) innerhalb eines using-Blocks verzögern können.

VERWENDUNGSZWECK

Erstellen Sie den "Abschnitt"

  1. Typisches Szenario: Fügen Sie in einer Teilansicht den Block nur einmal ein, unabhängig davon, wie oft die Teilansicht auf der Seite wiederholt wird:

    @using (Html.Delayed(isOnlyOne: "some unique name for this section")) {
        <script>
            someInlineScript();
        </script>
    }
    
  2. Fügen Sie in einer Teilansicht den Block für jede Verwendung des Teils ein:

    @using (Html.Delayed()) {
        <b>show me multiple times, @Model.Whatever</b>
    }
    
  3. Fügen Sie den Block in einer Teilansicht nur einmal ein, unabhängig davon, wie oft der Teil wiederholt wird, und rendern Sie ihn später spezifisch mit dem Namen when-i-call-you:

    @using (Html.Delayed("when-i-call-you", isOnlyOne: "different unique name")) {
        <b>show me once by name</b>
        <span>@Model.First().Value</span>
    }
    

Rendern Sie die "Abschnitte"

(d. h. Anzeige des verzögerten Abschnitts in einer übergeordneten Ansicht)

@Html.RenderDelayed(); // writes unnamed sections (#1 and #2, excluding #3)
@Html.RenderDelayed("when-i-call-you", false); // writes the specified block, and ignore the `isOnlyOne` setting so we can dump it again
@Html.RenderDelayed("when-i-call-you"); // render the specified block by name
@Html.RenderDelayed("when-i-call-you"); // since it was "popped" in the last call, won't render anything due to `isOnlyOne` provided in `Html.Delayed`

CODE

public static class HtmlRenderExtensions {

    /// <summary>
    /// Delegate script/resource/etc injection until the end of the page
    /// <para>@via https://stackoverflow.com/a/14127332/1037948 and http://jadnb.wordpress.com/2011/02/16/rendering-scripts-from-partial-views-at-the-end-in-mvc/ </para>
    /// </summary>
    private class DelayedInjectionBlock : IDisposable {
        /// <summary>
        /// Unique internal storage key
        /// </summary>
        private const string CACHE_KEY = "DCCF8C78-2E36-4567-B0CF-FE052ACCE309"; // "DelayedInjectionBlocks";

        /// <summary>
        /// Internal storage identifier for remembering unique/isOnlyOne items
        /// </summary>
        private const string UNIQUE_IDENTIFIER_KEY = CACHE_KEY;

        /// <summary>
        /// What to use as internal storage identifier if no identifier provided (since we can't use null as key)
        /// </summary>
        private const string EMPTY_IDENTIFIER = "";

        /// <summary>
        /// Retrieve a context-aware list of cached output delegates from the given helper; uses the helper's context rather than singleton HttpContext.Current.Items
        /// </summary>
        /// <param name="helper">the helper from which we use the context</param>
        /// <param name="identifier">optional unique sub-identifier for a given injection block</param>
        /// <returns>list of delayed-execution callbacks to render internal content</returns>
        public static Queue<string> GetQueue(HtmlHelper helper, string identifier = null) {
            return _GetOrSet(helper, new Queue<string>(), identifier ?? EMPTY_IDENTIFIER);
        }

        /// <summary>
        /// Retrieve a context-aware list of cached output delegates from the given helper; uses the helper's context rather than singleton HttpContext.Current.Items
        /// </summary>
        /// <param name="helper">the helper from which we use the context</param>
        /// <param name="defaultValue">the default value to return if the cached item isn't found or isn't the expected type; can also be used to set with an arbitrary value</param>
        /// <param name="identifier">optional unique sub-identifier for a given injection block</param>
        /// <returns>list of delayed-execution callbacks to render internal content</returns>
        private static T _GetOrSet<T>(HtmlHelper helper, T defaultValue, string identifier = EMPTY_IDENTIFIER) where T : class {
            var storage = GetStorage(helper);

            // return the stored item, or set it if it does not exist
            return (T) (storage.ContainsKey(identifier) ? storage[identifier] : (storage[identifier] = defaultValue));
        }

        /// <summary>
        /// Get the storage, but if it doesn't exist or isn't the expected type, then create a new "bucket"
        /// </summary>
        /// <param name="helper"></param>
        /// <returns></returns>
        public static Dictionary<string, object> GetStorage(HtmlHelper helper) {
            var storage = helper.ViewContext.HttpContext.Items[CACHE_KEY] as Dictionary<string, object>;
            if (storage == null) helper.ViewContext.HttpContext.Items[CACHE_KEY] = (storage = new Dictionary<string, object>());
            return storage;
        }


        private readonly HtmlHelper helper;
        private readonly string identifier;
        private readonly string isOnlyOne;

        /// <summary>
        /// Create a new using block from the given helper (used for trapping appropriate context)
        /// </summary>
        /// <param name="helper">the helper from which we use the context</param>
        /// <param name="identifier">optional unique identifier to specify one or many injection blocks</param>
        /// <param name="isOnlyOne">extra identifier used to ensure that this item is only added once; if provided, content should only appear once in the page (i.e. only the first block called for this identifier is used)</param>
        public DelayedInjectionBlock(HtmlHelper helper, string identifier = null, string isOnlyOne = null) {
            this.helper = helper;

            // start a new writing context
            ((WebViewPage)this.helper.ViewDataContainer).OutputStack.Push(new StringWriter());

            this.identifier = identifier ?? EMPTY_IDENTIFIER;
            this.isOnlyOne = isOnlyOne;
        }

        /// <summary>
        /// Append the internal content to the context's cached list of output delegates
        /// </summary>
        public void Dispose() {
            // render the internal content of the injection block helper
            // make sure to pop from the stack rather than just render from the Writer
            // so it will remove it from regular rendering
            var content = ((WebViewPage)this.helper.ViewDataContainer).OutputStack;
            var renderedContent = content.Count == 0 ? string.Empty : content.Pop().ToString();
            // if we only want one, remove the existing
            var queue = GetQueue(this.helper, this.identifier);

            // get the index of the existing item from the alternate storage
            var existingIdentifiers = _GetOrSet(this.helper, new Dictionary<string, int>(), UNIQUE_IDENTIFIER_KEY);

            // only save the result if this isn't meant to be unique, or
            // if it's supposed to be unique and we haven't encountered this identifier before
            if( null == this.isOnlyOne || !existingIdentifiers.ContainsKey(this.isOnlyOne) ) {
                // remove the new writing context we created for this block
                // and save the output to the queue for later
                queue.Enqueue(renderedContent);

                // only remember this if supposed to
                if(null != this.isOnlyOne) existingIdentifiers[this.isOnlyOne] = queue.Count; // save the index, so we could remove it directly (if we want to use the last instance of the block rather than the first)
            }
        }
    }


    /// <summary>
    /// <para>Start a delayed-execution block of output -- this will be rendered/printed on the next call to <see cref="RenderDelayed"/>.</para>
    /// <para>
    /// <example>
    /// Print once in "default block" (usually rendered at end via <code>@Html.RenderDelayed()</code>).  Code:
    /// <code>
    /// @using (Html.Delayed()) {
    ///     <b>show at later</b>
    ///     <span>@Model.Name</span>
    ///     etc
    /// }
    /// </code>
    /// </example>
    /// </para>
    /// <para>
    /// <example>
    /// Print once (i.e. if within a looped partial), using identified block via <code>@Html.RenderDelayed("one-time")</code>.  Code:
    /// <code>
    /// @using (Html.Delayed("one-time", isOnlyOne: "one-time")) {
    ///     <b>show me once</b>
    ///     <span>@Model.First().Value</span>
    /// }
    /// </code>
    /// </example>
    /// </para>
    /// </summary>
    /// <param name="helper">the helper from which we use the context</param>
    /// <param name="injectionBlockId">optional unique identifier to specify one or many injection blocks</param>
    /// <param name="isOnlyOne">extra identifier used to ensure that this item is only added once; if provided, content should only appear once in the page (i.e. only the first block called for this identifier is used)</param>
    /// <returns>using block to wrap delayed output</returns>
    public static IDisposable Delayed(this HtmlHelper helper, string injectionBlockId = null, string isOnlyOne = null) {
        return new DelayedInjectionBlock(helper, injectionBlockId, isOnlyOne);
    }

    /// <summary>
    /// Render all queued output blocks injected via <see cref="Delayed"/>.
    /// <para>
    /// <example>
    /// Print all delayed blocks using default identifier (i.e. not provided)
    /// <code>
    /// @using (Html.Delayed()) {
    ///     <b>show me later</b>
    ///     <span>@Model.Name</span>
    ///     etc
    /// }
    /// </code>
    /// -- then later --
    /// <code>
    /// @using (Html.Delayed()) {
    ///     <b>more for later</b>
    ///     etc
    /// }
    /// </code>
    /// -- then later --
    /// <code>
    /// @Html.RenderDelayed() // will print both delayed blocks
    /// </code>
    /// </example>
    /// </para>
    /// <para>
    /// <example>
    /// Allow multiple repetitions of rendered blocks, using same <code>@Html.Delayed()...</code> as before.  Code:
    /// <code>
    /// @Html.RenderDelayed(removeAfterRendering: false); /* will print */
    /// @Html.RenderDelayed() /* will print again because not removed before */
    /// </code>
    /// </example>
    /// </para>

    /// </summary>
    /// <param name="helper">the helper from which we use the context</param>
    /// <param name="injectionBlockId">optional unique identifier to specify one or many injection blocks</param>
    /// <param name="removeAfterRendering">only render this once</param>
    /// <returns>rendered output content</returns>
    public static MvcHtmlString RenderDelayed(this HtmlHelper helper, string injectionBlockId = null, bool removeAfterRendering = true) {
        var stack = DelayedInjectionBlock.GetQueue(helper, injectionBlockId);

        if( removeAfterRendering ) {
            var sb = new StringBuilder(
#if DEBUG
                string.Format("<!-- delayed-block: {0} -->", injectionBlockId)
#endif
                );
            // .count faster than .any
            while (stack.Count > 0) {
                sb.AppendLine(stack.Dequeue());
            }
            return MvcHtmlString.Create(sb.ToString());
        } 

        return MvcHtmlString.Create(
#if DEBUG
                string.Format("<!-- delayed-block: {0} -->", injectionBlockId) + 
#endif
            string.Join(Environment.NewLine, stack));
    }


}
36
drzaus

Ich hatte dieses Problem und benutzte diese Technik.

Es ist die beste Lösung, die ich gefunden habe, die sehr flexibel ist. 

Auch bitte stimmen Siehier , um Unterstützung für die kumulative Sektionserklärung hinzuzufügen

15
iBoy

Wenn Sie eine legitime Notwendigkeit haben, eine js von einer partial auszuführen, können Sie Folgendes tun: jQuery ist erforderlich:

<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>
8
Serj Sagan

Gemäß dem Prinzip unaufdringlich ist es nicht unbedingt erforderlich, dass "_myPartial" Inhalte direkt in den Skriptabschnitt einfügt. Sie können diese partiellen Ansichtsskripts zu einer separaten .js-Datei hinzufügen und sie aus der übergeordneten Ansicht in den Abschnitt @scripts einfügen.

8
archil

Es gibt einen grundlegenden Fehler in der Art und Weise, wie wir über das Internet denken, insbesondere bei der Verwendung von MVC. Der Fehler ist, dass JavaScript irgendwie in der Verantwortung der Ansicht liegt. Eine Ansicht ist eine Ansicht. JavaScript (verhaltensmäßig oder anderweitig) ist JavaScript. Im MVVM-Muster von Silverlight und WPF sehen wir uns mit "Ansicht zuerst" oder "Modell zuerst" konfrontiert. In MVC sollten wir immer versuchen, aus Sicht des Modells zu argumentieren, und JavaScript ist in vielerlei Hinsicht ein Teil dieses Modells. 

Ich würde vorschlagen, das AMD - Muster zu verwenden (ich selbst mag RequireJS ). Trennen Sie JavaScript in Modulen, definieren Sie Ihre Funktionalität und hängen Sie von JavaScript in Ihre HTML ein, anstatt sich auf eine Ansicht zu verlassen, um das JavaScript zu laden. Dies wird Ihren Code bereinigen, Ihre Anliegen trennen und das Leben einfacher machen.

4
Mr. Baudin

Die erste Lösung, die mir einfällt, ist die Verwendung von ViewBag zum Speichern der Werte, die gerendert werden müssen. 

Onestly habe ich nie ausprobiert, ob diese Arbeit aus einer partiellen Sicht, aber es sollte imo.

2
Iridio

Sie können diese Erweiterungsmethoden verwenden : (Speichern als 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);
                }
            }
        }
    }
}

Gebrauch wie folgt:

Beispiel partiell: (_MyPartial.cshtml) Setzen Sie das HTML in das if und das js in das else.

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

Fügen Sie in Ihrer _Layout.cshtml-Datei oder an der Stelle, an der Sie die Skripte der Partials darstellen möchten, Folgendes ein (einmalig): Es wird nur das Javascript aller Partials auf der aktuellen Seite an diesem Ort dargestellt.

@{ Html.RenderPartialScripts(); }

Um Ihr Partial zu verwenden, führen Sie einfach Folgendes aus: Es wird nur die HTML-Datei an dieser Stelle dargestellt.

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

Es gibt eine Möglichkeit, Abschnitte in Teilansichten einzufügen, obwohl dies nicht schön ist. Sie müssen Zugriff auf zwei Variablen aus der übergeordneten Ansicht haben. Da ein Teil der Teilansicht gerade dazu dient, diesen Abschnitt zu erstellen, ist es sinnvoll, diese Variablen zu benötigen.

So sieht es aus, einen Abschnitt in die Teilansicht einzufügen:

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

Und auf der Seite, die die Teilansicht einfügt ...

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

Sie können diese Technik auch verwenden, um den Inhalt eines Abschnitts in jeder Klasse programmgesteuert zu definieren.

Genießen!

1
Pluto

Dies funktionierte für mich und erlaubte mir, Javascript und HTML für eine teilweise Ansicht in derselben Datei zu lokalisieren. Hilft beim Nachdenken, HTML und verwandten Teil in derselben Teilansicht-Datei anzuzeigen.


In der Ansicht, die die Teilansicht namens "_MyPartialView.cshtml" verwendet

<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" } })

 }

In der Teilansicht-Datei

@model SomeType

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

@if (region == "HTMLSection")
{


}

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

Sie können Abschnitte nicht in Teilansicht verwenden.

In Ihre Teilansicht einfügen . Die Funktion wird ausgeführt, nachdem jQuery geladen wurde . Sie können die Bedingungsklausel für Ihren Code ändern.

<script type="text/javascript">    
var time = setInterval(function () {
    if (window.jQuery != undefined) {
        window.clearInterval(time);

        //Begin
        $(document).ready(function () {
           //....
        });
        //End
    };
}, 10); </script>

Julio Spader

1
Julio Spader

Mit Mvc Core können Sie ein aufgeräumtes TagHelper scripts erstellen (siehe unten). Dies könnte leicht in ein section-Tag umgewandelt werden, in dem Sie auch einen Namen vergeben (oder der Name wird vom abgeleiteten Typ übernommen). Beachten Sie, dass die Abhängigkeitsinjektion für IHttpContextAccessor eingerichtet werden muss.

Beim Hinzufügen von Skripten (z. B. in einem unvollständigen)

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

Beim Ausgeben der Skripte (z. B. in einer Layoutdatei)

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

Code

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()));
            }
        }
    }
0
BlackjacketMack

Ich habe dies auf einem völlig anderen Weg gelöst (weil ich es eilig hatte und keinen neuen HtmlHelper implementieren wollte):

Ich habe meine Teilansicht in einer großen if-else-Anweisung zusammengefasst:

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

Dann rief ich den Partial zweimal mit einer benutzerdefinierten ViewData an:

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

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

wahlweise können Sie Ihre Folder/index.cshtml als Masterseite verwenden und dann Abschnittskripte hinzufügen. Dann haben Sie in Ihrem Layout:

@RenderSection("scripts", required: false) 

und Ihre index.cshtml:

@section scripts{
     @Scripts.Render("~/Scripts/file.js")
}

und es wird über alle Ihre Teilansichten arbeiten. Es funktioniert für mich

0
RogerEdward

Ich habe diesen Code gerade in meine Teilansicht aufgenommen und das Problem gelöst, obwohl es nicht sehr sauber ist. Sie müssen sicherstellen, dass die IDs der Objekte, die Sie rendern, vorhanden sind.

0
luis

Ich hatte ein ähnliches Problem, wo ich eine Masterseite wie folgt hatte:

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

...

@Html.Partial("_Charts", Model)

die teilweise Ansicht hing jedoch von etwas JavaScript im Abschnitt Scripts ab. Ich löste es, indem ich die Teilansicht als JSON codierte, sie in eine JavaScript-Variable lade und dann ein div auffüllte, also:

@{
    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>
0
John M

Plutos Idee auf eine schönere Weise:

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());
        });
    }
}

Ansichten\web.config:

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

Aussicht:

@PartialWithScripts("_BackendSearchForm")

Teilweise (_BackendSearchForm.cshtml):

@{ RenderScriptsInBasePage(scripts()); }

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

Layoutseite:

@RenderSection("scripts", required: false)
0
PaulSanS

Das Ziel des OP ist, dass er Inline-Skripte in seiner Teilansicht definieren möchte. Ich gehe davon aus, dass dieses Skript nur für diese Teilansicht gilt, und dass dieser Block in seinen Skriptabschnitt aufgenommen wird.

Ich verstehe, dass er diese Teilansicht haben will, um in sich geschlossen zu sein. Die Idee ist ähnlich wie bei der Verwendung von Angular. 

Mein Weg wäre, die Skripte einfach in der Teilansicht zu belassen. Jetzt ist das Problem beim Aufrufen von Partial View. Es kann das Skript dort vor allen anderen Skripts ausführen (die normalerweise am unteren Rand der Layoutseite hinzugefügt werden). In diesem Fall müssen Sie nur das Teilansicht-Skript auf die anderen Skripts warten. Dafür gibt es mehrere Möglichkeiten. Die einfachste, die ich zuvor verwendet habe, ist die Verwendung eines Ereignisses in body

Auf meinem Layout hätte ich etwas unten:

// global scripts
<script src="js/jquery.min.js"></script>
// view scripts
@RenderSection("scripts", false)
// then finally trigger partial view scripts
<script>
  (function(){
    document.querySelector('body').dispatchEvent(new Event('scriptsLoaded'));
  })();
</script>

Dann auf meiner Teilansicht (unten):

<script>
  (function(){
    document.querySelector('body').addEventListener('scriptsLoaded', function() {

      // .. do your thing here

    });
  })();
</script>

Eine andere Lösung ist die Verwendung eines Stapels, um alle Ihre Skripte zu pushen und am Ende jedes Skript aufzurufen. Eine andere Lösung, wie bereits erwähnt, ist das RequireJS/AMD-Pattern, das auch sehr gut funktioniert.

0
alans