نظرات مطالب
طراحی افزونه پذیر با ASP.NET MVC 4.x/5.x - قسمت سوم
از مطالبی مانند «Messaging Patterns with Postal.NET» ایده بگیرید. ایده اصلی آن ارتباط loosely coupled  قسمت‌های مختلف برنامه با هم است. شبیه به همین ایده در برنامه‌های دسکتاپ WPF که از الگوی MVVM استفاده می‌کنند، با مفهومی به نام Messenger وجود دارد. توسط Messenger دو قسمت مختلف برنامه با هم کار می‌کنند، بدون اینکه هیچ ارجاع مستقیمی از یکدیگر را داشته باشند.
نظرات مطالب
EF Code First #12
سیستم مدیریت محتوای IRIS از الگوی واحد کار استفاده کرده. از کدهاش برای انجام یک پروژه واقعی ایده بگیرید. برای برنامه‌های دسکتاپ هم دوره طراحی یک فریم ورک برای کار با WPF و EF Code First توسط الگوی MVVM از الگوی واحد کار استفاده می‌کنه.
مطالب
استفاده از SQL-CE به کمک NHibernate

خلاصه‌ای را در مورد SQL Server CE قبلا در این سایت مطالعه‌ کرده‌اید. در ادامه خلاصه‌ای کاربردی را از تنظیمات و نکات مرتبط به کار با SQL-CE به کمک NHibernate ملاحظه خواهید نمود:

1) دریافت SQL-CE 4.0


همین مقدار برای استفاده از SQL-CE 4.0 به کمک NHibernate کفایت می‌کند و حتی نیازی به نصب سرویس پک یک VS 2010 هم نیست.

2) ابزار سازی جهت ایجاد یک بانک اطلاعاتی خالی SQL-CE

using System;
using System.IO;

namespace NHibernate.Helper.DbSpecific
{
public class SqlCEDbHelper
{
const string engineTypeName = "System.Data.SqlServerCe.SqlCeEngine, System.Data.SqlServerCe";

/// <summary>
/// note: this method will delete existing db and then creates a new one.
/// </summary>
/// <param name="filename"></param>
/// <param name="password"></param>
public static void CreateEmptyDatabaseFile(string filename, string password = "")
{
if (File.Exists(filename))
File.Delete(filename);

var type = System.Type.GetType(engineTypeName);
var localConnectionString = type.GetProperty("LocalConnectionString");
var createDatabase = type.GetMethod("CreateDatabase");

var engine = Activator.CreateInstance(type);

string connectionStr = string.Format("Data Source='{0}';Password={1};Encrypt Database=True", filename, password);
if (string.IsNullOrWhiteSpace(password))
connectionStr = string.Format("Data Source='{0}'", filename);

localConnectionString.SetValue(
obj: engine,
value: connectionStr,
index: null);
createDatabase.Invoke(engine, new object[0]);
}

/// <summary>
/// use this method to compact or encrypt existing db or decrypt it to a new db with all records
/// </summary>
/// <param name="sourceConnection"></param>
/// <param name="destConnection"></param>
public static void CompactDatabase(string sourceConnection, string destConnection)
{
var type = System.Type.GetType(engineTypeName);
var engine = Activator.CreateInstance(type);

var localConnectionString = type.GetProperty("LocalConnectionString");
localConnectionString.SetValue(
obj: engine,
value: sourceConnection,
index: null);

var compactDatabase = type.GetMethod("Compact");
compactDatabase.Invoke(engine, new object[] { destConnection });
}
}
}

کلاس فوق، یک کلاس عمومی است و مرتبط به NHibernate نیست و در همه جا قابل استفاده است.
متد CreateEmptyDatabaseFile یک فایل بانک اطلاعاتی خالی با فرمت مخصوص SQL-CE را برای شما تولید خواهد کرد. به این ترتیب می‌توان بدون نیاز به ابزار خاصی، سریعا یک بانک خالی را تولید و شروع به کار کرد. در این متد اگر کلمه عبوری را وارد نکنید، بانک اطلاعاتی رمزنگاری شده نخواهد بود و اگر کلمه عبور را وارد کنید، دیتابیس اولیه به همراه کلیه اعمال انجام شده بر روی آن در طول زمان، با کمک الگوریتم AES به صورت خودکار رمزنگاری خواهند شد. کل کاری را هم که باید انجام دهید ذکر این کلمه عبور در کانکشن استرینگ است.
متد CompactDatabase، یک متد چند منظوره است. اگر بانک اطلاعاتی SQL-CE رمزنگاری نشده‌ای دارید و می‌خواهید کل آن‌را به همراه تمام اطلاعات درون آن رمزنگاری کنید، می‌توانید جهت سهولت کار از این متد استفاده نمائید. آرگومان اول آن به کانکشن استرینگ بانکی موجود و آرگومان دوم به کانکشن استرینگ بانک جدیدی که تولید خواهد شد، اشاره می‌کند.
همچنین اگر یک بانک اطلاعاتی SQL-CE رمزنگاری شده دارید و می‌خواهید آن‌را به صورت یک بانک اطلاعاتی جدید به همراه تمام رکوردهای آن رمزگشایی کنید، باز هم می‌توان از این متد استفاده کرد. البته بدیهی است که کلمه عبور را باید داشته باشید و این کلمه عبور جایی درون فایل بانک اطلاعاتی ذخیره نمی‌شود. در این حالت در کانکشن استرینگ اول باید کلمه عبور ذکر شود و کانکشن استرینگ دوم نیازی به کلمه عبور نخواهد داشت.

فرمت کلی کانکشن استرینگ SQL-CE هم به شکل زیر است:

Data Source=c:\path\db.sdf;Password=1234;Encrypt Database=True

البته این برای حالتی است که قصد داشته باشید بانک اطلاعاتی مورد استفاده را رمزنگاری کنید یا از یک بانک اطلاعاتی رمزنگاری شده استفاده نمائید. اگر بانک اطلاعاتی شما کلمه عبوری ندارد، ذکر Data Source=c:\path\db.sdf کفایت می‌کند.

این کلاس هم از این جهت مطرح شد که NHibernate می‌تواند ساختار بانک اطلاعاتی را بر اساس تعاریف نگاشت‌ها به صورت خودکار تولید و اعمال کند، «اما» بر روی یک بانک اطلاعاتی خالی SQL-CE از قبل تهیه شده (در غیراینصورت خطای The database file cannot be found. Check the path to the database را دریافت خواهید کرد).

نکته:
اگر دقت کرده باشید در این کلاس engineTypeName به صورت رشته ذکر شده است. چرا؟
علت این است که با ذکر engineTypeName به صورت رشته، می‌توان از این کلاس در یک کتابخانه عمومی هم استفاده کرد، بدون اینکه مصرف کننده نیازی داشته باشد تا ارجاع مستقیمی را به اسمبلی SQL-CE به برنامه خود اضافه کند. اگر این ارجاع وجود داشت، متدهای یاد شده کار می‌کنند، در غیراینصورت در گوشه‌ای ساکت و بدون دردسر و بدون نیاز به اسمبلی خاصی برای روز مبادا قرار خواهند گرفت.


3) ابزار مرور اطلاعات بانک اطلاعاتی SQL-CE

با استفاده از management studio خود SQL Server هم می‌شود با بانک‌های اطلاعاتی SQL-CE کار کرد، اما ... اینبار برخلاف نگارش کامل اس کیوال سرور، با یک نسخه‌ی بسیار بدوی، که حتی امکان rename فیلدها را هم ندارد مواجه خواهید شد. به همین جهت به شخصه برنامه SqlCe40Toolbox را ترجیح می‌دهم و اطمینان داشته باشید که امکانات آن برای کار با SQL-CE از امکانات ارائه شده توسط management studio مایکروسافت، بیشتر و پیشرفته‌تر است!



4) تنظیمات NHibernate جهت کار با SQL-CE

الف) پس از نصب SQL-CE ، فایل‌های آن‌را در مسیر C:\Program Files\Microsoft SQL Server Compact Edition\v4.0 می‌توان یافت. درایور ADO.NET آن هم در مسیر C:\Program Files\Microsoft SQL Server Compact Edition\v4.0\Desktop قرار دارد. بنابراین در ابتدا نیاز است تا ارجاعی را به اسمبلی System.Data.SqlServerCe.dll به برنامه خود اضافه کنید (نام پوشه desktop آن هم غلط انداز است. از این جهت که نگارش 4 آن، به راحتی در برنامه‌های ذاتا چند ریسمانی ASP.Net بدون مشکل قابل استفاده است).
نکته مهم: در این حالت NHibernate قادر به یافتن فایل درایور یاد شده نخواهد بود و پیغام خطای «Could not create the driver from NHibernate.Driver.SqlServerCeDriver» را دریافت خواهید کرد. برای رفع آن، اسمبلی System.Data.SqlServerCe.dll را در لیست ارجاعات برنامه یافته و در برگه خواص آن، خاصیت «Copy Local» را true کنید. به این معنا که NHibernate این اسمبلی را در کنار فایل اجرایی برنامه شما جستجو خواهد کرد.

ب) مطلب بعد، تنظیمات ابتدایی NHibernate‌ است جهت شناساندن SQL-CE . مابقی مسایل (نکات mapping، کوئری‌ها و غیره) هیچ تفاوتی با سایر بانک‌های اطلاعاتی نخواهد داشت و یکی است. به این معنا که اگر برنامه شما از ویژگی‌های خاص بانک‌های اطلاعاتی استفاده نکند (مثلا اگر از رویه‌های ذخیره شده اس کیوال سرور استفاده نکرده باشد)، فقط با تغییر کانکشن استرینگ و معرفی dialect و driver جدید، به سادگی می‌تواند به یک بانک اطلاعاتی دیگر سوئیچ کند؛ بدون اینکه حتی بخواهید یک سطر از کدهای اصلی برنامه خود را تغییر دهید.



تنها نکته جدید آن این متد است:

private Configuration getConfig()
{
var configure = new Configuration();
configure.SessionFactoryName("BuildIt");

configure.DataBaseIntegration(db =>
{
db.ConnectionProvider<DriverConnectionProvider>();
db.Dialect<MsSqlCe40Dialect>();
db.Driver<SqlServerCeDriver>();
db.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
db.IsolationLevel = IsolationLevel.ReadCommitted;
db.ConnectionString = ConnectionString;
db.Timeout = 10;

//for testing ...
db.LogFormattedSql = true;
db.LogSqlInConsole = true;
});

return configure;
}

که در آن نحوه تعریف MsSqlCe40Dialect و SqlServerCeDriver مشخص شده است.

نکته حاشیه‌ای!
در این مثال primary key از نوع identity تعریف شده و بدون مشکل کار کرد. همین را اگر با EF تست کنید، این خطا را دریافت می‌کنید: «Server-generated keys and server-generated values are not supported by SQL Server Compact». بله، EF نمی‌تواند با primary key از نوع identity حین کار با SQL-CE کار کند. برای رفع آن توصیه شده است که از Guid استفاده کنید!

نکته تکمیلی:
استفاده از Dialect سفارشی در NHibernate


نکته پایانی!
و در پایان باید اشاره کرد که SQL-CE یک بانک اطلاعاتی نوشته شده با دات نت نیست (با CPP نوشته شده است و نصب آن هم نیاز به ران تایم به روز VC را دارد). به این معنا که جهت سیستم‌های 64 بیتی و 32 بیتی باید نسخه مناسب آن‌را توزیع کنید. یا اینکه Target platform پروژه جاری دات نت خود را بر روی X86 قرار دهید (نه بر روی Any CPU پیش فرض) و در این حالت تنها یک نسخه X86 بانک اطلاعاتی SQL-CE و همچنین برنامه خود را برای تمام سیستم‌ها توزیع کنید.

نظرات مطالب
امن سازی برنامه‌های ASP.NET Core توسط IdentityServer 4x - قسمت ششم - کار با User Claims
این مطلوب است که اطلاعات پویا مانند آدرس یا نقش‌های یک کاربر که پویا هستند را در کلایم‌ها نگهداری کنیم؟ بهترین راه برای بروز بودن همیشگی نقش‌های یک کاربر این است که برای هر درخواست او نقش هارا از IDP دریافت کنیم؟
ضمنا بسته‎ی IdentityModel که معرفی کرده اید با آخرین نسخه نگارش آن در Core 3.1 سازگاری ندارد، آخرین چیزی که بهش رسیدم این بود که درخواست برای  tokenEndpoint ارسال میشود منتهی با خطای unsupported_grant_type مواجه میشوم با GrantType از نوع HybridAndClientCredentials هم تست کردم فرقی نداشته است.
مطالب
شروع به کار با EF Core 1.0 - قسمت 9 - بررسی رابطه‌ی One-to-One
بررسی رابطه‌ی One-to-Zero-or-One

زمانیکه نیاز است موجودیت A با هیچ و یا حداکثر یک وهله از موجودیت B در ارتباط باشد، به یک چنین رابطه‌ای One-to-Zero-or-One می‌گویند. برای اینکه یک چنین ارتباطی را تشکیل دهیم، نیاز است کلید اصلی یک جدول، در جدول مرتبط به آن، هم به عنوان کلید اصلی و هم به عنوان کلید خارجی معرفی شود؛ همانند شکل زیر که در آن CartableId، همزمان به صورت PK و FK تعریف شده‌است که به آن one-to-one association with shared primary key نیز می‌گویند:



الف) مدلسازی رابطه‌ی One-to-Zero-or-One توسط Fluent API

در اینجا دو موجودیت را ملاحظه می‌کنید که توسط دو navigation property به هم متصل شده‌اند:
    public class UserProfile
    {
        public int UserProfileId { get; set; }
        public string UserName { get; set; }

        public virtual Cartable Cartable { get; set; }
    }

    public class Cartable
    {
        public int CartableId { get; set; }

        public virtual UserProfile UserProfile { get; set; }
    }
برای اینکه بتوان CartableId را هم به عنوان PK و هم FK معرفی کرد، نیاز است از Fluent API به نحو ذیل استفاده کنیم:
    public class MyDBDataContext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"Data Source=(local);Initial Catalog=testdb2;Integrated Security = true");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Cartable>(entity =>
            {
                entity.Property(e => e.CartableId).ValueGeneratedNever();

                entity.HasOne(d => d.UserProfile)
                    .WithOne(p => p.Cartable)
                    .HasForeignKey<Cartable>(d => d.CartableId);
            });
        }

        public virtual DbSet<Cartable> Cartables { get; set; }
        public virtual DbSet<UserProfile> UserProfiles { get; set; }
    }
در اینجا رابطه‌ی یک به یک، توسط متدهای HasOne و WithOne معرفی شده‌است. به علاوه FK بودن CartableId به صورت صریح توسط متد HasForeignKey نیز مشخص گردیده‌است.
همچنین بر روی CartableId، فراخوانی متد ValueGeneratedNever را مشاهده می‌کنید. این متد را در قسمت «روش‌های مختلف تولید خودکار مقادیر خواص» مطلب «شروع به کار با EF Core 1.0 - قسمت 5 - استراتژهای تعیین کلید اصلی جداول و ایندکس‌ها» پیشتر بررسی کردیم. هدف آن این است که به بانک اطلاعاتی اعلام کند، این فیلد یک کلید اصلی از نوع خود افزایش یابنده نیست و مقدار آن توسط برنامه به صورت صریح تنظیم می‌شود (چون کلید خارجی نیز هست و به کلید اصلی جدول سمت دیگر رابطه اشاره می‌کند).

ب) مدلسازی رابطه‌ی One-to-Zero-or-One توسط Data Annotations
برای تنظیم این رابطه توسط ویژگی‌ها نیاز است DatabaseGenerated به None تنظیم شود تا کلید اصلی CartableId به صورت خودکار توسط بانک اطلاعاتی تولید نشود. همچنین این کلید اصلی نیز باید به صورت کلید خارجی نیز معرفی شود. به علاوه توسط InversePropertyها، باید هر دو سطر به هم مرتبط، ذکر شوند:
    public class Cartable
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int CartableId { get; set; }

        [ForeignKey("CartableId")]
        [InverseProperty("Cartable")]
        public virtual UserProfile UserProfile { get; set; }
    }

    public class UserProfile
    {
        public int UserProfileId { get; set; }
        public string UserName { get; set; }

        [InverseProperty("UserProfile")]
        public virtual Cartable Cartable { get; set; }
    }


بررسی رابطه‌ی One-to-One

تشکیل رابطه‌ی One-to-One که در آن برخلاف رابطه‌ی One-to-Zero-or-One، وجود هر دو سر رابطه اجباری هستند، در SQL Server میسر نیست (زیرا زمانیکه یک چنین رابطه‌ای تشکیل شود، نمی‌توان رکوردی را Insert کرد! چون زمانیکه هنوز یک سر رابطه ثبت نشده‌است، چگونه می‌توان Id آن‌را در سر دیگری به اجبار ثبت کرد؟!). SQL Server این رابطه را نیز به صورت همان One-to-Zero-or-One تشکیل می‌دهد. تنظیمات آن نیز با قبل تفاوتی ندارد. در این حالت اجباری بودن و یا نبودن یک سر رابطه همانند نکات قسمت «تعیین اجباری بودن یا نبودن ستون‌ها در EF Core» در مطلب «شروع به کار با EF Core 1.0 - قسمت 6 - تعیین نوع‌های داده و ویژگی‌های آن‌ها» است و این تنظیمات در اینجا صرفا از دیدگاه EF Core مفهوم دارند.
جهت تکمیل بحث، روش تشکیل رابطه‌ی One-to-One بدون استفاده از روش به اشتراک گذاری کلید اصلی (one-to-one association with shared primary key) به صورت زیر است:


همانطور که مشاهده می‌کنید، در اینجا هر بلاگ حداکثر یک تصویر را می‌تواند داشته باشد. علت آن نیز به ذکر MyBlogForeignKey بر می‌گردد که یک کلید خارجی نال نپذیر است.
    public class MyBlog
    {
        public int MyBlogId { get; set; }
        public string Url { get; set; }

        public MyBlogImage MyBlogImage { get; set; }
    }

    public class MyBlogImage
    {
        public int MyBlogImageId { get; set; }
        public byte[] Image { get; set; }
        public string Caption { get; set; }

        public int MyBlogForeignKey { get; set; }
        public MyBlog MyBlog { get; set; }
    }
با این تنظیمات:
modelBuilder.Entity<MyBlog>()
   .HasOne(p => p.MyBlogImage)
   .WithOne(i => i.MyBlog)
   .HasForeignKey<MyBlogImage>(b => b.MyBlogForeignKey);
در اینجا جدول MyBlogImage هنوز Id خود افزاینده‌ی خود را دارد، اما ثبت رکورد آن بدون وجود کلید خارجی MyBlog میسر نیست.
مسیرراه‌ها
ASP.NET Core
ASP.NET Core 1.0
ASP.NET Core 2.0
روش ارتقاء
ASP.NET Core Identity 

کار با Areas در ASP.NET Core
کار با کوکی‌ها در ASP.NET Core
بررسی روش آپلود فایل‌ها در ASP.NET Core
ارسال ایمیل در ASP.NET Core
نوشتن Middleware سفارشی در ASP.NET Core
نوشتن TagHelperهای سفارشی برای ASP.NET Core
بررسی تغییرات Reflection در NET Core.
استفاده‌ی گسترده از DateTimeOffset در NET Core.
بررسی روش دسترسی به HttpContext در ASP.NET Core
توزیع پروژه‌های ASP.NET Core 1.1 بدون ارائه فایل‌های View آن
تغییرات رمزنگاری اطلاعات در NET Core.
ساخت بسته‌های نیوگت مخصوص NET Core.
تهیه قالب برای ارسال ایمیل‌ها در ASP.NET Core توسط Razor Viewها
روش یافتن لیست تمام کنترلرها و اکشن متدهای یک برنامه‌ی ASP.NET Core
بررسی روش آپلود فایل‌ها از طریق یک برنامه‌ی Angular به یک برنامه‌ی ASP.NET Core
سفارشی سازی صفحه‌ی اول برنامه‌های Angular CLI توسط ASP.NET Core
تغییرات Encoding در NET Core.
تغییرات متدهای بازگشت فایل‌ها به سمت کلاینت در ASP.NET Core
پیاده سازی برنامه‌های چند مستاجری در ASP.NET Core
مقدمه‌ای بر تزریق وابستگی‌ها درASP.NET Core 
نمایش خطاهای اعتبارسنجی سمت سرور ASP.NET Core در برنامه‌های Angular
احراز هویت و اعتبارسنجی کاربران در برنامه‌های Angular - قسمت اول - معرفی و ایجاد ساختار برنامه
روش استفاده‌ی صحیح از HttpClient در برنامه‌های دات نت
اجرای سرویسهای NodeJS در ASP.NET Core
بررسی خطاهای ممکن در حین راه اندازی اولیه برنامه‌های ASP.NET Core در IIS 
تست کردن متدهای یک Controller به کمک PowerShell
کار با Visual Studio در ASP.NET Core

مطالب دوره‌ها
معرفی پروژه NotifyPropertyWeaver
پس از معرفی مباحث IL Code Weaving و همچنین ارائه راه حلی در مورد «استفاده از AOP Interceptors برای حذف کدهای تکراری INotifyPropertyChanged در WPF» راه حل مشابهی به نام NotifyPropertyWeaver ارائه شده است که همان کار AOP Interceptors را انجام می‌دهد؛ اما بدون نیاز به تشکیل پروکسی و سربار اضافی. کار نهایی را توسط ویرایش اسمبلی و افزودن کدهای IL لازم انجام می‌دهد؛ البته بدون استفاده از PostSharp. این پروژه از کتابخانه سورس باز پایه‌ای به نام Fody استفاده می‌کند که جهت IL Code weaving طراحی شده است.
اگر به Wiki آن مراجعه نمائید، لیست افزونه‌های قابل توجهی را در مورد آن خواهید یافت که PropertyChanged تنها یکی از آن‌ها است.


پیشنیازها
الف) صفحه پروژه در GitHub
ب) دریافت از طریق نوگت


روش استفاده

پس از نصب بسته نوگت پروژه PropertyChanged.Fody
 PM> Install-Package PropertyChanged.Fody
کلاسی را که باید پس از کامپایل، پیاده سازی‌های خودکار OnPropertyChanged را شامل شود، با ویژگی ImplementPropertyChanged مزین کنید.
using PropertyChanged;

namespace AOP02
{
    [ImplementPropertyChanged]
    public class Person
    {
        public string Id { set; get; }
        public string Name { set; get; }
    }
}
و سپس پروژه را کامپایل نمائید. خروجی کنسول Build در VS.NET :
------ Build started: Project: AOP02, Configuration: Debug x86 ------
  Fody (version 1.13.6.1) Executing
  Finished Fody 287ms.
  AOP02 -> D:\Prog\AOP02\bin\Debug\AOP02.exe
========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========
اکنون اگر فایل اسمبلی نهایی پروژه را در برنامه ILSpy باز کنیم، چنین پیاده سازی را می‌توان شاهد بود:
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace AOP02
{
    public class Person : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public string Id
        {
            [System.Runtime.CompilerServices.CompilerGenerated]
            get
            {
                return this.<Id>k__BackingField;
            }
            [System.Runtime.CompilerServices.CompilerGenerated]
            set
            {
              if (string.Equals(this.<Id>k__BackingField, value, System.StringComparison.Ordinal))
              {
                  return;
              }
              this.<Id>k__BackingField = value;
              this.OnPropertyChanged("Id");
            }
        }
        public string Name
        {
            [System.Runtime.CompilerServices.CompilerGenerated]
            get
            {
               return this.<Name>k__BackingField;
            }
            [System.Runtime.CompilerServices.CompilerGenerated]
            set
           {
             if (string.Equals(this.<Name>k__BackingField, value, System.StringComparison.Ordinal))
             {
                return;
             }
             this.<Name>k__BackingField = value;
             this.OnPropertyChanged("Name");
            }
        }
        public virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
            if (propertyChanged != null)
            {
                propertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}
مطالب
استفاده از bower در visual studio
اگر از آن دسته افرادی هستید که با پکیج‌های مختلف و پروژه‌های مختلف تحت کلاینت سر و کار دارید و همچنین اطلاعات چندانی نسبت به NodeJs ندارید (مثل خود من)، حتما به پروژه‌هایی در Github برخوردید که نیازمند نصب وابستگی‌ها از خط فرمان bower و یا npm هستند.
بعد از مطالعه‌ی مطلب آشنایی با bower این نیاز ایجاد شد تا در پروژه‌هایی که قرار است درون Visual Studio اجرا شوند، وابستگی‌های bower چگونه می‌توانند مدیریت شوند.
خوشبختانه Microsoft این امکان را ایجاد کرده تا شما بتوانید پروژه‌هایی را که وابستگی‌هایشان درون bower تعریف شده را نیز درون Visual Studio حل و فصل کنید. در ادامه تمامی این مراحل، قدم به قدم اضافه تشریح شده است.
قابل ذکر است که هر سه package manager معروف npm، bower و Nuget در ویژوال استدیو 2015 به صورت توکار موجود هستند. 
جزیات بیشتر در مستندات مایکروسافت


معرفی پکیج Bower

همانطور که در مقاله آشنایی با bower نیز اشاره شد، bower یک package manager برای تکنولوژی‌ها و کتابخانه‌های کلاینت است. این package manager بر روی Git اجرا می‌شود. همانطور که می‌دانید تمامی پکیج‌ها نیز از Git دریافت می‌شود.
اما حال اینکه چگونه می‌توان از این package manager در سمت Visual studio بدون نصب NodeJs و Git استفاده کرد، با پکیج توسعه داده شده Bower مایکروسافت رفع شده‌است.
جزئیات این پکیج را میتوانید در NuGet  مطالعه کنید.


شروع کار با Bower

برای آغاز، یک پروژه‌ی web Application ایجاد می‌کنیم. من Empty را انتخاب و ریسورس‌های MVC را هم اضافه کردم.
حال در بخش Package Manager Console دستور زیر را اجرا کنید:
Install-Package Bower
پس از نصب وابستگی‌ها و خود bower خروجی package manager console به صورت زیر خواهد بود:

مشاهده می‌کنید که فولدر .bin به پروژه‌ی شما اضافه شده است.

 حال درون صفحه‌ی cmd (توجه کنید cmd، نه package manager console) به آدرس پروژه (نه solution) با دستور زیر منتقل شوید:

cd <Project Location>

که به جای project location آدرس فایل پروژه را قرار می‌دهیم. شکل زیر نمایانگر این مسیر است:

با اجرای دستور زیر bower.json را به پروژه اضافه می‌کنیم:

bower init

مشاهده می‌کنید که پس از دستور bower init مواردی که قرار است درون bower قرار گیرد، مقدار دهی می‌شوند. من مقادیر را به صورت زیر (حالت‌های پیش فرض) تکمیل کردم:

حال باید تا اینجای کار یک فایل bower.json برای شما در روت پروژه ساخته شده باشد. حال بیایید اولین اسکریپت رفرنس را به پروژه اضافه نماییم. من قصد دارم تا با دستور زیر JQuery را به پروژه اضافه کنم:

bower install jquery

پکیج JQuery به صورت زیر دانلود می‌شود و در پوشه‌ی bower_component در روت پروژه قرار می‌گیرد.

به همین صورت شما می‌توانید تمامی نیازمندی‌های پروژه را از Git با استفاده از bower package manager دریافت کنید.