نظرات مطالب
سفارشی سازی ASP.NET Core Identity - قسمت پنجم - سیاست‌های دسترسی پویا
ممنون بابت پاسخگویی.
فرض کنید در SampleController، اکشنی به نام Edit وجود دارد که سبب نمایش فرم ویرایش میشود که این فرم حاوی دراپ دانی می‌باشد که  اطلاعات خود رو از اکشنی مجزا به نام GetData در همان کنترلر به صورت ajax دریافت میکند.اگر بخواهیم با روش فعلی به این موارد دسترسی دهیم به حالت زیر خواهیم رسید:
 مشاهده فرم ویرایش   SampleController:Edit  ✓ 
 مشاهده محتویات دراپ دان  SampleController:GetData  ✓ 
در این حالت صفحه بدون مشکل لود شده و محتویات دراپ دان نمایش داده میشود.حالتی که تنها اکشن  index به calim افزوده شود در این حالت صفحه بارگذاری میشود اما محتویات دراپ دان به دلیل اینکه در Calim وجود ندارد لود نخواهد شد و درخواست ajax با خطای 401 مواجه میشود. 
روشی وجود دارد که با انتخاب اکشن Edit تمامی اکشن‌های مورد نیاز در فرم ویرایش نیز به Calim اضافه گردد؟
نظرات مطالب
بارگزاری PartialView با استفاده از jQuery در زمان اجرا
باسلام و خسته نباشید. 
من مثال فوق را خط به خط اجرا کردم ولی partial view  نمایش داده نمیشه. فکر کنم مکان  قطعه کد Ajax  را اشتباه جایگذاری کردم اگه ممکنه راهنمائی می‌کنید که قطعه:
 $( function () {
$.ajax({
//مشخص کردن  اکشنی که باید فراخوانی شود
url: '/Home/Details' ,
contentType: 'application/html; charset=utf-8' ,
type: 'GET' ,
//نوع نتیجه بازگشتی
dataType: 'html'
 
})
.success( function (result) {
  //زمانی که کدهای سمت سرور بدون خطا اجرا شده اند
  //این قسمت فراخوانی می‌شود و نتیجه اکشن درون متغیر
  //result
  //قرار می‌گیرد
  $( '#sectionContents' ).html(result);
})
.error( function (xhr, status) {
  alert(xhr.responseText);
});
  });
دقیقا کجای Index باید قرارداده بشه؟ سورس پروژه را هم ارسال می‌کردید خیلی خوب می‌شد .
ممنون. 
نظرات مطالب
متدهای کمکی مفید در پروژه های asp.net mvc
خروجی json در یک View یعنی متغیری از نوع جاوا اسکریپت. این متغیر به صورت مستقیم در کدهای یک htmlHelper قابل استفاده نیست (چون از نوع دات نت و سی شارپ یا وی بی است).
در اینجا تبدیل تاریخ مدنظر را باید همان طرف کدهای کنترلر انجام داد. یا این طرف از توابع جاوا اسکریپتی تبدیل تاریخ میلادی به شمسی باید استفاده کرد. دو context مختلف را نمی‌شود در آن واحد با هم ترکیب کرد.
البته می‌شود داخل کدهای جاوا اسکریپتی یک View از کدهای مثلا Razor استفاده کرد اما این کدها در زمان اجرا به صورت جاوا اسکریپتی پردازش و رندر می‌شوند و نه به فرمت مثلا سی شارپ. برای نمونه می‌شود در یک View داخل کدهای JavaScript موجود از Url.Action استفاده کرد. این مورد در زمان اجرا فقط تبدیل به یک رشته JavaScript می‌شود. البته این نکته برای بکارگیری Html.FarsiDateAndTime نیز صدق می‌کند و فراخوانی آن باید داخل کدهای Ajax جاوا اسکریپتی یک View باشد (و نه خارج از آن چون context دیگر JavaScript نخواهد بود). همچنین باید درنظر داشت که Html.FarsiDateAndTime در زمان رندر شدن جاوا اسکریپت موجود در یک View، تبدیل به معادل رشته‌ای آن شده و جایگزین می‌شود. یعنی در قسمت نتیجه یک عملیات Ajax قابل استفاده نخواهد بود.

