معرفی Dynamic Bundles در MVC

جمعه 5 شهریور 1395

فایل های image , javascript , CSS , HTML که اجزای تشکیل دهنده یک صفحه هستند ، را در یک مکان قرار می دهیم . MVC Bundles خود را برای اطمینان از این که در طبقه بندی درستی بارگذاری شده اند ، Auto Generate می گذاریم .

معرفی Dynamic Bundles در MVC

معرفی :
هنگامی که سایت شما در پیچیدگی رشد میکند، این احساس ایجاد میشود که  maintainable بودن سایت باید با استفاده از Component ها حفظ شود،componentهایی همانند partial viewها،
DisplayTemplates و EditorTemplates .
مشکل این است که ،  هنگامی که شما HTML خود را از این راه سازماندهی می‌کنید ، فایل CSS و Javascript و image شما ، همچنان در دایرکتوری های خودشان ذخیره سازی شده اند ، 
با هیچ نشانه روشنی ، دقیقا همان چیزی که (فایل CSS و ...) توسط partial استفاده شده است . اساسا ، اجرای هر partial ، باعث گسترش 4 دایرکتوری میشود . 
که باعث سهولت در شکستن partial میشود ، زمانی که یک فایل CSS یا javascript را تغییر میدهید .  وابستگی بین فایل های HTML , CSS و JavaScript همیشه روشن و شفاف نیست ، که همین امر استفاده دوباره از Partial را در جای دیگر بسیار سخت می کند . 

شما می توانید با استفاده از MVC areas، این را تا حدودی رفع کنید،اما اینها اصولا درساختsub-sitesها
 استفاده قرار میگیرند . راه حل این مشکل این است که همه موجودی‌ها (CSS, JavaScript و images) را در یک مکان قرار دهید که از یکسری HTML در همان دایرکتوری پشتیبانی میکند . 

موجودی‌ها از همه صفحات Controller  پشتیبانی می‌کنند ، می‌توانند برای Controller به دایرکتوری View بروند . و موجودی‌هایی که در سرتاسر سایت به اشتراک گذاشته شده اند ، میتوانند به یک دایرکتوری سطح بالا بروند . 
این میتواند به تعداد زیادی فایلهای کوچک و متمرکز JavaScript ،CSS منجر شود. که درکل چیز خوبی است، اما باعث سختی ایجاد MVC bundles شما می‌شود.صفحات شما هنوز مجبور هستند تا CSS و JavaScript  مناسب در طبقه بندی مناسب را load کنند . برای کمک به این،به هنگام بارگذاری صفحه bundles توسط 
 Dynamic Bundles برای شما ایجاد می شود . Overhead ، Cashing را در حداقل حالت ممکن نگه میدارد . 

مزایای کلیدی :
Dynamic Bundles یکی از ضمیمه های Razor view engine و MVC bundles است ، که تا حد زیادی روند نگهداری (maintainability ) و استفاده دوباره (reuse) از کدهای سایت شما را بهبود می بخشد . 

 • همه فایل های HTML, CSS, JavaScript و images هایی که تشکیل دهنده صفحه شما هستند را ، در یک دایرکتوری یکسان قرار دهید ، به جای اینکه آنها را در دایرکتوری هایی بر اساس نوع آنها تقسیم بندی کنید . 


•  کوچک سازی یکسان و  ترکیب فایل های نرم افزاری تحت عنوان MVC bundles استاندارد را ، فراهم میکند . 

ساختار فایل :
بیایید مقایسه ای بر یک سایت MVC کلاسیک با سایتی که از Dynamic Bundles استفاده میکند ، داشته باشیم .  

Classic MVC :
• فایل های HTML, CSS, JavaScript و image ها براساس type در دایرکتوری های جداگانه سازماندهی میشوند .
 
 • CSS و JavaScriptهایی که از صفحات مختلف پشتیبانی میکنند و عناصر تشکیل دهنده آنها در یک دایرکتوری قرار دارد ، باعث ایجاد وابستگی مخفی (hidden dependencies) میشود .  

 • آدرس های شکننده طولانی از فایل های CSS برای تصاویر پس زمینه

 • معلوم نیست چه CSS ، javascript و image ای برای یک عنصر داده شده ،  مورد نیاز است . 


Dynamic Bundles :
• فایل های HTML, CSS, JavaScript و image هایی که متعلق به هم هستند در یک دایرکتوری یکسان قرار میگیرند . 
• 
view engine در Dynamic Bundlesهای نرم افزاری شما، امکان قرار دادن partial views وفایل های layout را در زیرشاخه خود دارند .
• برای حفظ کوچک و متمرکز بودن فایل های CSS و JavaScript آنها را به وسیله
 component encourages developers ، خرد می کنیم . 
• تصویر پس‌زمینه ساده با url کوتاه در CSS شما
• قرار دادن همه فایل های موجود در یک دایرکتوری ، استفاده دوباره (reuse) را بسیار آسان تر می سازد.
  


Bundles :
در این بخش می خواهیم راه های ساخت Bundles در MVC Classic را با یک سایت MVC که از Dynamic Bundles استفاده میکند ، مقایسه کنیم . 

Classic MVC :
• ایجاد و نگهداری از bundles  را مجبورید که خودتان انجام دهید . 
• شما باید اطمینان داشته باشید که شامل فایل های درست ، با طبقه بندی درست است . 
• زمانی که فایل CSS و یا Javascript اضافه یا حذف می شوند ، سایت نیاز به Compile دوباره دارد . 


public static void RegisterBundles(BundleCollection bundles)
{
    // Need to create bundles yourself, in code. To make any change,
    // you have to recompile. Must always make sure to include the
    // right files in the right order.

    bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                "~/Scripts/jquery-{version}.js"));

    bundles.Add(new ScriptBundle("~/bundles/shared/js").Include(
                "~/Scripts/SharedCode.js",
                "~/Scripts/VariousCode.js"));

    bundles.Add(new ScriptBundle("~/bundles/pile/js").Include(
                "~/Scripts/PileOfCode.js"));

    bundles.Add(new StyleBundle("~/Content/shared/css").Include(
                "~/Content/Reset.css",
                "~/Content/Site.css"));

    bundles.Add(new StyleBundle("~/Content/account/css").Include(
                "~/Content/Account.css"));
}

public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        // No need to register bundles in BundleConfig
    }
}

@*Nominate where to load the bundles.
The bundles themselves are automatically generated.*@
@DynamicBundlesTopRender()
...
@RenderBody()
...
@DynamicBundlesBottomRender()


Installation :

a. نصب Dynamic Bundles
b. اضافه کردن view engine به global.asax
c. اضافه کردن layout Container
d. بروزرسانی Web.config برای viewها 
e. قرار دادن همه فایل ها و موجودی در یک دایرکتوری  
f. ایجاد وابستگی صریح 


1. نصب Dynamic Bundles :
 
DynamicBundles package از Nuget نصب کنید . 

Install-Package DynamicBundles


2. اضافه کردن view engine به global.asax :
 
global.asax.cs  خود را بروزرسانی کنید ، برای اضافه کردن DynamicBundles view engine 

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        // Add DynamicBundles view engine. This functions the same as the Razor view engine,
        // but can find views sitting in their own directories, such as ~/Views/Home/Index/Index.cshtml
        // Note: this leaves the other view engines in place, so they can still be used.
        ViewEngines.Engines.Add(new DynamicBundles.DynamicBundlesViewEngine()); 
    }

    ...
}


3. اضافه کردن layout Container :

در سایت های MVC classic ، صفحات دارای یک _Layout.cshtml هستند ، که شامل header , footer و ... های به اشتراک گذاشته شده (shared) هستند . 
مشکل ما در زمان معرفی Dynamic Bundles این است که ما خواهان جداسازی 
CSS, JavaScript and picturesهایی هستیم که مختص layout هستند و برای سرتاسر سایت shared شده اند .   
برای ایجاد این جداسازی ، یک فایل جدید با نام LayoutContainer.cshtml_ میسازیم . این فایل و 
Layout.cshtml_ در دایرکتوری های خودشان قرار می گیرند . 


Dynamic Bundles :


محتوای LayoutContainer.cshtml_  :

<!DOCTYPE html>
<html>
    @*Nominate where to load the bundles. The bundles themselves are automatically generated.*@
    @DynamicBundlesTopRender()

    @RenderBody()

    @DynamicBundlesBottomRender()
</html>


تغییراتی در  _Layout.cshtml :

a. ا layout را روی LayoutContainer.cshtml_ تنظیم کنید ، که به عنوان ظرف کلی از سایت عمل می کند .
b. ا doctype و html tagها را حذف کنید . 
c. تمام styleها و script renderingای که شامل بخش rendering of script هستند ، را حذف کنید.

@{
    // Add _LayoutContainer as the container for the _Layout.cshtml file itself.
    Layout = "../_LayoutContainer/_LayoutContainer.cshtml";
}

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>Dynamic Bundles for ASP.NET MVC</title>

    @Styles.Render("~/Content/shared/css")
    @Styles.Render("~/Content/account/css")
</head>
<body>
    @RenderBody()

    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/shared/js")
    @Scripts.Render("~/bundles/pile/js")

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

4. علاوه بر فایل Web.config در دایرکتوری ریشه سایت خود ، هر سایت MVC همچنین دارای یک فایل Web.config در دایرکتوری View نیز هست . اگر سایت شما از areaها استفاده میکند ، هر area یک دایرکتوری view دارد که فایل web.config خودش را دارد . 
 

فایل های web.config در دایرکتوری های view نیاز دارند که به مواردی که در زیر ذکر میشود ، بروز رسانی شوند :

a. صفحه بر مبنای Dynamic Bundles را نصب کنید . هر view را برای register موجودی هایی که نیاز دارد ، میگیرد .
b.  به
 وب سرور برای خدمت به CSS، جاوا اسکریپت و فایل های تصویری از دایرکتوری های view ، اجازه می دهد.

<configuration>
  <system.web.webPages.razor>
    <pages pageBaseType="System.Web.Mvc.WebViewPageDynamicBundles.WebViewPage">
      ...
    </pages>
  </system.web.webPages.razor>

  <system.webServer>
  
    <!--
    The BlockViewHandler blocks all requests. In classic MVC sites, it is used to block all requests for files from
    a Views directory. With Dynamic Bundles where CSS, JavaScript and images files are co-located with the view files,
    we only want to block requests for the view files.
    -->
    
    <handlers>
      <remove name="BlockViewHandler"/> 
      <!-- Replace path="*.cshtml" with path="*.vbhtml" if you use Visual Basic. -->
      <add name="BlockViewHandler" path="*.cshtml" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
    </handlers>
  </system.webServer>
</configuration>


5. قرار دادن همه فایل ها و موجودی در یک دایرکتوری :

درنهایت همه  فایل های موجودی خود (CSS, JavaScript, images) ، با view ها را در جایی استفاده می شوند ، قرار دهید :

• همه موجودی هایی که در سایت shared هستند را در دایرکتوری  LayoutContainer_ قرار دهید .





•  تمام موجودی هایی که برای تمام viewهای یک shared ، controller هستند را در دایرکتوری همان Controller قرار دهید . 



• اگر در اینجا یک موجودی ، مختص یک view تنها است ، یک زیر شاخه برای view بسازید و همه موجودی های مربوط به آن view را در آن sub directory که ایجاد کرده اید ، قرار دهید . 
توجه داشته باشید که نام sub directory باید با نام view یکی باشد فقط بدون پسوندش . 



•  Dynamic Bundles هم به موجودی ها در sub directory ها و هم به directoryهای والد آنها اضافه خواهد شد . در مثال زیر ، وقتی /Product/List بارگذاری می شود ، ابتدا موجودی های به 
Views/Product/~ و سپس آنها به Views/Product/List/~ اضافه خواهند شد . 

این هم برای Controller مختص viewها کار میکند هم برای controller مختص partial) view)ها .
Dynamic Bundles تضمین میکند که موجودی ها فقط یکبار به یک bundles اضافه می شوند .




6. ایجاد وابستگی صریح :

ممکن است که شما از یک دایرکتوری وابستگیهایی به دیگران داشته باشید ، برای مثال یک فایل Javascript را فرض کنید که در یک دایرکتوری دیگر load می شود . 
شما با استفاده از nuspec. میتوانید وابستگیها را  مشخص کنید . اینها همان ساختار یکسان، همانند NuGet خود را دارند . 
اگر Dynamic Bundles یک فایل nuspec در یک دایرکتوری پیدا کرد ، آن دایرکتوری های مشخص شده در فایل nuspec را پیدا خواهد کرد وموجودی ها را به دایرکتوریها اضافه خواهد کرد . 
اگر این دایرکتوری ها خودشان نیز فایل nuspec داشتند ، دوباره  Dynamic Bundles همین پردازش را تکرار میکند . این یک فرآیند کاملا مکرر است . 

برای ایجاد وابستگی از دایرکتوری X به دیگر دایرکتوری ها ، یک فایل nuspec همانند زیر در دایرکتوری X میگذاریم :

<?xml version="1.0"?>
<package >
  <metadata>
      <dependencies>
        <dependency id="../AccountDetailsAssets" />
        <dependency id="~/Views/Shared/DetailsAssets" />
      </dependencies>
  </metadata>
</package>

توجه داشته باشید که :
• نام فایل nuspec اصلا مهم نیست ، بعد از نام آن پسوند nuspec. باید گذاشته شود .

آموزش asp.net mvc

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید