مطالب
چگونه پروژه‌های Angular ی سبکی داشته باشیم - قسمت اول
یکی از عیب‌هایی که برنامه نویسان front-end و گاها بعضی از مدیران از Angular می‌گیرند، حجم زیاد صفحاتی است که با Angular کار می‌شود. در نتیجه‌ی جستجوی مشکل ذکر شده، با تعدادی پاسخ مشابه ^ و ^ روبرو می‌شویم که هیچ کدام روش صحیحی را برای رفع مشکل ذکر شده عنوان نکرده‌اند. در ادامه پروژه‌ی Angular ای را شروع می‌کنیم و حجم صفحات خروجی را مورد بررسی قرار می‌دهیم. سپس نحوه‌ی بهینه سازی و کم کردن حجم صفحات خروجی را بررسی می‌کنیم. 

برای شروع، CMD را در مسیر دلخواهی برای ساخت پروژه باز کرده  و ابتدا Angular CLI را توسط دستور زیر به آخرین نسخه‌ی موجود به‌روز رسانی می‌کنیم:
npm install -g @angular/cli
و سپس پروژه‌ی انگیولاری را  با دستور زیر می‌سازیم:
ng new HowToKeepAngularSizeSmall
پاسخ سوال ? Would you like to add Angular routing? (y/N)  را  y و scss را به عنوان فرمت stylesheet انتخاب می‌کنیم.
در ادامه پروژه را با استفاده از دستور زیر
ng serve --open --prod
اجرا می‌کنیم . سپس با استفاده از ابزار DevTools console از تب network، حجم فایل‌های لود شده را بررسی می‌کنیم:

حجم خروجی پروژه بعد از ساخت 222KB است.
حال برای آنکه پروژه‌ی جاری را به پروژه‌های واقعی نزدیک‌تر کنیم، بسته‌های npm زیر را به فایل package.json اضافه کرده و با دستور npm i بسته‌ها را نصب می‌کنیم.
"@agm/core": "^1.0.0-beta.5",
"@angular/flex-layout": "^7.0.0-beta.23",
"@angular/material": "^7.3.3",
"@angular/platform-browser": "~7.2.0",
"@asymmetrik/ngx-leaflet": "^5.0.1",
"@ngx-loading-bar/router": "1.3.1",
"@ngx-translate/core": "^11.0.1",
"@ngx-translate/http-loader": "^4.0.0",
"@progress/kendo-angular-buttons": "^4.3.3",
"@progress/kendo-angular-dateinputs": "^3.6.0",
"@progress/kendo-angular-dialog": "^3.10.1",
"@progress/kendo-angular-dropdowns": "^3.5.1",
"@progress/kendo-angular-excel-export": "^2.3.0",
"@progress/kendo-angular-grid": "^3.13.0",
"@progress/kendo-angular-inputs": "^4.2.0",
"@progress/kendo-angular-intl": "^1.7.0",
"@progress/kendo-angular-l10n": "^1.3.0",
"@progress/kendo-angular-layout": "^3.2.0",
"@progress/kendo-data-query": "^1.5.0",
"@progress/kendo-drawing": "^1.5.8",
"@progress/kendo-theme-default": "^3.3.1",
"@swimlane/ngx-datatable": "^14.0.0",
"angular-calendar": "0.23.7",
"angular-tree-component": "7.0.1",
"bootstrap": "^3.4.0",
"chart.js": "2.7.2",
"d3": "4.13.0",
"dragula": "3.7.2",
"hammerjs": "2.0.8",
"intl": "1.2.5",
"leaflet": "1.3.1",
"moment": "2.21.0",
"ng2-charts": "1.6.0",
"ng2-dragula": "1.5.0",
"ng2-file-upload": "1.3.0",
"ng2-validation": "4.2.0",
"ngx-perfect-scrollbar": "5.3.5",
"ngx-quill": "2.2.0",
"screenfull": "3.3.2",
"font-awesome": "^4.7.0",
"jalali-moment": "^3.3.1",
"jquery": "^3.3.1",
"ng-snotify": "^4.3.1",
"normalize.css": "^8.0.1",
و خطوط زیر را به styles.scss اضافه می‌کنیم:
@import "~bootstrap/dist/css/bootstrap.css";
@import "~@progress/kendo-theme-default/scss/all";
@import '@angular/material/prebuilt-themes/pink-bluegrey.css';
@import '~perfect-scrollbar/css/perfect-scrollbar.css';
@import "~ng-snotify/styles/material";
و قسمت scripts زیر را به فایل angular.json اضافه می‌کنیم:
"scripts": [
              "node_modules/jquery/dist/jquery.js",
              "node_modules/bootstrap/dist/js/bootstrap.min.js",
              "node_modules/hammerjs/hammer.min.js"
            ],
و فایل app.module.ts را نیز به صورت زیر تغییر می‌دهیم:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';


// Import Material
import {
  MatFormFieldModule, MatInputModule,
  MatButtonModule, MatButtonToggleModule,
  MatDialogModule, MatIconModule,
  MatSelectModule, MatToolbarModule,
  MatDatepickerModule,
  DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE, MatTableModule, MatCheckboxModule, MatRadioModule, MatCardModule, fadeInContent,
  MatListModule, MatProgressBarModule, MatTabsModule,
  MatSidenavModule,
  MatSlideToggleModule,
  MatMenuModule
} from '@angular/material';



// Import kendo angular ui
import { ButtonsModule } from '@progress/kendo-angular-buttons';
import { GridModule, ExcelModule } from '@progress/kendo-angular-grid';
import { DropDownsModule } from '@progress/kendo-angular-dropdowns';
import { InputsModule } from '@progress/kendo-angular-inputs';
import { DateInputsModule } from '@progress/kendo-angular-dateinputs';
import { DialogsModule } from '@progress/kendo-angular-dialog';
import { RTL } from '@progress/kendo-angular-l10n';
import { LayoutModule } from '@progress/kendo-angular-layout';
import { WindowService, WindowRef, WindowCloseResult, DialogService, DialogRef, DialogCloseResult } from '@progress/kendo-angular-dialog';

import { SnotifyModule, SnotifyService, SnotifyPosition, SnotifyToastConfig, ToastDefaults } from 'ng-snotify';


import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,

    // material 
    MatSidenavModule,
    MatSlideToggleModule,
    MatInputModule,
    MatFormFieldModule,
    MatButtonModule, MatButtonToggleModule,
    MatDialogModule, MatIconModule,
    MatSelectModule, MatToolbarModule,
    MatDatepickerModule,
    MatCheckboxModule,
    MatRadioModule,
    MatCardModule,
    MatMenuModule,
    MatListModule,
    MatProgressBarModule,
    MatTabsModule,


    // kendo-angular
    ButtonsModule,
    GridModule,
    ExcelModule,
    DropDownsModule,
    InputsModule,
    DateInputsModule,
    DialogsModule,
    LayoutModule,

    SnotifyModule,


  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

بدون اینکه component جدیدی را به پروژه‌ی جاری اضافه کنیم، پروژه را با دستور ng serve --open --prod  اجرا کرده و خروجی را بررسی می‌کنیم:

همانطور که می‌بینید بدون افزودن کامپوننت جدیدی، حجم خروجی از 222KB به 582KB رسیده‌است. معمولا در هر پروژه نیاز به تعدادی دایرکتیو و سرویس پایه نیز می‌باشد که کم کم به حجم خروجی صفحات می‌افزاید. در نظر بگیرید که هنوز هیچ قالب خاصی برای صفحه مورد نظرمان استفاده نشده و به حجم 582KB رسیده‌ایم. برای نمونه می‌توانیم سری به سایت madewithangular.com بزنیم و حجم خروجی تعدادی از سایت‌های نوشته شده‌ی با انگیولار را بررسی کنیم. سایت‌های زیر خروجی بالای 1.5MB دارند. همچنین سایتی را که خودم تقریبا یک سال پیش شروع کرده بودم، حجم خروجی آن  2.7MB است:

دلیل بالا رفتن حجم خروجی، اضافه شدن فایل‌های JavaScript و style-sheet به bundle اصلی پروژه است. برای مثال حجم فایل main.js را در نمونه‌های ذکر شده بررسی کنید. 

در قسمت‌های بعدی، به نحوه‌ی کار صحیح با انگیولار می‌پردازیم و حجم صفحات را بررسی می‌کنیم. 

مطالب
بررسی جزئیات برنامه نویسی افزونه تاریخ فارسی برای outlook 2007 - قسمت اول

قبل از شروع بحث، سورس کامل پروژه را از اینجا دریافت کنید (یک پروژه VSTO از نوع outlook add-in در VS.Net 2008 SP1).

توضیحات مربوطه را به دو قسمت تقسیم کرده‌ام. قسمت اول یافتن تاریخ‌های sent و فارسی کردن آنها و قسمت بعدی نحوه اضافه کردن یک ستون و مقدار دهی آن (در روزی دیگر).

متن ایمیل‌های دریافتی در آوت‌لوک‌های جدید عموما به دو فرمت HTML و یا RichText دریافت می‌شوند. حالت‌های دیگری هم مانند plain و unspecified هم موجود هستند که حتی اگر ایمیلی را به صورت plain ارسال نمائید، با فرمت RichText نمایش داده خواهد شد (بنابراین بر اساس آزمایشات من بررسی این دو فرمت کفایت می‌کند).

برای اینکه قسمت‌های sent را پیدا کنیم در ابتدا باید سورس صفحه را بررسی نمائیم (کلیک راست و view source).
در حالت فرمت HTML داریم:

<p class=MsoNormal><b><span style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'>From:</span></b><span
style='font-size:10.0pt;font-family:"Tahoma","sans-serif"'> Nasiri, Vahid <br>
<b>Sent:</b> <span lang=AR-SA dir=RTL>our date goes here</span><br>
<b>To:</b> xyz<br>
<b>Subject:</b> our subject<o:p></o:p></span></p>


و در حالت ایمیل‌های RichText خواهیم داشت:

From: tst@tst.net<br>
Sent:<span lang=AR-SA dir=RTL>our date goes here</span><br>
To: Nasiri, Vahid<br>
Subject: <span lang=AR-SA dir=RTL>xyz</span><br>

خوب، برای پیدا کردن عبارت تاریخ قسمت sent چه باید کرد؟ (our date goes here در اینجا)
استفاده از روش‌های متداول کار با رشته‌ها در اینجا به علت انبوهی از تگ‌های HTML اصلا مقرون به صرفه نیست و کند خواهد بود. خوشبختانه با وجود کتابخانه regular expressions در دات نت، پیدا کردن عباراتی که از یک الگوی خاص پیروی می‌کنند به سادگی و با سرعت بسیار بالایی قابل انجام است.
پیشنهاد من برای دو فرمت بالا به صورت زیر بوده: (شاید شما الگوی دیگری را یافتید، زیبایی اوپن سورس :))

private const string REGEXHTMLPATTERN = @"(?s)>\s(.+?)<br>";
private const string REGEXPLAINTEXTPATTERN = "(?s)Sent:(.+?)<br>";

برای مثال در حالت دوم هر چیزی که بین sent و br قرار می‌گیرد در کل متن بررسی خواهد شد (با استفاده از MatchCollection فضای نام System.Text.RegularExpressions). در اینجا اگر Convert.ToDateTime آن عبارت موفق بود یعنی تاریخ قابل تبدیل است (البته قبل از تبدیل تمام تگ‌های HTML احتمالی هم تمیز خواهند شد) و ما آنرا با استفاده از تابع DateTimeToFarsiStr در کلاس cDate به نمونه شمسی تبدیل کرده (لطفا به سورس برنامه مراجعه کنید) و نهایتا آنرا در متن جایگزین می‌کنیم.
سرعت استفاده از RegularExpressions فوق العاده بالا است و برای نمونه در ایمیلی با بیش از 20 ریپلای در کسری از ثانیه کل این عملیات انجام خواهد شد.

تا اینجا بررسی کلی الگوریتم مورد استفاده قسمت اول به پایان می‌رسد.

بیشترین وقتی که در این پروژه صرف شد نحوه پیدا کردن شیء MailItem جاری باز شده با استفاده از رخدادهای آوت‌لوک بود (مدت مدیدی را برای این مورد وقت گذاشتم! چون عملا در هیچ کتابی به این مباحث پرداخته نمی‌شود و باید کل نت را زیر و رو کرد). دو مورد را باید بررسی کرد. الف) inspector ها (صفحه‌ای که جهت ایجاد یک ایمیل جدید یا ریپلای به ایمیل جاری باز می‌شود، inspector نام دارد) ب) ActiveExplorer ها (صفحه‌ای که لیست ایمیل‌ها را نمایش می‌دهد و این صفحه می‌تواند در فولدرهای مختلفی که شما ایجاد کرده‌اید نیز نمایش داده شود بنابراین بررسی inbox به تنهایی کافی نیست)
نحوه ایجاد اشیاء مربوطه و تحت نظر قرار دادن آنها را در روال ThisAddIn_Startup فایل ThisAddIn.cs می‌توانید مشاهده نمائید. نکته مهمی که اینجا وجود دارد، تعریف این اشیاء در سطح کلاس است. در غیراینصورت با اولین خانه تکانی garbage collector ، اشیاء شما (بدلیل نبود ارجاعی فعال به آنها) معدوم خواهند شد(!) و دیگر روال‌های رخداد گردان تعریف شده کار نخواهند.

مطالب
توسعه برنامه‌های Cross Platform با Xamarin Forms & Bit Framework - قسمت شانزدهم
در این قسمت می‌خواهیم به بحث Style دهی و Font‌ها در Xamarin Forms بپردازیم. در XF به دو روش می‌توان Style اعمال کرد؛ یکی با CSS و دیگری با Xaml. از هر روشی که استفاده کنیم، Styleها درون Resource‌ها قرار می‌گیرند. Resource، یک Dictionary است که درون آن هر چیزی می‌توان قرار داد؛ یک string یا Style یا عدد و ...
فایل App.xaml و همچنین تک تک صفحات، دارای Resources هستند که اگر چیزی درون App.xaml Resources قرار بگیرد، در کل برنامه می‌توان از آن استفاده کرد. برای مثال در صورت قرار دادن یک Style در App Resources، آن Style بر روی کل برنامه قابلیت اعمال پیدا می‌کند. همچنین اگر چیزی درون Resources یک صفحه قرار بگیرد، فقط برای کنترل‌های درون آن صفحه در دسترس است و ...
در روش Style دهی به سبک Xaml، می‌توانید از تمامی امکاناتی که تا اینجا یاد گرفته‌اید استفاده کنید؛ برای مثال Triggers و Binding و ... . هر Style یک Target Type دارد، اگر Style ای Target Type اش Label باشد، برای تمامی Property‌های Label می‌تواند تعیین تکلیف کند:
<Style TargetType="Label">
    <Setter Property="FontFamily" Value="Some font..." />
</Style>
هر Label مقدار FontFamily یا سایر Property‌های خودش را به شکل زیر حساب می‌کند:
1- اگر بر روی یک Label، صراحتا FontFamily مقدار دهی شود، آن مقدار معتبر در نظر گرفته می‌شود.
2- اگر در Resource‌های آن صفحه ای که Label درون آن قرار دارد، Style برای Label تعریف شود و در آن Style به FontFamily مقداری تخصیص داده شده باشد، آن مقدار ملاک قرار می‌گیرد.
3- اگر نه بر روی خود Label و نه در Resourceهای صفحه ای که Label در آن قرار دارد، مقدار FontFamily مشخص نشود، آنگاه بررسی می‌شود که آیا Style ای در App.xaml برای Label وجود دارد که به FontFamily مقداری داده باشد یا نه، که اگر وجود داشته باشد، آن عدد ملاک است.
4- در نهایت اگر هیچ جایی از FontFamily صحبتی نشده باشد، مقدار پیش فرض ارائه شده توسط تیم Xamarin Forms ملاک قرار می‌گیرد.

البته این آموزش همه جزئیات را شامل نمی‌شود تا از پیچیده شدن بحث جلوگیری کند و با همین مقدار از یادگیری نیز می‌توانید به خوبی کار خود را پیش ببرید.
حال اگر بخواهیم تمامی صفحات برنامه، Background آبی داشته باشند، می‌توان در App.xaml برای ContentPageها یک Style نوشت که BackgroundColor را آبی تعیین کرده باشد:
<Style TargetType="ContentPage" ApplyToDerivedTypes="True" >
    <Setter Property="BackgroundColor" Value="Blue" />
</Style>  
اگر دقت کنید، ApplyToDerivedTypes نیز مقدار True گرفته است. علت این است که صفحه لاگین که برای مثال قصد آبی کردن آن را به همراه تمامی صفحات دیگر داریم، از جنس ContentType نیست، بلکه از آن ارث بری کرده‌است. همچنین PopupPage‌ها نیز از ContentPage ارث بری کرده‌اند. با ApplyToDerivedTypes ما این Style را نه تنها بر روی ContentPage که بر روی کلاس‌هایی که از آن ارث بری کرده‌اند نیز اعمال می‌کنیم. صد البته که در پروژه ما خود ContentPage اصلا جایی مستقیما استفاده نشده‌است و تمامی صفحات ما، در واقع ارث بری ای از ContentPage محسوب می‌شوند. البته در مثال Label، ارث بری ای در کار نیست و همیشه مستقیما از Label استفاده می‌کنیم، نه اینکه از آن ارث بری کنیم.
حال ممکن است بخواهیم Style ای تعریف کنیم به نام Danger Button که نه کل دکمه‌های برنامه که چندتایی در صفحات مختلف می‌خواهند از آن استفاده کنند. اگر برای Button یک Style نوشته شود، تمامی Buttonها آن را خودکار می‌گیرند، پس راه حل چیست؟ راه حل این است که به Style ای که تعریف کرده‌ایم، یک x:Key دهیم. اگر Style ای Key داشته باشد، باید موقع استفاده در هر Button، نام آن Key ذکر شود.
<Style x:Key="DangerButton" TargetType="Button">
    <Setter Property="BackgroundColor" Value="Red" />
    <Setter Property="FontAttributes" Value="Bold" />
</Style>  
سپس موقع استفاده داریم:
<Button Style="{StaticResource DangerButton}" />
وقتی از StaticResource استفاده می‌کنیم، در Resourceهای صفحه‌ای که Button در آن قرار دارد و یا در App.xaml دنبال یک Style با x:Key برابر با DangerButton می‌گردد.
برای استفاده از Binding/Trigger در Styleها مثالی را داریم که متن تمامی Entryها به صورت Bold می‌شود، وقتی که IsFocused آنها True است!
<Style TargetType="Entry">
    <Style.Triggers>
        <Trigger TargetType="Entry" Property="IsFocused" Value="True">
            <Setter Property="FontAttributes" Value="Bold" />
        </Trigger>
    </Style.Triggers>
</Style>
برای Style دهی به شکل CSS نیز مثال زیر را داریم که متن تمامی buttonها را bold می‌کند:
<StyleSheet>
<![CDATA[
    button {
        font-style: bold;
    }
]]>
</StyleSheet>
می‌توان cssها را در فایل‌هایی با پسوند css نیز نوشت و به پروژه اضافه کرد. همچنین هر کنترل، دو ویژگی StyleId و class را دارد که بتوان به آن class / id داد تا در css به صورت . یا # استایل داد. مواردی چون stackpanel label به معنی label هایی که درون stack panel هستند و ... نیز پشتیبانی می‌شوند.
در رابطه با فونت نیز شما باید ابتدا فونت یا فونت‌های مربوطه را به هر سه پروژه Android/iOS/Windows اضافه کنید و سپس در App.xaml برای Font Family کنترل‌های مختلفی چون Label و ... از آن فونت استفاده کنید.
برای این مهم، ابتدا فایل‌های فونتی را انتخاب کرده (مثلا Open Sans) را به پروژه Windows/Android/iOS اضافه کنید: (سه فایل ما OpenSansItalic.ttf/OpenSansBold.ttf /OpenSansRegular.ttf هستند) 
در ویندوز آنها را در فولدر Assets/Fonts و در Android در فولدر Assets/Fonts و در iOS در فولدر Resources/Fonts کپی کنید. در iOS علاوه بر این کار، این‌ها را نیز به Key Value‌های فایل info.plist نیز اضافه کنید:
<key>UIAppFonts</key>
<array>
    <string>Fonts/OpenSansItalic.ttf</string>
    <string>Fonts/OpenSansRegular.ttf</string>
    <string>Fonts/OpenSansBold.ttf</string>
</array>  

سپس کدهای زیر را استفاده کنید:

<bitView:OnPlatform
    x:Key="OpenSansRegular"
    x:TypeArguments="x:String"
    Value="{OnPlatform Android='Fonts/OpenSansRegular.ttf#Open Sans',
                        iOS='OpenSans-Regular',
                        UWP='Assets/Fonts/OpenSansRegular.ttf#Open Sans'}" />

<!--  Italic مشابه کد بالا برای -->
<!--  Bold مشابه کد بالا برای -->

چون آدرس و نحوه نام دهی FontFamily در سه پلتفرم متفاوت است، با استفاده از OnPlatform، یک String می‌سازیم با x:Key برابر با OpenSansRegular که در هر پلتفرم مقدار خود را دارد. سپس از این نام برای مقدار دهی FontFamily در کنترل‌های Label/Entry/Button و ... در حالت‌های None/Italic/Bold استفاده می‌کنیم. برای مثال:

<Style TargetType="Label">
    <Style.Triggers>
        <Trigger TargetType="Label" Property="FontAttributes" Value="Bold">
            <Setter Property="FontFamily" Value="{StaticResource OpenSansBold}" />
        </Trigger>
        <Trigger TargetType="Label" Property="FontAttributes" Value="Italic">
            <Setter Property="FontFamily" Value="{StaticResource OpenSansItalic}" />
        </Trigger>
        <Trigger TargetType="Label" Property="FontAttributes" Value="None">
            <Setter Property="FontFamily" Value="{StaticResource OpenSansRegular}" />
        </Trigger>
    </Style.Triggers>
</Style>

این کد می‌گوید زمانیکه FontAttributes یک Label برابر با Bold است، از OpenSansBold برای FontFamily اش استفاده شود و همینطور برای Italic و None (یا همان Regular)

در قسمتی‌که داشتیم برای اندروید و ویندوز، مسیر فایل فونت را مشخص می‌کردیم، از مقدار OpenSansRegular.ttf#Open Sans استفاده کردیم که OpenSansRegular.ttf نام فیزیکی فایل و Open Sans نام خود فایل است که با دو بار کلیک کردن روی فایل آن در ویندوز از طریق برنامه Font ویندوز قابل مشاهده است:

همچنین برای اینکه این سه فایل، سه بار برای سه پلتفرم در سورس کنترلر کپی نشوند، از روش Add as link در Visual Studio بهره گرفته‌ایم و فایل فیزیکی فونت‌ها فقط در پروژه UWP وجود دارند. البته این به معنای این نیست که در Apk نهایی Android و ipa نهایی iOS این فایلها وجود نخواهند داشت؛ بلکه به خاطر ماهیت Add as link، انگار که این فایل‌ها در هر سه پروژه هستند و پشت صحنه کپی می‌شوند.

اشتراک‌ها
استفاده از MongoDB .NET Driver با NET Core Web API.

Source could be also accessed from GitHub -> https://github.com/fpetru/WebApiMongoDB.

Problem / solution format brings an easier understanding on how to build things, giving an immediate feedback. Starting from this idea, the blog post will present step by step how to build

a web application to store your ideas in an easy way, adding text notes, either from desktop or mobile, with few characteristics: run fast, save on the fly whatever you write, and be reasonably reliable and secure.

This blog post will implement just the backend, WebApi and the database access, in the most simple way. Next blog post will cover the front end, using Angular. Then, there will be an additional article on how to increase the performance and the security. 

استفاده از MongoDB .NET Driver با NET Core Web API.
نظرات اشتراک‌ها
رایگان شدن بیش از ۷۰۰۰ دوره سایت Pluralsight
من ثبت نام کردم و تعدادی آموزش هم از طریق اپلیکیشن دانلود کردم اما وقتی میخوام تماشا کنم خطای زیر داده میشه
Your current subscription does not include this course
اشتراک‌ها
معرفی Mapster

 Writing mapping method is machine job. Do not waste your time, let Mapster do it.

Benchmark 

معرفی Mapster
نظرات مطالب
یکپارچه سازی Angular CLI و ASP.NET Core در VS 2017
- در قسمت «ایجاد ساختار اولیه‌ی برنامه‌ی Angular CLI در داخل پروژه‌ی جاری» در متن جاری توضیح داده شده‌است.
+ فقط پروژه‌های قدیمی و بدون پشتیبانی MVC 5 هستند که فایل‌های جدید اضافه نشده‌ی به فایل csproj را به solution در IDE اضافه نمی‌کنند. چنین مشکلی با پروژه‌های جدید ASP.NET Core وجود ندارد و دقیقا مانند VSCode رفتار می‌کنند. یعنی هر فایلی که توسط Angular CLI اضافه شد، به صورت خودکار در IDE نمایش داده می‌شود (بدون نیاز به ذکر ارجاعی به آن‌ها در فایل csproj). بنابراین یا از VSCode استفاده کنید، یا هربار در پروژه‌های با ساختار قدیمی MVC 5 باید این فایل‌های جدید تولید شده را به فایل csproj به صورت دستی اضافه کنید (اگر می‌خواهید آن‌ها را داخل VS ویرایش کنید).

- این مطلب را هم مدنظر داشته باشید:
«چه زمانی باید به فکر ارتقاء به ASP.NET Core بود؟» 

If you’re starting a new project and plan on using MVC and/or Web API, then it’s almost certain you should use ASP.NET Core.   

مطالب
مقایسه و بررسی پوشه‌های Bin و Obj در برنامه‌های NET.
زمانیکه شما یک برنامه‌ی دات نتی نوشته شده به زبان سی شارپ را کامپایل می‌کنید، دو پوشه‌ی bin و obj را مشاهده می‌کنید. در این مطلب، اهمیت و تفاوت این دو پوشه را بررسی می‌کنیم. این پوشه‌ها حاوی کد‌های کامپایل شده‌ی IL می‌باشند. 

فرآیند کامپایل به دو مرحله‌ی کامپایل سورس کد و همچنین ایجاد پیوند (linking) بین فایل‌های کامپایل شده تقسیم می‌شود.
به دیاگرام زیر دقت نمائید:
• در مرحله‌ی کامپایل، هر یک از سورس فایل‌ها، بصورت مجزا کامپایل می‌شود و به ازای هر سورس فایل، یک فایل مجزای کامپایل شده تولید می‌شود. بدین معنا که اگر دو فایل داشته باشیم، دو کد مستقل کامپایل شده نیز تولید می‌شوند.
• در مرحله‌ی متصل کردن (linking)، همه‌ی فایل‌های کامپایل شده به یک اسمبلی واحد کامپایل می‌شوند که این اسمبلی می‌تواند از نوع DLL و یا EXE باشد.

اگر هر دو پوشه را مقایسه کنید، تعداد فایل‌های موجود در obj، بیشتر از bin است؛ به این خاطر که در این پوشه برای هر فایل، یک فایل کامپایل شده‌ی مجزا تولید می‌شود.

اما سؤالی که در ذهن ایجاد می‌شود این است که چرا این فرآیند در دو مرحله انجام می‌شود و چرا فرآیند کامپایل در یک مرحله انجام نمی‌شود. با انجام 2 مرحله‌ای فرآیند کامپایل، می‌توان از قابلیت کامپایل شرطی (Conditional Compiling) بهره‌مند شد.
زمانیکه یک پروژه‌ی بزرگ را کامپایل می‌کنیم، انتظار داریم تنها فایل‌هایی را که تغییر کرده‌اند، کامپایل شوند و در پوشه‌ی obj، ما هر فایل کامپایل شده را بصورت مجزا داریم. در نتیجه می‌توانیم تشخیص دهیم  که چه فایل‌هایی تغییر کرده‌اند و تنها آنها را کامپایل می‌کنیم که این کار باعث افزایش سرعت فرآیند کامپایل می‌شود.

بطور خلاصه در پوشه‌ی obj، ما به ازای هر سورس فایل، یک فایل کامپایل شده داریم؛ اما در پوشه‌ی bin تنها یک فایل یکپارچه شده را خواهیم داشت.