مطالب دوره‌ها
کار با فرم‌ها در بوت استرپ 3
در مطلب «استفاده از Twitter Bootstrap در کارهای روزمره طراحی وب» به نکات مرتبط با کار با فرم‌ها در بوت استرپ 2 پرداخته شد. همچنین مطالبی مانند «ویرایش قالب پیش فرض Add View در ASP.NET MVC برای سازگار سازی آن با Twitter bootstrap» برای خودکار سازی تولید فرم‌های بوت استرپ 2 در برنامه‌های ASP.NET MVC و نکات «اعمال کلاس‌های ویژه اعتبارسنجی Twitter bootstrap به فرم‌های ASP.NET MVC» نیز بررسی شدند. در بوت استرپ 3، بسیاری از این نکات تغییر کرده‌اند و نیاز است با نحوه ارتقاء فرم‌های بوت استرپ 2 به 3 و کلا نحوه کار با فرم‌ها در بوت استرپ 3 بیشتر آشنا شد.


نحوه ارتقاء فرم‌های بوت استرپ 2 به 3

تمام این تغییرات در بوت استرپ 3، جهت پیاده سازی ایده mobile-first بودن آن است. برای مثال فرم‌های افقی بوت استرپ 3 با کوچک شدن اندازه صفحه، به صورت خودکار واکنش نشان داده و تبدیل به فرم‌های معمولی که اجزای آن به صورت یک stack عمودی قرار گرفته‌اند، می‌شوند.
اکنون اگر فرم‌هایی را دارید که در برنامه‌های پیشین خود از بوت استرپ 2 استفاده کرده‌اند، نیاز است تغییرات ذیل را به آن‌ها اعمال کنید تا با سیستم جدید بوت استرپ 3 سازگار شوند:

- کلاس control-group را به کلاس form-group تبدیل کنید.
- form-search حذف شده است. آن‌را با form-inline جایگزین کنید.
- دیگر نیازی به استفاده از input-block-level نیست؛ از آنجائیکه به صورت پیش فرض کلیه inputها دارای عرض 100 درصد هستند.
- help-inline حذف شده است. آن‌را با help-block جایگزین کنید.
- عرض ستون‌ها را در فرم‌های افقی، برچسب‌ها و کنترل‌ها مشخص کنید.
- کلاس controls حذف شده است.
- کلاس form-control را به inputها و selectها اضافه کنید.
- checkboxها و radioها باید در یک div محصور شوند.
- کلاس‌های radio.inline و checkbox.inline باید با inline جایگزین شوند.
- کلاس‌های input-small به input-sm و input-large به input-lg تبدیل شده‌اند.
- کلاس‌های input-prepend با input-group و input-append با input-group جایگزین شده‌اند.
- کلاس alert-error حذف شده‌است. بجای آن می‌شود از alert-warning استفاده کرد.
- کلاس alert-block را با alert جایگزین کنید.


ایجاد اولین فرم افقی با بوت استرپ 3

فرض کنید که قصد داریم یک چنین فرم افقی را توسط امکانات بوت استرپ 3 ایجاد کنیم:



همانطور که ملاحظه می‌کنید، با کوچک شدن اندازه صفحه، این فرم نیز تغییر شکل می‌دهد:



کدهای کامل این فرم را در ادامه ملاحظه می‌کنید:
    <div class="container">
        <h4 class="alert alert-info">
            فرم‌های بوت استرپ 3</h4>
        <div class="row">
            <article class="registrationform">
                <h2>
                    فرم ثبت نام</h2>               
                <form class="registration form-horizontal" action="#">
                <fieldset id="personalinfo">
                    <legend>اطلاعات شخصی</legend>
                    <section class="row">
                        <label class="col col-lg-4 control-label" for="myname">
                            نام</label>
                        <div class="controls">
                            <input class="col col-lg-8" type="text" name="myname" 
                                   id="myname" autofocus placeholder="نام و نام خانوادگی"
                                   required>
                        </div>
                        <!-- controls -->
                    </section><!-- row -->
                    <section class="row">
                        <label class="col col-lg-4 control-label" for="companyname">
                            نام شرکت</label>
                        <div class="controls">
                            <input class="col col-lg-8" type="text" name="companybname" id="companyname" />
                        </div>
                        <!-- controls -->
                    </section><!-- row -->
                    <section class="row">
                        <label class="col col-lg-4 control-label" for="myemail">
                            ایمیل</label>
                        <div class="controls">
                            <input class="col col-lg-8" type="email" name="myemail" id="myemail" 
                                   required autocomplete="off" />
                        </div>
                        <!-- controls -->
                    </section><!-- row -->
                </fieldset>
                <!-- personal info -->
                <fieldset id="otherinfo">
                    <legend>سایر اطلاعات</legend>
                    <section class="row">
                        <label class="col col-lg-4 control-label">
                            نوع درخواست</label>
                        <div class="controls col col-lg-8">
                            <label class="radio">
                                <input type="radio" name="requesttype" value="question" />
                                سؤال
                            </label>
                            <label class="radio">
                                <input type="radio" name="requesttype" value="comment" />
                                انتقاد
                            </label>
                        </div>
                        <!-- controls -->
                    </section><!-- row -->
                    <section class="row">
                        <label class="col col-lg-4 control-label">
                            خبرنامه</label>
                        <div class="controls col col-lg-8">
                            <label class="checkbox">
                                <input type="checkbox" id="subscribe" name="subscribe" checked value="yes" />
                               آیا مایل به دریافت ایمیل‌های خبرنامه ما هستید؟
                            </label>
                        </div>
                        <!-- controls -->
                    </section><!-- row -->
                    <section class="row">
                        <label class="col col-lg-4 control-label" for="reference">
                            چطور از وجود سایت ما آگاه شدید؟</label>
                        <div class="controls col col-lg-8">
                            <select name="reference" id="reference">
                                <option>لطفا انتخاب کنید...</option>
                                <option value="friend">از طریق یک دوست</option>
                                <option value="facebook">Facebook</option>
                                <option value="twitter">Twitter</option>
                            </select>
                        </div>
                        <!-- controls -->
                    </section><!-- row -->
                </fieldset>
                <button class="btn" type="submit">
                    ارسال</button>
                </form>
            </article>
        </div>
        <!-- end row -->
    </div>
    <!-- /container -->
توضیحات:

- باید درنظر داشت که اگر هیچگونه فرمتی را به فرم‌های بوت استرپ 3 اعمال نکنیم، به صورت پیش فرض فرمت دهی شده و تبدیل به فرم‌های عمودی شکیلی می‌شوند که شاید از دیدگاه خیلی‌ها مناسب بوده و نیاز به تغییرات خاصی نداشته باشند.
- برای تبدیل این فرم عمودی پیش فرض، به فرم‌های افقی دو ستونه، نیاز است یک سری کلاس بوت استرپ 3 را به المان‌های آن اضافه کنیم. برای این منظور ابتدا کلاس form-horizontal را به تگ فرم اضافه می‌کنیم.
- هر سطر فرم، در یک المان section با کلاس row قرار خواهد گرفت.
- اکنون هر سطر، از یک برچسب به همراه یک یا چند المان تشکیل خواهد شد. در هر سطر، کنترل‌ها در یک div با کلاس controls قرار می‌گیرند.
- برای اینکه برچسب‌های هر ردیف با کنترل‌ها و المان‌های آن ردیف، تراز شوند، تنها کافی است به آن‌ها کلاس control-label را اضافه کنیم.
در ادامه تمام این مراحل را باید به ازای هر سطر فرم تکرار کنیم.

- زمانیکه به radio buttons یا check boxes می‌رسیم، باید به چند نکته دقت داشت:
الف) حین کار با radio buttons، علاوه بر برچسب آن سطر که با label مشخص می‌شود، هر radio button نیز باید داخل یک label با کلاس radio محصور شود.
ب) تمام radio buttons یک سطر نیز باید در یک div ایی با کلاس controls محصور شوند.
این نکته در مورد check boxes نیز صادق است.

با رعایت همین چند نکته ساده می‌توان به یک طراحی دو ستونی خودکار واکنشگرا رسید.



اصلاح قالب ایجاد فرم‌های خودکار ASP.NET MVC بر اساس بوت استرپ 3

مطلب «ویرایش قالب پیش فرض Add View در ASP.NET MVC برای سازگار سازی آن با Twitter bootstrap» جهت بوت استرپ 2 تهیه شده بود. فایل نهایی ویرایش شده آن‌را با توجه به توضیحات مطلب جاری برای بوت استرپ 3 از پیوست انتهای بحث دریافت کنید و برای استفاده از آن فقط کافی است آن‌را در مسیر CodeTemplates\AddView\CSHTML\CreateBootstrap3Form.tt ریشه پروژه جاری خود کپی و به پروژه اضافه کنید تا در صفحه دیالوگ Add view ظاهر شود (خاصیت custom tool آن‌را هم خالی کنید).


در مورد اعتبارسنجی‌های فرم‌ها چطور؟

اصلاح مطالبی مانند «اعمال کلاس‌های ویژه اعتبارسنجی Twitter bootstrap به فرم‌های ASP.NET MVC» جهت کار با فرم‌های بوت استرپ 3 بسیار ساده است. از این جهت که در کدهای آن فقط باید نام کلاس‌های CSS قدیمی به جدید ویرایش شوند. مابقی کدها یکسان است. مثلا نام کلاس control-group شده است form-group (همان توضیحات ابتدای بحث جاری). کلاس‌های error شده‌اند has-error و success شده است has-success.



فایل‌های نهایی این قسمت را از اینجا نیز می‌توانید دریافت کنید:
bs3-sample05.zip  
مطالب
چگونه نرم افزارهای تحت وب سریعتری داشته باشیم؟ قسمت هفتم
قسمت ششم 

20.اسکریپت در پایین صفحه
لینک‌های مربوطه به javascript‌های خود را تا جای ممکن در پایین صفحه قرار دهید. وقتی parser مرورگر به فایل‌های javascript می‌رسد، تمامی فعالیت‌ها را متوقف کرده و سعی در دانلود و سپس اجرای آن دارد. برخلاف اینکه مرورگرها امکان دانلود چند فایل را به صورت همزمان از سرور دارند، هنگامی که به اسکریپت‌ها می‌رسند، تنها یک فایل را دانلود می‌کنند. یعنی اجرای برنامه و دانلودهای مرتبط با صفحه شما متوقف شده و پس از دانلود و اجرای اسکریپت اجرای آنها ادامه پیدا می‌کند. این مسئله وقتی نمود بیشتری پیدا می‌کند که شما فایل هغای اسکریپت با حجم و تعداد بالا در برنامه خود استفاده می‌کنید.
برای فرار از این مشکل می‌توانید تگهای مربوط به اسکریپت را در آخر صفحات خود بگذارید. فقط دقت کنید اگر نیاز است که قبل از نمایش صفحه تغییری ذر DOM ایجاد کنید، باید حتما اسکریپت‌های مربوطه را بالای صفحه قرار دهید.
روش دیگر دانلود فایل‌های اسکریپت به وسیله AJAX است که انشاء الله در آینده مقاله ای در این رابطه خواهم نوشت.

21.CDN
CDN یا Content Delivery Network سرورهای توزیع شده ای در سطح دنیا هستند که یک نسخه از برنامه شما برای اجرا بر روی آن قرار دارد. هنگامی که کاربر می‌خواهد به سایت شما دسترسی پیدا کند به صورت خودکار به نزدیکترین سرور منتقل می‌شود تا بتواند سرعت بیشتری را تجربه کند. علاوه بر این CDN باعث بالانس شدن بار ترافیک شبکه شما شده خط حملات D.O.S و D.D.O.S را به حداقل می‌رساند.

زمانیکه شما یک سیستم CDN را فعال میکنید تاثیر آن بصورت زیر خواهد بود:
۱- شبکه توزیع محتوا یا همان CDN تمامی سرورهای شبکه جهانی اینترنت را پوشش میدهد. بنابراین زمانیکه شما این سیستم را برای سایت خود فعال میکنید اطلاعات شما بر روی تمامی این سرورها کپی و ذخیره میشود و زمانیکه یک بازدیدکننده به سایت یا وبلاگ شما وارد میشود محتوای سایت شامل تصاویر و متون را از نزدیک‌ترین سرور نزدیک به خود دریافت میکند و مستقیما به هاست یا سرور شما متصل نمیشود. این کار موجب بهبودی چشمگیر در عملکرد سایت شما خواهد شد.
۲- CDN تمام اطلاعات ثابت شما مانند تصاویر، کدهای CSS و javascript، mp3، pdf و فایلهای ویدئویی شما را پشتیبانی میکند و تنها اطلاعاتی که قابل تغییر و بروزرسانی هستند مانند متون و کدهای HTML از سرور اصلی شما فراخوان میشوند. با این کار مصرف پهنای باند هاست شما کاهش یافته و هزینه ای که سالانه برای آن میپردازید کاهش چشمگیری خواهد داشت.
۳- تفاوت سرعت و عملکرد برای خودتان یا افرادی که در نزدیکی سرور اصلی شما هستند تفاوت زیادی نخواهد داشت ولی برای کسانی که ار نقاط مختلف جهان به سایت شما وارد میشوند این افزایش سرعت ناشی از CDN کاملا محسوس خواهد بود، با توجه به اینکه سایتهای ایرانی معمولا سرور و هاست خود را از خارج و کشورهایی مانند آلمان و آمریکا تهیه میکنند و عموم بازدیدکنندگان از داخل کشور هستند استفاده از CDN میتواند بسیار موثر باشد. برای تعیین تاثیر CDN بر سرعت سایت میتوانید عملکرد خود را با ابزارهایی مانند Pingdom و GTmetrix بعد و قبل از فعال سازی CDN بررسی و مقایسه کنید. 
ابزارها، تکنیک‌ها و روش‌های متفاوتی برای راه اندازی CDN وجود دارد که نیازمند مقاله ای مجزا می‌باشد.
مطالب
نمایش خودکار آیکون لینک‌های سایت‌های خارجی با استفاده از jQuery

اگر دقت کرده باشید در کنار هر لینک خارجی (هر لینک ختم شده به خارج از سایت) در این وبلاگ، آیکون آن سایت هم به صورت خودکار نمایش داده می‌شود. از نظر من جالب بوده (خصوصا جهت مشخص کردن وجود یک لینک در میان انبوهی متن، یا برای نمایش لیستی از لینک‌ها)، نظر شما رو نمی‌دونم!
این‌کار در ادامه‌ی مطلبی است که در مورد نوشتن اسکریپت‌های گریس مانکی چندی قبل منتشر کردم. البته بهبود یافته‌ی آن است. برای ایجاد یک چنین قابلیتی در سایت فقط کافی است چند سطر اسکریپت زیر را به هدر سایت خود اضافه کنید.

<script src='http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js' type='text/javascript' />
<script type="text/javascript">
$(document).ready(function(){
$("a").each(function(){
var $a = $(this);
var href = $a.attr("href");
// see if the link is external
if (href && href.match(/^http/))
if (!href.match(document.domain)) {
var domain = href.replace(/<\S[^><]*>/g, "").split('/')[2];
var image = '<img src="http://' + domain +
'/favicon.ico" width="0" ' +
' onload="this.width=16;this.height=16;this.style.paddingLeft=\'3px\';this.style.paddingRight=\'1px\';" ' +
' style="border:0" ' +
' onerror="this.src=\'http://vahid.nasiri.googlepages.com/weblink.gif\';" />';
$(this).prepend(image);
}
});
});
</script>

توضیحاتی در مورد جزئیات برنامه نویسی آن:
با استفاده از jQuery ، زمانیکه document ما ready شد ( document.ready )، تمام لینک‌های موجود در صفحه را پیدا می‌کنیم (یک به یک). سپس مقدار href آن‌ها را می‌خوانیم (ببینید با jQuery انجام این نوع کارها چقدر ساده شده است). اکنون روی لینک دریافت شده باید پردازش صورت گیرد و نام دومین آن جدا شود (اگر ختم به خارج از سایت بود). سپس بر اساس این دومین ، یک تگ img منتهی به آیکون آن سایت طراحی و نمایش داده خواهد شد (به قبل از لینک اضافه می‌شود).
عموما هر پروژه‌ای هر چند کوچک و به ظاهر کم اهمیت، نکات خاصی را به همراه دارد.
برای مثال، در ابتدای کار width=0 در نظر گرفته نشد. مشکلی را که ایجاد کرد این بود که یک سایت ممکن است اصلا favicon.ico نداشته باشد. فایرفاکس محترم اصلا به روی مبارک هم نخواهد آورد و شما متوجه نخواهید شد که در صفحه کمبود تصویری وجود دارد. اما در IE حتما جای خالی آیکون و تصویر به نحوه واضحی گوشزد می‌شود. بنابراین در ابتدای کار قرار نیست چیزی را نمایش دهیم (width=0). سپس در رخ‌داد onload تگ img، اگر تصویر واقعا وجود داشت و بارگذاری شد، طول و عرض آن‌را 16 در 16 قرار خواهیم داد (این مورد هم لازم است. چون بعضی از سایت‌ها اندازه‌های بسیار بزرگی را برای آیکون خود در نظر می‌گیرند که اصلا مقصود ما را برآورده نخواهند کرد).
این مورد (عدم نمایش تصاویری که وجود ندارند) مشکلی را که در ادامه ایجاد خواهد کرد، عدم یکنواختی در سایت است. یک سری از لینک‌های خارجی آیکون دارند و یک سری خیر. نکته جالبی که در مورد تگ img وجود دارد رخ‌داد onerror آن است. اگر مرورگر نتواند تصویر مورد نظر را پیدا یا بارگذاری کند، این روال رخ‌داد‌ گردان فراخوانی می‌شود. همینجا از موقعیت استفاده شده و src تصویر جاری به یک آیکون مشخص و از قبل تعیین شده تنظیم می‌شود.

نظرات مطالب
نحوه صحیح تولید Url در ASP.NET MVC
یک نکته‌ی تکمیلی:
لزوم استفاده از Tag Helper‌ها در Asp.net Core جهت تولید آدرس‌های صحیح
 با یک مثال بررسی میکنیم. ابتدا نگاهی داشته باشیم به Route Template
app.UseMvc(routes =>
{
   routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
حالا با وجود این الگوی مسیریابی می‌خواهیم لینکی تولید کنیم که با کلیک بر روی آن جزئیات کاربر را مشاهده کنیم:
 ایجاد لینک بدون استفاده از تگ هلپر
<a href="Home/Details/@student.Id">View Details</a>
ایجاد لینک با استفاده از تگ هلپر
<a asp-controller="Home" asp-action="Details" asp-route-id="@student.Id">View Details </a>
وقتی به کدهای HTML تولید شده نگاه کنید می‌بینید که تغییرات چندانی رخ نداده است:
 خروجی حاصل
<a href="Home/Details/1">View Details</a>
<a href="/Home/Details/1">View Details</a>
حال اگر کمی تغییر را در route template ایجاد کنیم:
app.UseMvc(routes =>
{
   routes.MapRoute("default", "uni/{controller=Home}/{action=Index}/{id?}");
});
و به آدرس localhost:56241/Uni مراجعه کنیم خواهید دید که خروجی‌های متفاوتی تولید شده است. برای حالت اول که از Tag Helpers استفاده نشده خواهیم داشت:
<a href="Home/Details/1">View Details</a>
و هنگام کلیک روی لینک تولید شده با خطای 404 مواجه خواهیم شد. ولی در حالت دوم که از Tag Helpers استفاده شده خواهیم داشت:
 <a href="/Uni/Home/Details/1">View Details</a>
و هدایت کاربر به اکشن متد Details به درستی انجام خواهد شد. بدین معنا که در آینده اگر لازم به ایجاد تغییراتی در الگوی مسیریابی باشد، این تغییرات بصورت اتوماتیک توسط Tag Helperها لحاظ خواهند شد و دیگر نیازی نیست که ما تمامی لینک‌های موجود را اصلاح کنیم.
مطالب
آشنایی با LibMan در پروژه‌های ASP.NET Core
مدیریت پکیج‌های سمت کلاینت
پروژه‌های جدیدی که با استفاده از قالب پیش‌فرض ایجاد می‌شوند، شامل یک پوشه با نام lib، در شاخه‌ی wwwroot هستند که حاوی این فایل‌ها می‌باشند:


اینها به عنوان حداقل‌های ایجاد یک وب اپلیکیشن، برای قالب انتخاب شده در نظر گرفته شده‌اند. اما فرض کنید بعد از مدتی می‌خواهیم ورژن bootstrap استفاده شده در پروژه را ارتقاء دهیم؛ در این حالت چندین انتخاب داریم:

  • دانلود مستقیم فایل موردنیاز و جایگزین کردن آن با نسخه‌ی فعلی
  • حذف پوشه‌ی wwwroot/lib و نصب مجدد پوشه‌ها از طریق NPM یا Yarn
  • استفاده از bower و سفارشی‌سازی مسیر قرار گرفتن فایل‌ها توسط browerrc.

روش اول، به نسبت ساده‌تر است؛ اما مشکل اینجاست که همه چیز به صورت دستی انجام خواهد گرفت. یعنی برای نسخه‌های بعدی همین روال باید مجدداً انجام شود. در روش دوم نیز مشکل اینجاست که مسیر قرار گرفتن پکیج‌های پروژه، از این به بعد node_modules خواهند بود و نیاز به یک تنظیم اضافی در فایل Startup.cs و مطلع کردن ASP.NET Core برای serve کردن فایل‌های سمت کلاینت است همچنین نیاز خواهد بود که تمامی ارجاعات داخل فایل Layout.cshtmlـ نیز از lib به node_modules تغییر پیدا کنند. در نهایت روش آخر نیز به دلیل منسوخ شدن bower پیشنهاد نمی‌شود.

استفاده از LibMan 
LibMan یک قابلیت جدید است که از نسخه‌ی Visual Studio 2017 برای مدیریت پکیج‌های سمت کلاینت اضافه شده است. این ابزار به صورت cross platform تهیه شده است؛ یعنی در خارج از Visual Studio نیز قابل استفاده می‌باشد. در واقع این ابزار را می‌توانیم به صورت Globally روی سیستم خود نصب کنیم و از طریق خط فرمان همانند NPM از آن استفاده کنیم.  

نصب و استفاده از LibMan
این ابزار ابتدا توسط Mads Kristensen با عنوان Client-Side Library Installer به صورت یک افزونه برای Visual Studio 2015 توسعه داده شد که در نهایت تیم ASP.NET این ابزار را  به صورت توکار به Visual Studio 2017 اضافه کرد. در نتیجه اگر از نسخه‌ی 2017 ویژوال استودیو استفاده می‌کنید، برای استفاده از این ابزار نیاز به نصب پکیج خاصی نخواهید داشت. برای استفاده از این ابزار در سیستم‌عامل‌های به غیر از ویندوز نیز یک CLI تهیه شده است که از طریق خط فرمان قابل استفاده می‌باشد. برای نصب این ابزار کافی است ابتدا آن را به صورت سراسری نصب کنید:
dotnet tool install -g Microsoft.Web.LibraryManager.Cli

قدم بعدی اضافه کردن فایلی با عنوان libman.json درون پروژه است. برای افزودن این فایل کافی است دستور زیر را در خطر فرمان وارد کنید:
libman init

با صدور فرمان فوق فایل مربوطه درون پروژه ایجاد می‌شود که در واقع یک فایل json ساده برای مدیریت پکیج‌های سمت کلاینت است:
{
  "version": "1.0",
  "defaultProvider": "cdnjs",
  "libraries": []
}

همانطور که مشاهده می‌کنید، می‌توانیم منبع دریافت پکیج‌‌ها را نیز تعیین کنیم که در حالت پیش‌فرض بر روی cdnjs تنظیم شده‌است و در واقع یک Content Delivery Network برای تعداد بیشماری پکیج سمت کلاینت است. درون آرایه‌ی libraries نیز می‌توانیم پکیج‌های موردنیاز خود را وارد کنیم. حتی برای هر پکیج هم می‌توانیم provider را override نمائیم. فرض کنید می‌خواهیم کتابخانه‌ی bootstrap را به پروژه اضافه کنیم. در اینحالت کافی است دستور زیر را برای نصب پکیج مربوطه صادر نمائیم:
libman install bootstrap@4.3.1 --provider unpkg --destination wwwroot/lib/bootstrap

در نهایت فایل libman.json چنین ساختاری پیدا خواهد کرد:
{
  "version": "1.0",
  "defaultProvider": "cdnjs",
  "libraries": [
    {
      "provider": "unpkg",
      "library": "bootstrap@4.3.1",
      "destination": "wwwroot/lib/bootstrap"
    }
  ]
}

برای نصب مجدد پکیج هم می‌توانید از دستور libman restore استفاده کنید؛ در این حالت دقیقا مانند Nuget، پکیج‌ها از روی فایل libman.json از provider مربوطه دانلود و به پروژه اضافه خواهند شد. در ادامه لیست دستورات موجود را مشاهده می‌کنید: