Kısmi Bir Razor Bölümünü Doldurma


103

Bunu yapmaya çalışmak için ana motivasyonum, Javascript'in sadece bir kısmının gerekli olduğu Javascript'i Javascript'in geri kalanıyla birlikte sayfanın alt kısmına ve kısmının işlendiği sayfanın ortasına değil.

İşte yapmaya çalıştığım şeyin basitleştirilmiş bir örneği:

Burada, gövdenin hemen önünde bir Komut Dosyaları bölümü bulunan düzen.

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />    
</head>

<body>
    @RenderBody()
    <script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
    @RenderSection("Scripts", false)
</body>
</html>

İşte bu düzeni kullanan bir örnek görünüm.

<h2>This is the view</h2>

@{Html.RenderPartial("_Partial");}

@section Scripts {
<script type="text/javascript">
        alert("I'm a view.");
</script>
}

Ve işte görünümden yapılan kısmi varlık.

<p>This is the partial.</p>

@* this never makes it into the rendered page *@
@section Scripts {
<script type="text/javascript">
    alert("I'm a partial."); 
</script>
}

Bu örnekte, görünümde belirtilen biçimlendirme bölüme yerleştirilir, ancak kısmi biçimlendirme yerleştirilmez. Razor ile kısmi bir görünümden bir bölümü doldurmak mümkün müdür? Değilse, Javascript'i global olarak dahil etmeden sayfanın alt kısmındaki bölümler için ihtiyaç duyulan diğer bazı yöntemler nelerdir?


belki bu bir sorun çünkü kısmi olarak başka bir komut dosyası bölümünüz var .. IDK .. kodunuz biraz kafa karıştırıcı ..
gideon

Değil. Bölüm görünümün dışında bırakılsa bile, kısmi kod, onu son oluşturulan sayfaya dönüştürmez. Bence SLaks, bölümlerin ebeveyn görünümünün bölümlerine katılamayacağı konusunda haklı.
Craig M

Yanıtlar:


78

Bununla uğraşma şeklim, HtmlHelper sınıfına birkaç uzantı yöntemi yazmaktır. Bu, kısmi görünümlerin bir komut dosyası gerektirdiklerini söylemelerine ve ardından gerekli komut dosyalarını yayınlamak için yardımcı yöntemime çağırdığım etiketi yazan düzen görünümünde

İşte yardımcı yöntemler:

public static string RequireScript(this HtmlHelper html, string path, int priority = 1)
{
    var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
    if (requiredScripts == null) HttpContext.Current.Items["RequiredScripts"] = requiredScripts = new List<ResourceInclude>();
    if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority });
    return null;
}

public static HtmlString EmitRequiredScripts(this HtmlHelper html)
{
    var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
    if (requiredScripts == null) return null;
    StringBuilder sb = new StringBuilder();
    foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
    {
        sb.AppendFormat("<script src=\"{0}\" type=\"text/javascript\"></script>\n", item.Path);
    }
    return new HtmlString(sb.ToString());
}
public class ResourceInclude
{
    public string Path { get; set; }
    public int Priority { get; set; }
}

Bunu yerine getirdikten sonra kısmi görünümünüzün çağrılması gerekir @Html.RequireScript("/Path/To/Script").

Ve düzen görünümünün baş bölümünde aradığınız @Html.EmitRequiredScripts().

Bunun ek bir avantajı, yinelenen komut dosyası isteklerini ayıklamanıza izin vermesidir. Belirli bir betiğe ihtiyaç duyan birden çok görünümünüz / kısmi görünümünüz varsa, yalnızca bir kez çıktı alacağınızı güvenle varsayabilirsiniz.


Zarif ve temiz çözüm. +1
bevacqua

Saçımın çoğunu çektikten sonra bu çözüme rastladım - mükemmel çözüm ...
Saçımın

Bu çözümün işe yaramasını sağlayamıyorum. Görünüşe göre EmitRequiredScripts (), herhangi bir kısmi görünüm RequireScript () 'i çağırmadan önce çağrılıyor. Yanlış bir şey mi yapıyorum?
Bryan Roth

Bir şeyler doğru gelmiyor Bryan. Bu çözümü geçen yıl boyunca yoğun bir şekilde kullandım ve iyi çalışıyor. Belki sorununuzun ayrıntılarını içeren yeni bir soru gönderin ve url'yi buraya
Mr Bell

1
Uygulamanın yeni bir sürümünü dağıtırken bunun herhangi bir önbellek bozma desteği var mı? Kutudan çıkan @ scripts.Render () yöntemi, son sürümün yeni bir sürüm dağıtıldığında tarayıcının en son sürümü getirmeye zorlanması için derleme sırasında oluşturulan bir URL parametresi yapıştırır.
Simon Green

28

Kısmi görünümler, ebeveyn görünümlerinin bölümlerine katılamaz.


1
Bu şüphelendiğim şey. Teşekkürler.
Craig M

@JohnBubriski Razor'da var 2. Önceki hakkında bilmiyorum. sürümler.
Shimmy Weitzhandler

@SLaks, bu neden tasarım gereği? Benim senaryomda bir başlık döndürücüsü olan bir kısmım var, komut dosyalarının / stillerinin yalnızca açıkken yüklenmesini istiyorum, onu satır içi olarak yüklemek neden kötü?
Shimmy Weitzhandler

2
@Shimmy: Kaset gibi bir kaynak yönetim sistemi kullanmalısınız.
SLaks

Teşekkür ederim. Ben inceleyeceğim.
Shimmy Weitzhandler

14

Sadece gerekli javascript'i enjekte etmekten sorumlu ikinci bir bölümünüz olabilir. @ifİsterseniz, blokların etrafına birkaç komut dosyası yerleştirin :

@model string
@if(Model == "bla") {
    <script type="text/javascript">...</script>
}

@else if(Model == "bli") {
    <script type="text/javascript">...</script>
}

Bu açıkça biraz temizlenebilirdi, ama sonra, Scriptsgörüşünüzün bölümünde:

@section Scripts
{
    @Html.Partial("_Scripts", "ScriptName_For_Partial1")
}

Yine bir güzellik ödülü kazanmayabilir ama işe yarayacak.


1
Bu yaptığım şeye oldukça yakın. Kesinlikle hoş değil ama işe yarıyor. Bunun tek dezavantajı, bir ajax çağrısı yoluyla parçayı alamamanız ve JS'yi dahil edememenizdir. Uzun vadede düşünüyorum, jQuery şablonlarını kullanarak yeniden düzenleme yapacağım ve sunucu tarafında html oluşturmak yerine sadece denetleyicilerimden JSON göndereceğim.
Craig M

@CraigM benim de gittiğim yer. MVC yasal, ancak şablonları istemci tarafında kullanmak (Backbone.js'ye bakıyorum) ve ardından bir API'den itmek / çekmek çok daha mantıklı geliyor (benim için).
one.beat.consumer

@ one.beat.customer - Backbone'u da kullandığımdan beri altçizgi şablonlarını kullanıyorum, ancak Twitter'dan Hogan kitaplığına veya Nodejitsu'dan Plates'e geçmeyi düşünüyorum. Her ikisinin de oldukça güzel özellikleri var.
Craig M

10

Bunu yapmanın daha zarif yolu, kısmi görünüm komut dosyalarını ayrı bir dosyaya taşımak ve ardından bunu, görünümün Komut Dosyaları bölümünde işlemektir:

<h2>This is the view</h2>

@Html.RenderPartial("_Partial")

@section Scripts
{
    @Html.RenderPartial("_PartialScripts")

    <script type="text/javascript">
        alert("I'm a view script.");
    </script>
}

Kısmi görünüm _ Partial.cshtml :

<p>This is the partial.</p>

Kısmi görünüm _ PartialScripts.cshtml yalnızca komut dosyalarıyla:

<script type="text/javascript">
    alert("I'm a partial script!");
</script>

Bu, diğer yanıtlarda önerilen bazı uzantı yöntemleri veya eklentiler kadar otomatik değildir, ancak basitlik ve açıklık avantajına sahiptir. Hoşuna gitti.
Mark Meuer

7

Forloop.HtmlHelpers'ı yükleyin nuget paketini - kısmi görünümlerde ve düzenleyici şablonlarında komut dosyalarını yönetmek için bazı yardımcılar ekler.

Düzeninizde bir yerde aramanız gerekir

@Html.RenderScripts()

Bu, herhangi bir komut dosyası dosyasının ve komut dosyası bloğunun sayfada çıktısının alınacağı yer olacaktır, bu nedenle onu düzendeki ana komut dosyalarınızın ve bir komut dosyaları bölümünün (eğer varsa) sonrasına koymanızı tavsiye ederim.

Paketleme ile Web Optimizasyon Çerçevesi kullanıyorsanız, aşırı yüklemeyi kullanabilirsiniz.

@Html.RenderScripts(Scripts.Render)

böylece bu yöntem komut dosyalarını yazmak için kullanılır.

Artık bir görünüme, kısmi görünüme veya şablona komut dosyası dosyaları veya bloklar eklemek istediğinizde,

@using (Html.BeginScriptContext())
{
  Html.AddScriptFile("~/Scripts/jquery.validate.js");
  Html.AddScriptBlock(
    @<script type="text/javascript">
       $(function() { $('#someField').datepicker(); });
     </script>
  );
}

Yardımcılar, birden çok kez eklenirse yalnızca bir komut dosyası referansının oluşturulmasını ve ayrıca komut dosyalarının beklenen bir sırada işlenmesini sağlar.

  1. Yerleşim
  2. Parçalar ve Şablonlar (görünümde göründükleri sırayla, yukarıdan aşağıya)

5

[Güncellenen sürüm] @Necrocubus sorusunu takip eden sürüm, satır içi komut dosyalarını içerecek şekilde güncellendi.

public static class ScriptsExtensions
{
    const string REQ_SCRIPT = "RequiredScript";
    const string REQ_INLINESCRIPT = "RequiredInlineScript";
    const string REQ_STYLE = "RequiredStyle";

    #region Scripts
    /// <summary>
    /// Adds a script 
    /// </summary>
    /// <param name="html"></param>
    /// <param name="path"></param>
    /// <param name="priority">Ordered by decreasing priority </param>
    /// <param name="bottom"></param>
    /// <param name="options"></param>
    /// <returns></returns>
    public static string RequireScript(this IHtmlHelper html, string path, int priority = 1, bool bottom=false, params string[] options)
    {
        var ctxt = html.ViewContext.HttpContext;

        var requiredScripts = ctxt.Items[REQ_SCRIPT] as List<ResourceToInclude>;
        if (requiredScripts == null) ctxt.Items[REQ_SCRIPT] = requiredScripts = new List<ResourceToInclude>();
        if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceToInclude() { Path = path, Priority = priority, Options = options, Type=ResourceType.Script, Bottom=bottom});
        return null;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="html"></param>
    /// <param name="script"></param>
    /// <param name="priority">Ordered by decreasing priority </param>
    /// <param name="bottom"></param>
    /// <returns></returns>
    public static string RequireInlineScript(this IHtmlHelper html, string script, int priority = 1, bool bottom = false)
    {
        var ctxt = html.ViewContext.HttpContext;

        var requiredScripts = ctxt.Items[REQ_INLINESCRIPT] as List<InlineResource>;
        if (requiredScripts == null) ctxt.Items[REQ_INLINESCRIPT] = requiredScripts = new List<InlineResource>();
        requiredScripts.Add(new InlineResource() { Content=script, Priority = priority, Bottom=bottom, Type=ResourceType.Script});
        return null;
    }

    /// <summary>
    /// Just call @Html.EmitRequiredScripts(false)
    /// at the end of your head tag and 
    /// @Html.EmitRequiredScripts(true) at the end of the body if some scripts are set to be at the bottom.
    /// </summary>
    public static HtmlString EmitRequiredScripts(this IHtmlHelper html, bool bottom)
    {
        var ctxt = html.ViewContext.HttpContext;

        var requiredScripts = ctxt.Items[REQ_SCRIPT] as List<ResourceToInclude>;
        var requiredInlineScripts = ctxt.Items[REQ_INLINESCRIPT] as List<InlineResource>;
        var scripts = new List<Resource>();
        scripts.AddRange(requiredScripts ?? new List<ResourceToInclude>());
        scripts.AddRange(requiredInlineScripts ?? new List<InlineResource>());
        if (scripts.Count==0) return null;
        StringBuilder sb = new StringBuilder();
        foreach (var item in scripts.Where(s=>s.Bottom==bottom).OrderByDescending(i => i.Priority))
        {
            sb.Append(item.ToString());
        }
        return new HtmlString(sb.ToString());
    }
    #endregion Scripts

    #region Styles
    /// <summary>
    /// 
    /// </summary>
    /// <param name="html"></param>
    /// <param name="path"></param>
    /// <param name="priority">Ordered by decreasing priority </param>
    /// <param name="options"></param>
    /// <returns></returns>
    public static string RequireStyle(this IHtmlHelper html, string path, int priority = 1, params string[] options)
    {
        var ctxt = html.ViewContext.HttpContext;

        var requiredScripts = ctxt.Items[REQ_STYLE] as List<ResourceToInclude>;
        if (requiredScripts == null) ctxt.Items[REQ_STYLE] = requiredScripts = new List<ResourceToInclude>();
        if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceToInclude() { Path = path, Priority = priority, Options = options });
        return null;
    }

    /// <summary>
    /// Just call @Html.EmitRequiredStyles()
    /// at the end of your head tag
    /// </summary>
    public static HtmlString EmitRequiredStyles(this IHtmlHelper html)
    {
        var ctxt = html.ViewContext.HttpContext;

        var requiredScripts = ctxt.Items[REQ_STYLE] as List<ResourceToInclude>;
        if (requiredScripts == null) return null;
        StringBuilder sb = new StringBuilder();
        foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
        {
            sb.Append(item.ToString());
        }
        return new HtmlString(sb.ToString());
    }
    #endregion Styles

    #region Models
    public class InlineResource : Resource
    {
        public string Content { get; set; }
        public override string ToString()
        {
            return "<script>"+Content+"</script>";
        }
    }

    public class ResourceToInclude : Resource
    {
        public string Path { get; set; }
        public string[] Options { get; set; }
        public override string ToString()
        {
            switch(Type)
            {
                case ResourceType.CSS:
                    if (Options == null || Options.Length == 0)
                        return String.Format("<link rel=\"stylesheet\" href=\"{0}\" type=\"text/css\" />\n", Path);
                    else
                        return String.Format("<link rel=\"stylesheet\" href=\"{0}\" type=\"text/css\" {1} />\n", Path, String.Join(" ", Options));
                default:
                case ResourceType.Script:
                    if (Options == null || Options.Length == 0)
                        return String.Format("<script src=\"{0}\" type=\"text/javascript\"></script>\n", Path);
                    else
                        return String.Format("<script src=\"{0}\" type=\"text/javascript\" {1}></script>\n", Path, String.Join(" ", Options));
            }
        }
    }
    public class Resource
    {
        public ResourceType Type { get; set; }
        public int Priority { get; set; }
        public bool Bottom { get; set; }
    }
    public enum ResourceType
    {
        Script,
        CSS
    }
    #endregion Models
}

Benim 2 sentim, bu eski bir gönderi, ancak yine de geçerli, bu yüzden işte Bay Bell'in ASP.Net Core ile çalışan çözümünün yükseltilmiş bir güncellemesi.

İçe aktarılan kısmi görünümlerden ve alt görünümlerden ana mizanpaja komut dosyaları ve stiller eklemeye ve komut dosyası / stil içe aktarmalara seçenekler eklemeye olanak tanır (eşzamansız erteleme vb. Gibi):

public static class ScriptsExtensions
{
    const string REQ_SCRIPT = "RequiredScript";
    const string REQ_STYLE = "RequiredStyle";

    public static string RequireScript(this IHtmlHelper html, string path, int priority = 1, params string[] options)
    {
        var ctxt = html.ViewContext.HttpContext;

        var requiredScripts = ctxt.Items[REQ_SCRIPT] as List<ResourceInclude>;
        if (requiredScripts == null) ctxt.Items[REQ_SCRIPT] = requiredScripts = new List<ResourceInclude>();
        if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority, Options = options });
        return null;
    }


    public static HtmlString EmitRequiredScripts(this IHtmlHelper html)
    {
        var ctxt = html.ViewContext.HttpContext;

        var requiredScripts = ctxt.Items[REQ_SCRIPT] as List<ResourceInclude>;
        if (requiredScripts == null) return null;
        StringBuilder sb = new StringBuilder();
        foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
        {
            if (item.Options == null || item.Options.Length == 0)
                sb.AppendFormat("<script src=\"{0}\" type=\"text/javascript\"></script>\n", item.Path);
            else
                sb.AppendFormat("<script src=\"{0}\" type=\"text/javascript\" {1}></script>\n", item.Path, String.Join(" ", item.Options));

        }
        return new HtmlString(sb.ToString());
    }


    public static string RequireStyle(this IHtmlHelper html, string path, int priority = 1, params string[] options)
    {
        var ctxt = html.ViewContext.HttpContext;

        var requiredScripts = ctxt.Items[REQ_STYLE] as List<ResourceInclude>;
        if (requiredScripts == null) ctxt.Items[REQ_STYLE] = requiredScripts = new List<ResourceInclude>();
        if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority, Options = options });
        return null;
    }


    public static HtmlString EmitRequiredStyles(this IHtmlHelper html)
    {
        var ctxt = html.ViewContext.HttpContext;

        var requiredScripts = ctxt.Items[REQ_STYLE] as List<ResourceInclude>;
        if (requiredScripts == null) return null;
        StringBuilder sb = new StringBuilder();
        foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
        {
            if (item.Options == null || item.Options.Length == 0)
                sb.AppendFormat("<link rel=\"stylesheet\" href=\"{0}\" type=\"text/css\" />\n", item.Path);
            else
                sb.AppendFormat("<link rel=\"stylesheet\" href=\"{0}\" type=\"text/css\" {1} />\n", item.Path, String.Join(" ", item.Options));
        }
        return new HtmlString(sb.ToString());
    }


    public class ResourceInclude
    {
        public string Path { get; set; }
        public int Priority { get; set; }
        public string[] Options { get; set; }
    }
}

Teşekkür ederim dostum! Bu, 6 yıllık cevaptan daha alakalı olduğu için daha fazla oylanmalıdır.
Necroqubus

Ayrıca, bu uzantılar, komut dosyası bölümlerinin girdi olmasına izin verecek şekilde değiştirilebilir mi? @ <text> </text> veya bölümler gibi bir şey? Aksi takdirde, diğer komut dosyasını Sunucu tarafı model değişkenleriyle başlatmak için hala küçük bir JS betiğine ihtiyacım var: /
Necroqubus

@Necroqubus güncellenmiş sürümü kontrol edebilirsiniz, ancak henüz test etmedim :)
Jean

Pekala, senin için deneyip test edeceğim. Umarım ASP.NET Core 1.0 MVC ile çalışır. Bağlam için, birden çok düzeyde iç içe geçmiş bölümlerim var ve bunların komut dosyalarının altbilgide işlenmesini istiyorum.
Necroqubus

İhtiyacınız yok, <text>onu bir dize olarak ekleyin (isterseniz çoklu satır için @ "" önekini kullanabilirsiniz) ve <script>etiketler olmadan
Jean

1

Yeni bir Layoutsayfa oluşturabilir ve PartialView'ı, içeriklerin ve ayrıca herhangi bir kitaplık bölümünün işlenmesinden sorumlu olan Tam Görünüm'ün içine sarabilirsiniz.

Örneğin, aşağıdaki koda sahip olduğumu varsayalım:

HomeController.cs

[HttpGet]
public ActionResult About()
{
    var vm = new AboutViewModel();
    return View("About", vm);
}

Tam Sayfa görünümü oluşturulduğunda, genellikle iki dosya birleştirilerek oluşturulur:

About.cshtml

@model AboutViewModel

@{
    ViewBag.Title = "About CSHN";
}

<h3>@ViewBag.Title</h3>

@section Styles {
    <style> /* style info here */ </style>
}

@section Scripts {
    <script> /* script info here */ </script>
}

_Layout.cshtml (veya _ViewStart'ta belirtilen veya sayfada geçersiz kılınan her şey)

<!DOCTYPE html>

<html>
<head>
    @RenderSection("Styles", false)
    <title>@ViewBag.Title</title>
</head>
<body>
    @RenderBody()

    @RenderSection("scripts", false)
</body>
</html>

Şimdi , sen Render istediğini varsayalım About.cshtmlbir şekilde Kısmi Manzaralı belki AJAX çağrısına yanıt olarak kalıcı bir pencere olarak. Buradaki amaç, _Layout.cshtmlana mizanpaja dahil edilen tüm şişkinlikler olmadan yalnızca hakkında sayfasında, komut dosyalarında ve hepsinde belirtilen içeriği döndürmektir (tam<html> belge ) .

Bu şekilde deneyebilirsiniz, ancak bölüm bloklarının hiçbiriyle gelmeyecektir:

return PartialView("About", vm);

Bunun yerine, şuna benzer daha basit bir düzen sayfası ekleyin:

_PartialLayout.cshtml

<div>
    @RenderBody()
    @RenderSection("Styles", false)
    @RenderSection("scripts", false)
</div>

Veya bunun gibi kalıcı bir pencereyi desteklemek için:

_ModalLayout.cshtml

<div class="modal modal-page fade" tabindex="-1" role="dialog" >
    <div class="modal-dialog modal-lg" role="document">
        <div class="modal-content">

            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                <h4 class="modal-title">@ViewBag.Title</h4>
            </div>

            <div class="modal-body">

                @RenderBody()
                @RenderSection("Styles", false)
                @RenderSection("scripts", false)

            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-inverse" data-dismiss="modal">Dismiss</button>
            </div>
        </div>
    </div>
</div>

Ardından , bu denetleyicide veya bir görünümün içeriğini ve komut dosyalarını aynı anda işlemek istediğiniz başka bir işleyicide özel bir Ana Görünüm belirleyebilirsiniz.

[HttpGet]
public ActionResult About()
{
    var vm = new AboutViewModel();
    return !Request.IsAjaxRequest()
              ? View("About", vm)
              : View("About", "~/Views/Shared/_ModalLayout.cshtml", vm);
}

1

Aspnet core 2.0 sürümünü arayanlar için:

    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.AspNetCore.Html;
    using Microsoft.AspNetCore.Http;

    public static class HttpContextAccessorExtensions
    {
        public static string RequireScript(this IHttpContextAccessor htmlContextAccessor, string path, int priority = 1)
        {
            var requiredScripts = htmlContextAccessor.HttpContext.Items["RequiredScripts"] as List<ResourceInclude>;
            if (requiredScripts == null) htmlContextAccessor.HttpContext.Items["RequiredScripts"] = requiredScripts = new List<ResourceInclude>();
            if (requiredScripts.All(i => i.Path != path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority });
            return null;
        }

        public static HtmlString EmitRequiredScripts(this IHttpContextAccessor htmlContextAccessor)
        {
            var requiredScripts = htmlContextAccessor.HttpContext.Items["RequiredScripts"] as List<ResourceInclude>;
            if (requiredScripts == null) return null;
            StringBuilder sb = new StringBuilder();
            foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
            {
                sb.AppendFormat("<script src=\"{0}\" type=\"text/javascript\"></script>\n", item.Path);
            }
            return new HtmlString(sb.ToString());
        }
        public class ResourceInclude
        {
            public string Path { get; set; }
            public int Priority { get; set; }
        }
    }

Komut dosyası oluşturma bölümü çağrısından sonra düzeninize ekleyin:

@HttpContextAccessor.EmitRequiredScripts()

Ve kısmi görünümünüzde:

@inject IHttpContextAccessor HttpContextAccessor

...

@HttpContextAccessor.RequireScript("/scripts/moment.min.js")

0

Yukarıdaki Bay Bell And Shimmy'nin cevabına dayanarak, Bundle betiği için ekstra fonksiyon ekliyorum.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.Web.Mvc;
namespace ABC.Utility
{
public static  class PartialViewHelper
{
    public static string RequireScript(this HtmlHelper html, string path, int priority = 1)
    {
        var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
        if (requiredScripts == null) HttpContext.Current.Items["RequiredScripts"] = requiredScripts = new List<ResourceInclude>();
        if (!requiredScripts.Any(i => i.Path == path)) requiredScripts.Add(new ResourceInclude() { Path = path, Priority = priority });
        return null;
    }

    public static string RequireBundleStyles(this HtmlHelper html, string bundleName)
    {
        var a = System.Web.Optimization.Styles.Render(bundleName);
        var requiredStyles = HttpContext.Current.Items["RequiredStyles"] as IHtmlString;
        if (requiredStyles == null) HttpContext.Current.Items["RequiredStyles"] = requiredStyles = a;
        return null;
    }

    public static string RequireBundleScripts(this HtmlHelper html, string bundleName)
    {
        var a=System.Web.Optimization.Scripts.Render(bundleName);
        var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as IHtmlString;
        if (requiredScripts == null) HttpContext.Current.Items["RequiredScripts"] = requiredScripts = a;
        return null;
    }

    public static HtmlString EmitRequiredBundleStyles(this HtmlHelper html)
    {
        var requiredStyles = HttpContext.Current.Items["RequiredStyles"] as IHtmlString;
        if (requiredStyles == null) return null;
        return MvcHtmlString.Create(requiredStyles.ToHtmlString()) ;
    }

    public static HtmlString EmitRequiredBundleScripts(this HtmlHelper html)
    {
        var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as IHtmlString;
        if (requiredScripts == null) return null;
        return MvcHtmlString.Create(requiredScripts.ToHtmlString());
    }

    public static HtmlString EmitRequiredScripts(this HtmlHelper html)
    {
        var requiredScripts = HttpContext.Current.Items["RequiredScripts"] as List<ResourceInclude>;
        if (requiredScripts == null) return null;
        StringBuilder sb = new StringBuilder();
        foreach (var item in requiredScripts.OrderByDescending(i => i.Priority))
        {
            sb.AppendFormat("<script src=\"{0}\" type=\"text/javascript\"></script>\n", item.Path);
        }
        return new HtmlString(sb.ToString());
    }
    public class ResourceInclude
    {
        public string Path { get; set; }
        public int Priority { get; set; }
    }
}//end class
}// end namespace  

PartialView üzerinde örnek: - @ Html.RequireBundleStyles ("~ / bundles / fileupload / bootstrap / BasicPlusUI / css"); @ Html.RequireBundleScripts ("~ / bundles / fileupload / bootstrap / BasicPlusUI / js");

MasterPage üzerinde örnek: - @ Html.EmitRequiredBundleStyles ()


0

Herhangi bir içeriği (komut dosyaları veya yalnızca HTML) sayfada daha sonra görüntülemek için https://stackoverflow.com/a/18790222/1037948@using(Html.Delayed()){ ...your content... } yanıtındaki uzantıları kullanın . Dahili doğru sıralamayı sağlamalıdır.Queue


0

Bu işlevsellik, ClientDependency.Core.Mvc.dll'de de uygulanır. Html yardımcılarını sağlar: @ Html.RequiresJs ve @ Html.RenderJsHere (). Nuget paketi: ClientDependency-Mvc


0

Burada sıkça sorulan sorulara çözümümü "Kısmi görünümlerden ana görünümlere veya asp.net mvc için ana düzen görünümüne bölümler nasıl enjekte edilir?" Stackoverflow üzerinde "bölüm + kısmi" anahtar kelimelerine göre bir arama yaparsanız, oldukça büyük bir ilgili soru listesi alırsınız ve cevaplar verilir, ancak bunların hiçbiri jilet motoru dilbilgisi sayesinde bana şık görünmüyor. Bu yüzden Razor motoruna bir göz atıp bu soruya daha iyi bir çözüm olup olmadığını görüyorum.

Neyse ki, Razor motorunun görünüm şablon dosyası (* .cshtml, * .vbhtml) için derlemeyi nasıl yaptığına dair ilginç bir şey buldum. (Daha sonra açıklayacağım), aşağıda oldukça basit ve kullanım açısından yeterince zarif olduğunu düşündüğüm çözüm kodum var.

namespace System.Web.Mvc.Html
{
    public static class HtmlHelperExtensions
    {
        /// <summary>
        /// 确保所有视图,包括分部视图(PartialView)中的节(Section)定义被按照先后顺序追加到最终文档输出流中
        /// </summary>
        public static MvcHtmlString EnsureSection(this HtmlHelper helper)
        {
            var wp = (WebViewPage)helper.ViewDataContainer;
            Dictionary<string, WebPages.SectionWriter> sw = (Dictionary<string, WebPages.SectionWriter>)typeof(WebPages.WebPageBase).GetProperty("SectionWriters", Reflection.BindingFlags.NonPublic | Reflection.BindingFlags.Instance).GetValue(wp);
            if (!helper.ViewContext.HttpContext.Items.Contains("SectionWriter"))
            {
                Dictionary<string, Stack<WebPages.SectionWriter>> qss = new Dictionary<string, Stack<WebPages.SectionWriter>>();
                helper.ViewContext.HttpContext.Items["SectionWriter"] = qss;
            }
            var eqs = (Dictionary<string, Stack<WebPages.SectionWriter>>)helper.ViewContext.HttpContext.Items["SectionWriter"];
            foreach (var kp in sw)
            {
                if (!eqs.ContainsKey(kp.Key)) eqs[kp.Key] = new Stack<WebPages.SectionWriter>();
                eqs[kp.Key].Push(kp.Value);
            }
            return MvcHtmlString.Create("");
        }

        /// <summary>
        /// 在文档流中渲染指定的节(Section)
        /// </summary>
        public static MvcHtmlString RenderSectionEx(this HtmlHelper helper, string section, bool required = false)
        {
            if (helper.ViewContext.HttpContext.Items.Contains("SectionWriter"))
            {
                Dictionary<string, Stack<WebPages.SectionWriter>> qss = (Dictionary<string, Stack<WebPages.SectionWriter>>)helper.ViewContext.HttpContext.Items["SectionWriter"];
                if (qss.ContainsKey(section))
                {
                    var wp = (WebViewPage)helper.ViewDataContainer;
                    var qs = qss[section];
                    while (qs.Count > 0)
                    {
                        var sw = qs.Pop();
                        var os = ((WebViewPage)sw.Target).OutputStack;
                        if (os.Count == 0) os.Push(wp.Output);
                        sw.Invoke();
                    }
                }
                else if (!qss.ContainsKey(section) && required)
                {
                    throw new Exception(string.Format("'{0}' section is not defined.", section));
                }
            }
            return MvcHtmlString.Create("");
        }
    }
}

kullanım : Kodu kullanmak da oldukça basittir ve her zamanki gibi neredeyse aynı stilde görünür. Ayrıca, iç içe geçmiş kısmi görünümlere yönelik tüm seviyeleri destekler. yani. Bir görünüm şablon zincirim var: _ViewStart.cshtml-> layout.cshtml-> index.cshtml -> [head.cshtml, foot.cshtml] -> ad.cshtml.

Layout.cshtml'de şunlara sahibiz:

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>@ViewBag.Title - @ViewBag.WebSetting.Site.WebName</title>
    <base href="@ViewBag.Template/" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta http-equiv="Cache-Control" content="no-siteapp" />
    <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1.0, user-scalable=0,user-scalable=no">
    <meta name="format-detection" content="telephone=no">
    <meta name="renderer" content="webkit">
    <meta name="author" content="Taro Technology Co.,LTD" />
    <meta name="robots" content="index,follow" />
    <meta name="description" content="" />
    <meta name="keywords" content="" />
    <link rel="alternate icon" type="@ViewBag.WebSetting.Site.WebFavIcon" href="@ViewBag.WebSetting.Site.WebFavIcon">
    @Html.RenderSectionEx("Head")
</head>
<body>
    @RenderBody()
    @Html.RenderSectionEx("Foot")
</body>
</html>

Ve index.cshtml'de şunlara sahibiz:

@{
    ViewBag.Title = "首页";
}

@Html.Partial("head")
<div class="am-container-1">
    .......
</div>
@Html.Partial("foot")

Ve head.cshtml'de koda sahip olurduk:

@section Head{
    <link rel="stylesheet" href="assets/css/amazeui.css" />
    <link rel="stylesheet" href="assets/css/style.css" />
}

<header class="header">
   ......
</header>
@Html.EnsureSection()

foot.cshtml veya ad.cshtml'de de aynıdır, bunlarda Baş veya Ayak bölümünü tanımlamaya devam edebilirsiniz, kısmi görünüm dosyasının sonunda @ Html.EnsureSection () 'ı çağırdığınızdan emin olun. Asp mvc'de konu olan sorundan kurtulmak için yapmanız gereken tek şey bu.

Kod parçacığımı başkalarının da kullanabilmesi için paylaşıyorum. Yararlı olduğunu düşünüyorsanız, lütfen gönderimi derecelendirmekten çekinmeyin. :)

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.