اشتراک‌ها
branca جایگزینی برای jwt

Branca is a catchy name for IETF XChaCha20-Poly1305 AEAD message with an additional version number and timestamp. It is well suited to be used as an authenticated and encrypted API token. Branca specification does not specify the payload format. 

branca جایگزینی برای  jwt
مطالب
Angular Material 6x - قسمت اول - افزودن آن به برنامه
کتابخانه‌ی Angular Material تعدادی کامپوننت زیبای با قابلیت استفاده‌ی مجدد، به خوبی آزمایش شده و با قابلیت دسترسی بالا را بر اساس الگوهای Material Design ارائه می‌دهد. برای توسعه دهندگان Angular، کتابخانه‌ی Angular Material پیاده سازی مرجع رهنمودهای طراحی متریال گوگل است که توسط تیم اصلی Angular پیاده سازی و توسعه داده می‌شود. در این سری، مفاهیم طراحی نگارش 6x این کتابخانه را به همراه نحوه‌ی برپایی و تنظیم آن و همچنین کار با کامپوننت‌های پیشرفته‌ی آن، بررسی خواهیم کرد.


منابع و مآخذ مرتبط با کتابخانه‌ی Angular Material

در اینجا مآخذ اصلی کار با این کتابخانه را ملاحظه می‌کنید که شامل اصول طراحی متریال و مخازن اصلی توسعه‌ی آن می‌باشند:
Material Design Specification
- https://material.io/design
Angular Material
- https://material.angular.io
- https://github.com/angular/material2


مفاهیم پایه‌ی طراحی متریال

چرا «زیبایی» رابط کاربری مهم است؟
در ابتدای معرفی کتابخانه‌ی Angular Material عنوان شد که این مجموعه به همراه تعدادی کامپوننت «زیبا» است. بنابراین این سؤال مطرح می‌شود که چرا و یا تا چه اندازه «زیبایی» رابط کاربری اهمیت دارد؟ مهم‌ترین دلیل آن بهبود تجربه‌ی کاربری است. بر اساس تحقیقاتی که بر روی کاربران بسیاری صورت گرفته‌است، مشخص شده‌است کاربران، با رابط‌های کاربری زیبا نتایج بهتری را از لحاظ کاهش زمان اتمام کار و تعداد خطاهای مرتبط دریافت می‌کنند.

اما ... طراحی برنامه‌های زیبا مشکل است. به همین جهت استفاده از کتابخانه‌های غنی مانند طراحی متریال که این امر را سهولت می‌بخشند، ضروری است. طراحی متریال یک زبان کامل طراحی برنامه‌های زیبا است. توسط گوگل طراحی شده‌است و دو هدف اصلی را دنبال می‌کند:
- وفاداری به اصول کلاسیک طراحی رابط کاربری
- ارائه‌ی تجربه‌ی کاربری یک‌دست و هماهنگ، در بین وسایل و اندازه‌های صفحات نمایشی مختلف

اصول پایه‌ی طراحی متریال نیز شامل موارد زیر است:
- «متریال» یک متافور است و بر اساس مطالعه‌ی نحوه‌ی کار با کاغذ، مرکب و ارتباط بین اشیاء در دنیای واقعی پدید آمد‌ه‌است.
- اشیاء در دنیای واقعی دارای ارتباط‌های ابعادی و حجمی هستند. برای مثال دو برگه‌ی کاغذ یک فضا را اشغال نمی‌کنند. طراحی متریال برای نمایش این ارتباط سه بعدی بین اشیاء، از نور و سایه استفاده می‌کند.
- در دنیای واقعی، اشیاء از درون یکدیگر رد نمی‌شوند. این مورد در طراحی متریال نیز صادق است.
- طراحی متریال به همراه جعبه‌ی رنگ مخصوص و بکارگیری فضاهای خالی و عناوین درشت بسیار مشخص، واضح و عمدی است.
- طراحی متریال به همراه حرکت و پویانمایی، جهت ارائه‌ی مفاهیم مختلف به کاربر، جهت درک بهتر او از برنامه است.


برپایی پیشنیازهای ابتدایی کار با Angular Material

پیش از ادامه‌ی بحث فرض بر این است که آخرین نگارش Angular CLI را نصب کرده‌اید و اگر پیشتر آن‌را نصب کرده‌اید، یکبار دستور ذیل را اجرا کنید تا تمام وابستگی‌های سراسری نصب شده‌ی در سیستم به صورت خودکار به روز رسانی شوند:
 npm update -g
سپس برنامه‌ی کلاینت Angular این سری را به همراه تنظیمات ابتدایی مسیریابی آن از طریق صدور فرمان ذیل آغاز می‌کنیم:
 ng new MaterialAngularClient --routing
پس از ایجاد ساختار اولیه‌ی برنامه و نصب خودکار وابستگی‌های آن، جهت آزمایش برنامه، به پوشه‌ی آن وارد شده و آن‌را اجرا می‌کنیم:
cd MaterialAngularClient
ng serve -o
که به این ترتیب برنامه در آدرس http://localhost:4200 و مرورگر پیش‌فرض سیستم نمایش داده خواهد شد.


افزودن کتابخانه‌ی Angular Material به برنامه

در طول این سری از سایت https://material.angular.io زیاد استفاده خواهیم کرد. همواره به روزترین روش افزودن کتابخانه‌ی Angular Material به یک برنامه‌ی موجود را در آدرس https://material.angular.io/guide/getting-started می‌توانید مشاهده کنید که خلاصه‌ی آن به صورت زیر است:
البته در Angular 6 روش تفصیلی نصب فوق که شامل 6 مرحله‌است، به صورت زیر هم خلاصه شده‌است:
 ng add @angular/material
متاسفانه در زمان نگارش این مطلب، نگارش 6.3.1 آن توسط دستور فوق نصب نشد و خطای «Error: Collection "@angular/material" cannot be resolved.» ظاهر گردید. البته روش رفع آن در اینجا بحث شده‌است که مهم نیست و در نگارش‌های رسمی بعدی حتما لحاظ خواهد شد. به همین جهت روش تفصیلی آن‌را که همیشه کار می‌کند، در ادامه پیگیری می‌کنیم. ابتدا بسته‌های ذیل را نصب کنید:
npm install --save @angular/material @angular/cdk
npm install --save @angular/animations
npm install --save hammerjs
- دستور اول  angular/cdk و angular/material را نصب می‌کند. cdk در اینجا به معنای کیت توسعه‌ی کامپوننت‌های Angular است که امکان استفاده‌ی از ویژگی‌های Angular Material را بدون الزامی به پیروی از زبان طراحی متریال، میسر می‌کند.
- همانطور که عنوان شد، طراحی متریال مبتنی بر حرکت و پویانمایی است. به همین جهت تعدادی از کامپوننت‌های آن نیاز به بسته‌ی angular/animations را دارند که توسط دستور دوم نصب می‌شود.
- دستور سوم نیز کامپوننت‌های slide و slider را پشتیبانی می‌کند (Gesture Support). البته پس نصب این وابستگی، نیاز است به فایل src/main.ts مراجعه کرده و یک سطر زیر را نیز افزود:
 import "hammerjs";
در ادامه پس از نصب بسته‌ی پویانمایی، به فایل app.module.ts مراجعه کرده و BrowserAnimationsModule را به لیست imports اضافه می‌کنیم:
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";

@NgModule({
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    AppRoutingModule
  ]
})
export class AppModule { }

مدیریت بهتر import کامپوننت‌های Angular Material

در ادامه به ازای هر کامپوننت Angular Material باید ماژول آن‌را به لیست imports افزود که پس از مدتی به یک فایل app.module.ts بسیار شلوغ خواهیم رسید. برای مدیریت بهتر این فایل، از روش مطرح شده‌ی در مطلب «سازماندهی برنامه‌های Angular» استفاده خواهیم کرد.
به همین جهت دو پوشه‌ی core و shared را درون پوشه‌ی src/app ایجاد می‌کنیم:


محتویات فایل src\app\core\core.module.ts به صورت زیر است:
import { CommonModule } from "@angular/common";
import { NgModule, Optional, SkipSelf } from "@angular/core";
import { RouterModule } from "@angular/router";


@NgModule({
  imports: [CommonModule, RouterModule],
  exports: [
    // components that are used in app.component.ts will be listed here.
  ],
  declarations: [
    // components that are used in app.component.ts will be listed here.
  ],
  providers: [
    /* ``No`` global singleton services of the whole app should be listed here anymore!
       Since they'll be already provided in AppModule using the `tree-shakable providers` of Angular 6.x+ (providedIn: 'root').
       This new feature allows cleaning up the providers section from the CoreModule.
       But if you want to provide something with an InjectionToken other that its class, you still have to use this section.
    */
  ]
})
export class CoreModule {
  constructor(@Optional() @SkipSelf() core: CoreModule) {
    if (core) {
      throw new Error("CoreModule should be imported ONLY in AppModule.");
    }
  }
}
در مورد جزئیات آن در مطلب «سازماندهی برنامه‌های Angular توسط ماژول‌ها» کاملا بحث شده‌است.
محتویات فایل src\app\shared\shared.module.ts نیز به صورت زیر است:
import { CommonModule } from "@angular/common";
import { HttpClientModule } from "@angular/common/http";
import { ModuleWithProviders, NgModule } from "@angular/core";
import { FormsModule } from "@angular/forms";

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    HttpClientModule
  ],
  entryComponents: [
    // All components about to be loaded "dynamically" need to be declared in the entryComponents section.
  ],
  declarations: [
    // common and shared components/directives/pipes between more than one module and components will be listed here.
  ],
  exports: [
    // common and shared components/directives/pipes between more than one module and components will be listed here.
    CommonModule,
    FormsModule,
    HttpClientModule,
  ]
  /* No providers here! Since they’ll be already provided in AppModule. */
})
export class SharedModule {
  static forRoot(): ModuleWithProviders {
    // Forcing the whole app to use the returned providers from the AppModule only.
    return {
      ngModule: SharedModule,
      providers: [ /* All of your services here. It will hold the services needed by `itself`. */]
    };
  }
}
سپس تعاریف import این دو فایل را به فایل app.module.ts اضافه می‌کنیم:
import { CoreModule } from "./core/core.module";
import { SharedModule } from "./shared/shared.module";

@NgModule({
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    CoreModule,
    SharedModule.forRoot(),
    AppRoutingModule
  ]
})
export class AppModule { }
پس از این مقدمات، فایل جدید src\app\shared\material.module.ts را در پوشه‌ی shared ایجاد می‌کنیم تا بتوانیم مداخل کامپوننت‌های Angular Material را صرفا به آن اضافه کنیم؛ با این محتوا:
import { CdkTableModule } from "@angular/cdk/table";
import { NgModule } from "@angular/core";
import {
  MatAutocompleteModule,
  MatButtonModule,
  MatButtonToggleModule,
  MatCardModule,
  MatCheckboxModule,
  MatChipsModule,
  MatDatepickerModule,
  MatDialogModule,
  MatExpansionModule,
  MatFormFieldModule,
  MatGridListModule,
  MatIconModule,
  MatInputModule,
  MatListModule,
  MatMenuModule,
  MatNativeDateModule,
  MatPaginatorModule,
  MatProgressBarModule,
  MatProgressSpinnerModule,
  MatRadioModule,
  MatRippleModule,
  MatSelectModule,
  MatSidenavModule,
  MatSliderModule,
  MatSlideToggleModule,
  MatSnackBarModule,
  MatSortModule,
  MatStepperModule,
  MatTableModule,
  MatTabsModule,
  MatToolbarModule,
  MatTooltipModule,
} from "@angular/material";

@NgModule({
  imports: [
    MatAutocompleteModule,
    MatButtonModule,
    MatButtonToggleModule,
    MatCardModule,
    MatCheckboxModule,
    MatChipsModule,
    MatDatepickerModule,
    MatDialogModule,
    MatExpansionModule,
    MatFormFieldModule,
    MatGridListModule,
    MatIconModule,
    MatInputModule,
    MatListModule,
    MatMenuModule,
    MatNativeDateModule,
    MatPaginatorModule,
    MatProgressBarModule,
    MatProgressSpinnerModule,
    MatRadioModule,
    MatRippleModule,
    MatSelectModule,
    MatSidenavModule,
    MatSliderModule,
    MatSlideToggleModule,
    MatSnackBarModule,
    MatStepperModule,
    MatSortModule,
    MatTableModule,
    MatTabsModule,
    MatToolbarModule,
    MatTooltipModule,
    CdkTableModule
  ],
  exports: [
    MatAutocompleteModule,
    MatButtonModule,
    MatButtonToggleModule,
    MatCardModule,
    MatCheckboxModule,
    MatChipsModule,
    MatDatepickerModule,
    MatDialogModule,
    MatExpansionModule,
    MatGridListModule,
    MatIconModule,
    MatInputModule,
    MatListModule,
    MatMenuModule,
    MatNativeDateModule,
    MatPaginatorModule,
    MatProgressBarModule,
    MatProgressSpinnerModule,
    MatRadioModule,
    MatRippleModule,
    MatSelectModule,
    MatSidenavModule,
    MatSliderModule,
    MatSlideToggleModule,
    MatSnackBarModule,
    MatStepperModule,
    MatSortModule,
    MatTableModule,
    MatTabsModule,
    MatToolbarModule,
    MatTooltipModule,
    CdkTableModule
  ]
})
export class MaterialModule {
}
در اینجا هر کامپوننت مورد نیاز، به قسمت‌های import و exports اضافه شده‌اند.
سپس MaterialModule را نیز به قسمت‌های imports و exports فایل src\app\shared\shared.module.ts اضافه خواهیم کرد:
import { MaterialModule } from "./material.module";

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    HttpClientModule,
    MaterialModule
  ],
  exports: [
    // common and shared components/directives/pipes between more than one module and components will be listed here.
    CommonModule,
    FormsModule,
    HttpClientModule,
    MaterialModule
  ]
})
export class SharedModule {
}
به این ترتیب در هر ماژول جدیدی که به برنامه اضافه شود و نیاز به کار با Angular Material را داشته باشد، تنها کافی است SharedModule را import کرد؛ مانند app.module.ts برنامه (البته بدون ذکر متد forRoot آن که این forRoot فقط محض ماژول اصلی برنامه است).

تا اینجا جهت اطمینان از اجرای برنامه، دستور ng serve -o را از ابتدا اجرا کنید.


افزودن چند کامپوننت مقدماتی متریال به برنامه

بهترین روش کار با این مجموعه، بررسی مستندات آن در سایت https://material.angular.io/components است. برای مثال برای افزودن دکمه، به مستندات آن مراجعه کرده و بر روی دکمه‌ی view source کلیک می‌کنیم:


سپس کدهای قسمت HTML آن‌را به برنامه و فایل app.component.html اضافه خواهیم کرد:
 <button mat-button>Click me!</button>
به همین ترتیب مستندات check box را یافته و آن‌را نیز اضافه می‌کنیم:
 <mat-checkbox>Check me!</mat-checkbox>
تا اینجا اگر برنامه را توسط دستور ng serve -o اجرا کنیم، یک چنین خروجی حاصل می‌شود:


البته شکل ظاهری آن‌ها تا اینجا آنچنان مطلوب نیست. برای رفع این مشکل، نیاز است یک قالب را به این کنترل‌ها و کامپوننت‌ها اعمال کرد. به همین جهت فایل styles.css واقع در ریشه‌ی برنامه را گشوده و قالب پیش‌فرض متریال را به آن اضافه می‌کنیم:
 @import "~@angular/material/prebuilt-themes/indigo-pink.css";
قالب‌های از پیش آماده‌ی متریال را در پوشه‌ی node_modules\@angular\material\prebuilt-themes می‌توانید مشاهده کنید.



پس از اعمال قالب، اکنون است که شکل ظاهری کنترل‌های آن بسیار بهتر شده‌اند و همچنین کار با آن‌ها به همراه پویانمایی نیز شده‌است:



افزودن آیکن‌های متریال به برنامه

مرحله‌ی آخر این تنظیمات، افزودن آیکن‌های متریال به برنامه‌است. برای این منظور فایل src\index.html را گشوده و یک سطر ذیل را به head اضافه کنید:
 <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
برای آزمایش آن، به فایل app.component.html مراجعه کرده و تعریف دکمه‌ای را که اضافه کردیم، به صورت ذیل با افزودن mat-icon تغییر می‌دهیم:
<button mat-button>
  <mat-icon>face</mat-icon>
  Click me!
</button>
<mat-checkbox>Check me!</mat-checkbox>
که این خروجی را تولید می‌کند:


لیست کامل این آیکن‌ها را به همراه توضیحات تکمیلی آن‌ها، در آدرس ذیل می‌توانید ملاحظه کنید:
http://google.github.io/material-design-icons

البته چون ما نمی‌خواهیم این آیکن‌ها را از وب بارگذاری کنیم، برای نصب محلی آن‌ها ابتدا دستور زیر را در ریشه‌ی پروژه صادر کنید:
 npm install material-design-icons --save
این آیکن فونت‌ها پس از نصب، در مسیر node_modules\material-design-icons\iconfont قابل مشاهده هستند:


همانطور که مشاهده می‌کنید، برای استفاده‌ی از این فایل‌های آیکن فونت محلی، تنها کافی است فایل material-icons.css را به برنامه معرفی کنیم. برای این منظور فایل angular.json را گشوده و قسمت styles آن‌را به صورت زیر تکمیل می‌کنیم:
"styles": [
   "node_modules/material-design-icons/iconfont/material-icons.css",
   "src/styles.css"
],
اکنون دیگر نیازی به ذکر link href اضافه شده‌ی به فایل src\index.html نداریم و باید از آن حذف شود.



کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید: MaterialAngularClient-01.zip
برای اجرای آن نیز ابتدا فایل restore.bat و سپس فایل ng-serve.bat را اجرا کنید.
مطالب
ارتقاء به Angular 6: بررسی تغییرات Angular CLI
اولین مرحله‌ی ارتقاء به Angular 6، به روز رسانی Angular CLI 1.x به نگارش 6 آن است. این شماره نگارش نیز با شماره نگارش Angular یکی شده‌است و دیگر 1x نیست. CLI 6.0 فقط پروژه‌های Angular 5.x و 6x را پشتیبانی می‌کند و برای نصب آن نیاز به حداقل NodeJS 8.9 و NPM 5.5 را خواهید داشت. بنابراین ابتدا دستورات زیر را صادر کرده و اگر هنوز از نگارش‌های قدیمی این ابزارها استفاده می‌کنید، قبل از هر کاری باید آن‌ها را به روز رسانی کنید:
node -v
npm -v
این نگارش از CLI در پشت صحنه از Webpack 4 استفاده می‌کند که نسبت به نگارش‌های پیشین آن بسیار سریعتر است، tree-shaking بهتری را انجام می‌دهد و در نهایت سبب تولید برنامه‌هایی با حجم کمتر و با سرعت build بیشتری خواهد شد.


فایل پیشین angular-cli.json حذف و فایل جدید angular.json بجای آن معرفی شده‌است

یکی از مهم‌ترین تغییرات CLI 6.0 نسبت به نگارش‌های قبلی آن، پشتیبانی از چندین پروژه است و به همین منظور ساختار فایل تنظیمات آن‌را به طور کامل تغییر داده‌اند و اگر دستور ng new project1 را صادر کنید، دیگر از فایل پیشین angular-cli.json خبری نبوده و بجای آن فایل جدید angular.json قابل مشاهده‌است:
{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "project1": {
در اینجا ساختار ابتدای فایل angular.json را مشاهده می‌کنید که در آن مفهوم projects (و یا workspace در اینجا) به همراه project1 جدیدی که ایجاد کردیم، به عنوان زیر مجموعه‌ی آن قابل مشاهده‌است.
مزیت مهم این قابلیت، امکان ایجاد libraries است که به صورت توکار از این نگارش پشتیبانی می‌شود و می‌توان اجزایی مانند components ،directives ،pipes و services اشتراکی را در یک یا چندین کتابخانه قرار داد و سپس از آن‌ها در پروژه‌ی اصلی و یا چندین پروژه‌ی متصل استفاده کرد.
نگارش 6 در پشت صحنه، پروژه‌ی موفق ng-packagr را به مجموعه‌ی CLI اضافه کرده‌است و از این پس توسط خود CLI می‌توان کتابخانه‌های استاندارد Angular را تولید کرد. این مورد، مزیت استاندارد سازی کتابخانه‌های npm حاصل را نیز به همراه دارد؛ مشکلی که گاهی از اوقات به علت عدم رعایت این ساختار، با بسته‌های فعلی npm مخصوص Angular وجود دارند. برای مثال بدون استفاده‌ی از این ابزار، نیاز است مستندات 13 صفحه‌ای ساخت کتابخانه‌های Angular را سطر به سطر پیاده سازی کنید که توسط CLI 6.0، به صورت خودکار ایجاد و مدیریت می‌شود.

بنابراین اکنون سؤال مهمی که مطرح می‌شود این است: آیا باید فایل angular-cli.json پیشین را به صورت دستی به این فایل جدید به روز رسانی کرد و چگونه؟


به روز رسانی تمام بسته‌های سراسری سیستم

در ادامه پیش از هر کاری نیاز است تمام بسته‌های سراسری npm ایی را که هر از چندگاهی به سیستم خود اضافه کرده‌اید، به روز رسانی کنید. برای مشاهده‌ی لیست موارد تاریخ مصرف گذشته‌ی آن‌ها، دستور زیر را صادر کنید:
 npm outdated -g --depth=0
و برای به روز رسانی یکجای آن‌ها نیاز است دستور زیر اجرا شود:
 npm update -g


به روز رسانی خودکار ساختار فایل angular-cli.json

این به روز رسانی توسط CLI 6.0 به صورت خودکار پشتیبانی می‌شود و شامل این مراحل است:
ابتدا نیاز است بسته‌ی سراسری آن‌را به روز رسانی کرد:
 npm i -g @angular/cli
سپس وارد پوشه‌ی اصلی پروژه‌ی خود شده و این دستور را به صورت محلی نیز وارد کنید:
 npm install --save-dev @angular/cli@latest
با اینکار بسته‌ی CLI محلی پروژه به روز شده و اکنون می‌توانیم از قابلیت جدید آن که ng update نام دارد، استفاده کنیم. برای این منظور دستورات ذیل را به ترتیب اجرا کنید:
ng update @angular/cli
ng update @angular/core
ng update rxjs
دستور اول کار تبدیل خودکار فایل angular-cli.json قدیمی را به ساختار جدید آن انجام میدهد؛ با این لاگ:
DELETE .angular-cli.json
CREATE angular.json (4273 bytes)
UPDATE karma.conf.js (1008 bytes)
UPDATE src/tsconfig.spec.json (322 bytes)
UPDATE package.json (2076 bytes)
UPDATE tslint.json (3217 bytes)
دستور دوم بسته‌های هسته‌ی angular را به روز رسانی می‌کند و دستور سوم کار به روز رسانی کتابخانه‌ی rxjs را انجام می‌دهد.
لیست سایر بسته‌هایی را که می‌توان توسط این دستور به روز رسانی کرد، با اجرا دستور ng update می‌توانید مشاهده کنید. برای مثال اگر از Angular Material نیز استفاده می‌کنید، دستور به روز رسانی آن به صورت زیر است:
 ng update @angular/material


مشکل! دستور ng update کار نمی‌کند!

اگر پروژه‌ی شما صرفا مبتنی بر بسته‌های اصلی Angular باشد، مراحل یاد شده‌ی فوق را با موفقیت به پایان خواهید رساند. اما اگر از کتابخانه‌های ثالثی استفاده کرده باشید، منهای دستور «ng update @angular/cli» که کار تولید فایل جدید angular.json را انجام می‌دهد، مابقی با خطاهایی مانند «incompatible peer dependency» و یا «Invalid range:>=2.3.1 <3.0.0||>=4.0.0» متوقف می‌شوند.
در یک چنین حالتی نیاز است ابتدا وابستگی‌های محلی پروژه را به روز کرد و سپس دستورات ng update را تکرار نمود. برای این منظور ابتدا بسته‌ی npm-check-updates را نصب کنید:
 npm install npm-check-updates -g
کار آن به روز رسانی خودکار بسته‌های npm یک پروژه است. پس از آن دستورات زیر را صادر نمائید:
ncu -u
npm install
دستور اول تمام شماره نگارش‌های بسته‌های موجود در فایل package.json را به صورت خودکار به آخرین نگارش آن‌ها روز رسانی می‌کند و دستور دوم این بسته‌های جدید را دریافت و نصب خواهد کرد.
اکنون تمام وابستگی‌های محلی پروژه‌ی شما به صورت خودکار به آخرین نگارش آن‌ها به روز رسانی شده‌اند و اینبار اگر دستورات ذیل را اجرا کنید، با خطاهای یاد شده مواجه نخواهید شد:
ng update @angular/core
ng update rxjs

البته اگر در این حالت برنامه را کامپایل کنید، کار نخواهد کرد. علت اصلی آن به به‌روز رسانی rxjs به نگارش 6 آن مرتبط می‌شود که در مطلب بعدی پیگیری خواهد شد و این نگارش شامل حذفیات بسیاری است در جهت کاهش حجم آن، یکپارچکی و یک دست شدن syntax آن و همچنین بهبود قابل ملاحظه‌ی کارآیی آن. البته پیشنیاز الزامی آن آشنایی با pipe-able operators است. علت دیگر کامپایل نشدن برنامه هم می‌تواند عدم استفاده از HttpClient نگارش 4.3 به بعد باشد.


خاموش کردن اخطار «TypeScript version mismatch»

اگر نگارش TypeScript نصب شده‌ی در سیستم به صورت سراسری، با نگارش محلی پروژه‌ی شما یکی نباشد، اخطار «TypeScript version mismatch» را دریافت می‌کنید. روش خاموش کردن آن در CLI جدید با اجرای دستور زیر است:
 ng config cli.warnings.typescriptMismatch false
البته نگارش 6 نیاز به TypeScript 2.7.2 ذکر شده‌ی در package.json پروژه‌ی محلی را دارد؛ وگرنه اصلا شروع به کامپایل برنامه نمی‌کند:
{
  "devDependencies": {
    "typescript": "~2.7.2"
  }
}
بهترین راه برای یافتن این شماره، اجرای دستور ng new projet1 در یک پوشه‌ی خالی است و سپس مقایسه‌ی محتوای فایل package.json آن با فایل پروژه‌ی موجود.


 تغییرات ng build در نگارش 6

در نگارش 6، مفهوم پیشین environments به configurations تغییر یافته‌است و اینبار در فایل جدید angular.json تنظیم می‌شوند:
{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "version": 1,
  "newProjectRoot": "projects",
  "projects": {
    "angular-template-driven-forms-lab": {
          "configurations": {
            "production": {
              "optimization": true,
              "outputHashing": "all",
              "sourceMap": false,
              "extractCss": true,
              "namedChunks": false,
              "aot": true,
              "extractLicenses": true,
              "vendorChunk": false,
              "buildOptimizer": true,
              "fileReplacements": [
                {
                  "replace": "src/environments/environment.ts",
                  "with": "src/environments/environment.prod.ts"
                }
              ]
            }
          }
        },
و پیشتر اگر برای تنظیم محیط build از سوئیچ env استفاده می‌شد:
 ng build --env staging
اکنون این سوئیچ به configuration تغییر یافته‌است و نام آن از مداخل configurations فایل angular.json، مانند مثال فوق که «production» نام دارد، باید دریافت و تنظیم شود:
 ng build --configuration staging
و یا برای مثال دستور «ng build --env=prod» دیگر اجرا نمی‌شود و env=prod حذف شده‌است و اکنون اجرای  ng build --prod مانند اجرای دستور ng build --configuration=prod است.


تغییرات نام‌های نهایی تولیدی

در CLI 6.0، نام‌های نهایی تولیدی دیگر به همراه bundle  و یا chunk نیستند. برای مثال دستور ng build یک چنین خروجی را تولید می‌کند:
 >ng build --watch

Date: 2018-05-05T09:10:50.158Z
Hash: a43eab94ff01539b8592
Time: 31733ms
chunk {main} main.js, main.js.map (main) 9.38 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 226 kB [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 5.4 kB [entry] [rendered]
chunk {styles} styles.js, styles.js.map (styles) 15.6 kB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 3.05 MB [initial] [rendered]

و هش‌های حالت prod به صورت زیر تولید و به نام فایل اضافه می‌شوند:
>ng build --prod --watch

Date: 2018-05-05T09:17:01.803Z
Hash: f25fd6788a4969c52b70
Time: 73279ms
chunk {0} runtime.6afe30102d8fe7337431.js (runtime) 1.05 kB [entry] [rendered]
chunk {1} styles.34c57ab7888ec1573f9c.css (styles) 0 bytes [initial] [rendered]
chunk {2} polyfills.6c08419970f9e4781b69.js (polyfills) 59.4 kB [initial] [rendered]


ساده شدن افزودن وابستگی‌های ثالث به پروژه‌های CLI

برای نصب یک کتابخانه‌ی ثالث، پیشتر می‌بایستی ابتدا بسته‌ی npm آن جداگانه نصب و سپس فایل config برنامه، جهت معرفی مداخل آن، ویرایش می‌شد. اکنون دستور جدید ng add تمام این مراحل را به صورت خودکار انجام می‌دهد:
 ng add @angular/material
برای نمونه دستور فوق نه تنها فایل‌های Angular Material را دریافت می‌کند، بلکه فایل‌های CSS و ماژول‌های مرتبط با آن‌را نیز import خواهد کرد. البته این مورد از کلید ng-add فایل package.json بسته‌ی در حال نصب دریافت و تنظیم می‌شود و کتابخانه‌های جدید باید خود را بر این اساس وفق دهند.
اشتراک‌ها
کتابخانه AngularJS Integration For Kendo UI
angular-kendo is a directive for AngularJS that runs an element through Kendo UI declarative initialization, allowing you to take full advantage of Kendo UI within the context of an AngularJS Application.  
کتابخانه AngularJS Integration For Kendo UI
نظرات مطالب
ارتقاء به ASP.NET Core 1.0 - قسمت 8 - فعال سازی ASP.NET MVC
ممنون. پروژه 3.1 از نوع dotnet new angular ایجاد کردم. یک کنترلر دارد به این صورت :
public class WeatherForecastController : ControllerBase
کلاس ControllerBase  چیست؟ با VSCode توضیحش اینه : A base class for an MVC controller without view support
میشه گفت این هم POCO Controller است؟
نظرات مطالب
کنترل دسترسی‌ها در Angular با استفاده از Ng2Permission
بعد از نصب و معرفی آن در appmodule برنامه ،  پیغام زیر درCommand Prompt نمایش می‌دهد. آیا این پکیج همخوانی با Angular 5 ندارد؟
ERROR in ./node_modules/angular2-permission/index.ts
Module build failed: Error: C:\Front\node_modules\angular2-permission\index.ts is missing from the TypeScript compilation. Please make sure it is in your tsconfig via the 'files' or 'include' property.
The missing file seems to be part of a third party library. TS files in published libraries are often a sign of a badly packaged library. Please open an issue in the library repository to alert its author and ask them to package the library using the Angular Package Format (https://goo.gl/jB3GVv).
    at AngularCompilerPlugin.getCompiledFile (C:\Front\node_modules\@ngtools\webpack\src\angular_compiler_plugin.js:674:23)
    at plugin.done.then (C:\Front\node_modules\@ngtools\webpack\src\loader.js:467:39)
    at process._tickCallback (internal/process/next_tick.js:68:7)

مطالب
استفاده از پیاده سازی Katana مربوط به استاندارد Owin در ASP.NET 4.x
قطعا ASP.NET MVC 5.x به عنوان یک فریم ورک بالغ و با امکانات فراوان شناخته میشود که در این مساله هیچ بحثی نیست. اما آیا در همه‌ی پروژه‌ها حتما باید از این فریم ورک استفاده شود؟ امروزه اکثر وب اپلیکیشن‌ها از فریم ورک‌های SPA استفاده میکنند و بنده به وفور در پروژه‌های مختلف شاهد این بوده‌ام که ASP.NET MVCی که در کنار آن استفاده میشود، عملا چیزی بیشتر از یک کنترلر Home و یک متد Index و حداکثر یک Layout، نیستند و معمولا در کنار آن از Web Api استفاده میکنند که حداقل در ASP.NET MVC 5.x چیزی کاملا مجزای از آن به حساب می‌آید. با این حال آیا واقعا از امکانات MVC 5.x استفاده شده است؟! یا فقط اینگونه پروژه‌ها محدودیت‌های MVC را به دوش میکشند؟
در ASP.NET 4.x به صورت معمول ارسال درخواست‌ها بدین صورت است که از سمت کلاینت به IIS و بعد از آن بر روی ISAPI نگاشت میشوند (یا Static File برای فایل‌های استاتیک). پس عملا وابستگی شدیدی به IIS ایجاد شده‌است و اینکه مشکلات این وابستگی چیست در این مقاله نمیگنجد. اگر قرار باشد همین امروز پروژه‌ای شروع شود قطعا ASP.NET 4.x گزینه‌ی معقولی به نظر میرسد؛ اما در پروژه‌های حجیم بیزینسی که باید ماه‌ها و شاید چندین سال بر روی نرم افزار آن کار شود، آیا آن موقع نیز ASP.NET مانند حال گزینه‌ی معقولی است یا بطور مثال ASP.NET Core با امکانات منحصر به فردش جایگزین خواهد شد؟ در نگاه اول وقتی دو پروژه‌ی ASP.NET 4.x و ASP.NET Core را در کنار هم میگذاریم، شاید اختلافات زیاد باشند و ارتقاء نرم افزار به ASP.NET Core سخت و یا حتی غیر ممکن به نظر برسد. اما آیا واقعا هیچ راهی وجود ندارد که هم اکنون نرم افزار خود را با ASP.NET 4.x که کاملا بالغ هم شده شروع کرده و بعد‌ها به ASP.NET Core به روز رسانی شود؟
این‌ها سوال‌هایی است که قطعا قبل از شروع یک پروژه‌ی بزرگ نرم افزاری باید از خود بپرسیم. شاید با نگاه عمیق‌تری بر روی این سوال‌ها بتوان پاسخی مناسب را برای آن‌ها داد. یکی از این راه‌حل‌ها استفاده از استاندارد Owin و پیاده سازی آن به نام Katana است.

برای شروع پروژه ابتدا یک پروژه‌ی ASP.NET 4.x از نوع empty را بسازید.
برای راحت شدن کار، ابتدا packages.config را باز کرده و کد‌های زیر را جایگزین آن نمایید:
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.AspNet.OData" version="6.0.0" targetFramework="net462" />
  <package id="Microsoft.AspNet.SignalR.Core" version="2.2.1" targetFramework="net462" />
  <package id="Microsoft.AspNet.SignalR.Owin" version="1.2.2" targetFramework="net462" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net462" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net462" />
  <package id="Microsoft.AspNet.WebApi.Owin" version="5.2.3" targetFramework="net462" />
  <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.2" targetFramework="net462" />
  <package id="Microsoft.Extensions.DependencyInjection" version="1.0.0" targetFramework="net462" />
  <package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="1.0.0" targetFramework="net462" />
  <package id="Microsoft.Net.Compilers" version="1.3.2" targetFramework="net462" developmentDependency="true" />
  <package id="Microsoft.OData.Core" version="7.0.0" targetFramework="net462" />
  <package id="Microsoft.OData.Edm" version="7.0.0" targetFramework="net462" />
  <package id="Microsoft.Owin" version="3.0.1" targetFramework="net462" />
  <package id="Microsoft.Owin.FileSystems" version="3.0.1" targetFramework="net462" />
  <package id="Microsoft.Owin.Host.SystemWeb" version="3.0.1" targetFramework="net462" />
  <package id="Microsoft.Owin.Security" version="3.0.1" targetFramework="net462" />
  <package id="Microsoft.Owin.StaticFiles" version="3.0.1" targetFramework="net462" />
  <package id="Microsoft.Spatial" version="7.0.0" targetFramework="net462" />
  <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net462" />
  <package id="Owin" version="1.0" targetFramework="net462" />
  <package id="System.Collections" version="4.0.11" targetFramework="net462" />
  <package id="System.Collections.Concurrent" version="4.0.12" targetFramework="net462" />
  <package id="System.ComponentModel" version="4.0.1" targetFramework="net462" />
  <package id="System.Diagnostics.Debug" version="4.0.11" targetFramework="net462" />
  <package id="System.Globalization" version="4.0.11" targetFramework="net462" />
  <package id="System.Linq" version="4.1.0" targetFramework="net462" />
  <package id="System.Linq.Expressions" version="4.1.0" targetFramework="net462" />
  <package id="System.Reflection" version="4.1.0" targetFramework="net462" />
  <package id="System.Resources.ResourceManager" version="4.0.1" targetFramework="net462" />
  <package id="System.Runtime.Extensions" version="4.1.0" targetFramework="net462" />
  <package id="System.Threading" version="4.0.11" targetFramework="net462" />
  <package id="System.Threading.Tasks" version="4.0.11" targetFramework="net462" />
</packages>
ما پکیج‌های OData و SignlarR , WebApi, Owin را اضافه نموده‌ایم و دستور زیر را برای اضافه شدن ارجاعات اجرا می‌کنیم:
PM>Update-Package -reinstall -Project YourProjectName
اکنون عملا تمام پکیج‌های لازم را برای شروع به کار، در اختیار داریم (اگر از dotNetFrameWork نسخه‌ی پایین‌تری بطور مثال 4.6.1 استفاده میکنید، بعد از اجرای دستور فوق، targetFramework شما به 461 اصلاح خواهد شد).
حال میخواهیم کمی کار اختیاری را نیز بر روی وب کانفیگ انجام دهیم که به performance نرم افزار شما بهبود قابل ملاحظه‌ای را می‌افزاید. کد‌های زیر را در وب کانفیگ جایگزین نمایید:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="owin:AppStartup" value="OwinKatanaTest.OwinAppStartup, OwinKatanaTest" />
    <!-- Owin App Startup Class -->
    <add key="webpages:Enabled" value="false" />
    <!-- Disable asp.net web pages. Note that based on our current configuration, asp.net web forms, mvc and web pages won't work. This configuration is for owin stuffs only, for example asp.net web api & odata, signalr, etc. -->
  </appSettings>
  <system.web>
    <compilation debug="true" defaultLanguage="c#" enablePrefetchOptimization="true" optimizeCompilations="true" targetFramework="4.6.2">
      <assemblies>
        <remove assembly="*" />
        <!-- To improve app startup performance, our app will continue its work without this compilations, these are required for asp.net web forms, mvc and web pages. -->
        <add assembly="OwinKatanaTest" />
      </assemblies>
    </compilation>
    <httpRuntime targetFramework="4.6.2" />
    <httpModules>
      <!-- No need to these modules and handlers, owin handler itself will do everything for us -->
      <clear />
    </httpModules>
    <httpHandlers>
      <clear />
    </httpHandlers>
    <sessionState mode="Off" />
  </system.web>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701" />
    </compilers>
  </system.codedom>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.AspNet.SignalR.Core" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-2.2.1.0" newVersion="2.2.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Reflection" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Runtime.Extensions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.1.0.0" newVersion="4.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="false">
      <!-- We're not going to remove all modules, some modules such as static & dynamic compression modules are really cool (-: -->
      <remove name="RewriteModule" />
      <remove name="OutputCache" />
      <remove name="Session" />
      <remove name="WindowsAuthentication" />
      <remove name="FormsAuthentication" />
      <remove name="DefaultAuthentication" />
      <remove name="RoleManager" />
      <remove name="FileAuthorization" />
      <remove name="UrlAuthorization" />
      <remove name="AnonymousIdentification" />
      <remove name="Profile" />
      <remove name="UrlMappingsModule" />
      <remove name="ServiceModel-4.0" />
      <remove name="UrlRoutingModule-4.0" />
      <remove name="ScriptModule-4.0" />
      <remove name="Isapi" />
      <remove name="IsapiFilter" />
      <remove name="DigestAuthentication" />
      <remove name="WindowsAuthentication" />
      <remove name="ServerSideInclude" />
      <remove name="DirectoryListing" />
      <remove name="DefaultDocument" />
      <remove name="CustomError" />
      <remove name="Cgi" />
    </modules>
    <defaultDocument>
      <!-- Default docs will be configured using owin static files middleware -->
      <files>
        <clear />
      </files>
    </defaultDocument>
    <handlers>
      <!-- Only use this handler for all requests -->
      <clear />
      <add name="Owin" verb="*" path="*" type="Microsoft.Owin.Host.SystemWeb.OwinHttpHandler, Microsoft.Owin.Host.SystemWeb" />
    </handlers>
    <httpProtocol>
      <customHeaders>
        <clear />
      </customHeaders>
    </httpProtocol>
  </system.webServer>
</configuration>
1) AppSettings برای کانفیگ Owin startup خواهد بود (در ادامه‌ی مقاله آن را مینویسیم).
2) در تگ compilation اسمبلی‌های اضافی را حذف مینماییم (برای بهبود performance از آنجایی که به asp.net web form یا mvc احتیاجی نداریم).
3) حذف http module و http handler در system.web (مربوط به iis 6).
4) در تگ system.codedom کامپایلر مربوط به vb را حذف مینماییم.
5) در تگ system.webserver ماژول‌ها و هندلر‌های اضافی را پاک مینماییم.
6) تگ defaultdocument، به دلیل اینکه از static file مربوط به owin استفاده میکنیم.
7) custom headers‌ها را نیز پاک میکنیم.

بعد از build کردن پروژه، در صورت خطا داشتن از References‌ها، System.Reflection و System.Runtime.Extensions را حذف کنید.
یک ریشه جدید را به نام Model ساخته و مدل‌های آزمایشی Product و Category را که هر دو فقط حاوی دو پراپرتی Id, Name میباشند، به آن اضافه کنید.

در root پروژه یک کلاس به نام OwinAppStartup را با محتوای زیر بسازید
using Microsoft.AspNet.SignalR;
using Microsoft.OData;
using Microsoft.OData.Edm;
using Owin;
using OwinKatanaTest.Model;
using OwinKatanaTest.ODataControllers;
using System.Collections.Generic;
using System.Web.Http;
using System.Web.OData.Builder;
using System.Web.OData.Extensions;
using System.Web.OData.Routing.Conventions;

namespace OwinKatanaTest
{
    public class OwinAppStartup
    {
        public void Configuration(IAppBuilder owinApp)
        {
            owinApp.Map("/odata", innerOwinAppForOData =>
            {
                HttpConfiguration webApiODataConfig = new HttpConfiguration();
                webApiODataConfig.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;

                webApiODataConfig.Formatters.Clear();

                IEnumerable<IODataRoutingConvention> conventions = ODataRoutingConventions.CreateDefault();

                ODataModelBuilder modelBuilder = new ODataConventionModelBuilder(webApiODataConfig);

                modelBuilder.Namespace = modelBuilder.ContainerName = "Test";
                var categoriesSetConfig = modelBuilder.EntitySet<Category>("Categories");
                var getBestCategoryFunctionConfig = categoriesSetConfig.EntityType.Collection.Function(nameof(CategoriesController.GetBestCategory));
                getBestCategoryFunctionConfig.ReturnsFromEntitySet<Category>("Categories");

                IEdmModel edmModel = modelBuilder.GetEdmModel();

                webApiODataConfig.MapODataServiceRoute("default", "", builder =>
                {
                    builder.AddService(ServiceLifetime.Singleton, sp => conventions);
                    builder.AddService(ServiceLifetime.Singleton, sp => edmModel);
                });

                innerOwinAppForOData.UseWebApi(webApiODataConfig);

            });

            owinApp.Map("/api", innerOwinAppForWebApi =>
            {
                HttpConfiguration webApiConfig = new HttpConfiguration();
                webApiConfig.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;

                webApiConfig.MapHttpAttributeRoutes();

                webApiConfig.Routes.MapHttpRoute(name: "default", routeTemplate: "{controller}/{action}", defaults: new { action = RouteParameter.Optional });

                innerOwinAppForWebApi.UseWebApi(webApiConfig);
            });

            owinApp.Map("/signalr", innerOwinAppForSignalR =>
            {
                innerOwinAppForSignalR.RunSignalR(new HubConfiguration
                {
                    EnableDetailedErrors = true
                });
            });

            owinApp.UseStaticFiles();

            owinApp.Run(async context =>
            {
                await context.Response.WriteAsync("owin katana");
            });
        }
    }
}
در وب کانفیگ، کار مربوط به استارتاپ را انجام دادیم و دیگر نیازی به قید کردن آن نیست. نگاشت اول، کانفیگ OData، دومی برای web api و همچنین سومی کانفیگ SignalR میباشد.
سپس یک پوشه‌ی جدید را به نام ODataControllers حاوی کلاسی با نام CategoriesController بدین گونه بسازید:
using OwinKatanaTest.Model;
using System.Web.Http;
using System.Web.OData;

namespace OwinKatanaTest.ODataControllers
{
    public class CategoriesController : ODataController
    {
        [HttpGet]
        public Category GetBestCategory()
        {
            return new Category { Id = 1, Name = "Test" };
        }
    }
}
و همچنین یک پوشه دیگر را به نام ApiControllers  به نام ProductsController با محتوای زیر:
using OwinKatanaTest.Model;
using System.Collections.Generic;
using System.Web.Http;

namespace OwinKatanaTest.ApiControllers
{
    public class ProductsController : ApiController
    {
        [HttpGet]
        [Route("products/{categoryId}")]
        public List<Product> GetProductsByCategoryId(int categoryId)
        {
            return new List<Product>
            {
                new Product { Id = 1 , Name = "Test" }
            };
        }
    }
}
حالا میتوانیم یه پروژه‌ی یونیت تست نوشته و کلیات مراحل فوق را تست نماییم. unit test را به پروژه اضافه کنید و reference پروژه‌ی اصلی خود را بدان اضافه کنید.
مانند پروژه‌ی قبلی، package.config را اضافه کرده و همه‌ی پکیج‌های قبلی به علاوه پکیج زیر را اضافه کنید:
<package id="Microsoft.Owin.Testing" version="3.0.1" targetFramework="net462" />
update-package فراموش نشود

در ادامه تست خود را اینگونه مینویسیم
using Microsoft.Owin.Testing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OwinKatanaTest;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

namespace Test
{
    [TestClass]
    public class Test
    {
        [TestMethod]
        public async Task TestWebApi()
        {
            using (TestServer server = TestServer.Create<OwinAppStartup>())
            {
                HttpResponseMessage apiResponse = await server.HttpClient.GetAsync("/api/products/1");
                apiResponse.EnsureSuccessStatusCode();
                Assert.AreEqual(HttpStatusCode.OK, apiResponse.StatusCode);
            }
        }

        [TestMethod]
        public async Task TestOData()
        {
            using (TestServer server = TestServer.Create<OwinAppStartup>())
            {
                HttpResponseMessage odataResponse = await server.HttpClient.GetAsync("odata/Categories/Test.GetBestCategory");
                odataResponse.EnsureSuccessStatusCode();
                Assert.AreEqual(HttpStatusCode.OK, odataResponse.StatusCode);
            }
        }
    }
}
الان باید solution شما چیزی شبیه به این باشد:

بعد از اجرای تست‌ها، باید تیک سبز کنارشان ایجاد شود.
بعد از خواندن این مقاله شاید متوجه شده باشید که چقدر pipeline این پروژه شبیه به پروژه‌های ASP.NET Coreی است؛ یا بهتر است تصحیح کنم به عکس. بلکه ASP.NET Core هست که خیلی شبیه به این میباشد!
عملا سرویس‌های شما کاملا مجزا شده‌اند و میتوانید به راحتی یک فریم ورک SPA را به پروژه‌ی خود اضافه کرده و برای Authentication هم Single Sign On Identity Server بسیار مناسب میباشد. بدون اینکه حتی برنامه نویسان بیزینسی پروژه‌ی شما متوجه بشوند، با تغییراتی در کانفیگ این پروژه، می‌توان آن را بروزرسانی نمود.
لینک دانلود پروژه OwinKatanaTest.zip