مطالب
روش ایجاد پروژه‌ها‌ی کتابخانه‌ای کامپوننت‌های Blazor
جهت به اشتراک گذاشتن کامپوننت‌های سفارشی Blazor در پروژه‌های مختلف، امکان بسته بندی آن‌ها به صورت کتابخانه‌های کامپوننت‌ها نیز پیش‌بینی شده‌است که می‌توانند به همراه فایل‌های CSS ،JS و تصاویر هم باشند.


روش ایجاد یک پروژه‌ی کتابخانه‌ای، از کامپوننت‌های Blazor

اگر از ویژوال استودیو استفاده می‌کنید، نوع «Razor Class Library»، پروژه‌های مخصوص کتابخانه‌های کامپوننت‌های Blazor را آغاز می‌کند و اگر می‌خواهید از CLI استفاده کنید، باید از دستور «dotnet new razorclasslib» استفاده کرد؛ که قابلیت تبدیل به بسته‌های نیوگت را با دستور dotnet pack داشته و به این ترتیب می‌توان آن‌ها را به اشتراک گذاشت و یا حتی می‌توان ارجاعی از این پروژه را در سایر پروژه‌های شخصی، مورد استفاده قرار داد.
ساختار پیش‌فرض فایل csproj اینگونه پروژه‌ها به صورت زیر است:
<Project Sdk="Microsoft.NET.Sdk.Razor">
  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>
  
  <ItemGroup>
    <SupportedPlatform Include="browser" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Components.Web" Version="5.0.6" />
  </ItemGroup>
</Project>

روش افزودن فایل‌های ثابت مورد استفاده‌ی در کتابخانه

پروژه‌ی پیش‌فرضی که در اینجا ایجاد می‌شود، به همراه یک پوشه‌ی wwwroot نیز هست. این پوشه محلی است که باید فایل‌های ثابت اشتراکی پروژه را مانند فایل‌های CSS و JS مورد استفاده، قرار داد.
این نوع پروژه‌ها از ویژگی Isolated CSS و یا Isolated JS ارائه شد‌ه‌ی در Blazor 5x نیز پشتیبانی می‌کنند.


روش استفاده‌ی از فایل‌های ثابت موجود در یک کتابخانه

این فایل‌های ثابت به همراه بسته‌ی نهایی پروژه، به صورت خودکار توزیع می‌شوند (و نیازی به ارائه‌ی مجزای آن‌ها نیست) و برای استفاده‌ی از آن‌ها در پروژه‌های دیگر، باید از روش مسیردهی زیر استفاده کرد:
/_content/PackageId/MyImage.png
- content_ مسیر آغاز کننده‌ی دسترسی به منابع یک کتابخانه‌ی کامپوننت‌های Blazor است.
- PackageId عموما همان نام پروژه‌ی مورد استفاده‌است (نام فایل csproj مانند MyBlazorComponentLibrary). هرچند می‌توان آن‌را به صورت مجزایی در فایل csproj نیز مقدار دهی کرد.
- در این مثال MyImage.png، نام منبعی است که قرار است از آن استفاده کنیم و پیشتر در پوشه‌ی wwwroot کتابخانه، کپی شده‌است و یا حتی می‌توان زیر پوشه‌هایی را نیز در اینجا ایجاد و از آن‌ها استفاده کرد؛ مانند:
/_content/MyBlazorComponentLibrary/scripts/HelloWorld.js
همچنین باید دقت داشت که مداخل فایل‌های اسکریپتی کتابخانه را مانند:
<script src="_content/MyBlazorComponentLibrary/exampleJsInterop.js"></script>
در برنامه‌های Blazor WASM باید به فایل wwwroot/index.html و در برنامه‌های Blazor Server به فایل Pages/_Host.cshtml افزود و این مداخل باید پیش از یکی از فایل‌های framework/blazor.server.js_ و یا framework/blazor.webassembly.js_ تعریف شوند.


روش استفاده‌ی از کتابخانه‌ی نهایی تولید شده

برای استفاده‌ی از کتابخانه‌ی نهایی تولید شده یا می‌توان ارجاعی را به فایل csproj آن، به پروژه‌ی خود افزود:
<ItemGroup>
   <ProjectReference Include="..\MyBlazorComponentLibrary\MyBlazorComponentLibrary.csproj" />
</ItemGroup>
و یا می‌توان بسته‌ی نیوگت آن‌را (در صورت وجود) نصب کرد.

پس از آن، جهت سهولت استفاده‌ی از این کامپوننت‌های اشتراکی، بهتر است فضای نام آن‌ها را به فایل Imports.razor_ پروژه‌ی خود افزود؛ تا نیازی به تعریف آن‌ها در تمام کامپوننت‌های مورد استفاده نباشد.
مطالب
آموزش فایرباگ - #10 - DOM Panel
در پنل DOM توابع و متغییرهایی که در صفحه وجود دارند بصورت درختی نمایش داده می‌شوند. object‌ها و array‌ها قابل باز شدن هستند و بصورت درختی می‌توانید محتویات آن‌ها را مشاهده کنید. توابع هم بصورت لینک هستند که با کلیک برون آن ها، کد مربوط در پنل Script نمایش داده می‌شود. توجه کنید که محتویاتی که مشاهده می‌کنید برای همان لحظه ای است که پنل را باز کردید و برای مشاهده تغییرات ثانویه باید محتویات پنل را بروزرسانی کرد.

قبل از بررسی این پنل اجازه دهید نگاهی به تعریف DOM بیندازیم.

DOM چیست؟
مدل شیءگرای سند یا دام (DOM - Document Object Model) عنوان یکی از دو ساختوارۀ (architecture) اصلی است (در کنار اس‌اِی‌اکس) که بر اساس آن سندهای اکس‌ام‌ال را به اشیایی که در بردارندهٔ آن است، تجزیه نموده، و آن‌ها را به‌صورت یک ساختار درختی داده‌ها در فضای حافظه اصلی پهن می‌کند. ساختوارۀ دام، نه به زبان برنامه‌نویسی خاصّی وابستگی دارد و نه به سکّوی برنامه‌نویسی ویژه‌ای، بلکه، به منظور اجراء و پیاده‌سازی آن باید از یک زبان برنامه‌نویسی بلندتراز همچون جاوا، سی‌شارپ، جاوااسکریپت یا مشابه آن‌ها سود بجوییم. آنسوی رابط کاربر سند با مدلی شیءگرا نمایانده می‌شود. 


Options Menu
این منو با راست کلیک کردن بروی نام پنل یا کلیک کردن بروی مثلثی که روی پنل قرار دارد، نمایش داده می‌شود.

  • Show User-defined Properties
    در صورت فعال بودن، پراپرتی هایی که توسط کاربر به صفحه اضافه شده اند را نمایش می‌دهد.
  • Show User-defined Functions
    در صورت فعال بودن، توابعی که توسط کاربر به صفحه اضافه شده اند را نمایش می‌دهد.
  • Show DOM Properties
    در صورت فعال بودن، پراپرتی هایی که بصورت پیشفرض در DOM وجود دارند را نمایش می‌دهد.
  • Show DOM Functions
     در صورت فعال بودن، توابعی که بصورت پیشفرض در DOM وجود دارند را نمایش می‌دهد.
  • Show DOM Constants
    در صورت فعال بودن، const هایی که بصورت پیشفرض در DOM وجود دارند را نمایش می‌دهد.
  •  Show Inline Event Handlers
    در صورت فعال بودن، رویدادهایی که بصورت خطی در تگ‌ها تعریف شده اند را نمایش می‌دهد.
  • Show Closures
    در صورت فعال بودن، Closure‌ها را نمایش می‌دهد.
  • Show Own Properties Only
    در صورت فعال بودن، فقط پراپرتی هایی که بروی خود شئ تعریف شده اند را نمایش می‌دهد.
  • Show Enumerable Properties Only
    در صورت فعال بودن، فقط پراپرتی‌های شمارشی را نمایش می‌دهد.
  • Refresh
    محتویات پنل را بروزرسانی می‌کند.


Property Path
این قسمت در بالاترین بخش پنل قرار دارد و وظیفه‌ی آن نمایش مسیر شئ از خود شئ تا window است.
همچنین با راست کلیک کردن بروی این قسمت دو گزینه نمایش داده می‌شود. Refresh برای بروزسازی آدرس نمایش داده شده و Use in Command Line هم برای استفاده از شئ در خط فرمان است. پس از راست کلیک کردن بروی یک شئ و انتخاب گزینه‌ی Use in Command Line فایرباگ تمرکز برنامه را به خط فرمان منتقل می‌کند و شئ را تحت متغییری به نام $p در خط فرمان کپی می‌کند.


رنگ ها
برای مشخص کردن نوع متغییرهای این پنل، فایرباگ برای هر نوع متغییر از یک رنگ استفاده می‌کند.
اشیاء
، اشیاء DOM ، توابع Getter ، توابع تعریفی کاربر ، توابع DOM ، توابع Constructor ، پراپرتی‌های Read-only 


Auto-Completion
مشابه پنل‌های Console, CSS, HTML در این پنل هم امکان اعمال تغییرات همراه با قابلیت تکمیل خودکار وجود دارد.


localStorage
در HTML5 سیستمی برای ذخیره مقادیر در سمت کاربر، به نام localStorage معرفی شد. در این پنل می‌توانید محتویات آن را بررسی/ویرایش کنید. برای کار با توابع آن هم می‌توانید از پنل Console استفاده کنید. ( همچنین می‌توانید از پنل Console بصورت Popup در این پنل و پنل‌های دیگر هم استفاده کنید. به تصویر زیر توجه فرمایید. )
توجه کنید که برای مشاهده‌ی این شئ، باید گزینه‌ی Show DOM Properties فعال باشد و همیچنین در Property Path، شئ window فعال باشد.

Breakpoint Column
شما می‌توانید با کلیک بروی ستون سمت چپ پراپرتی ها، آن پراپرتی را تحت نظر گرفته و در صورت تغییر یافتن مقدار آن پراپرتی، کنترل روند اجرای برنامه از همان نقطه را بدست بگیرید. به این صورت که زمانی که کدی پراپرتی موردنظر را تغییر دهد، پنل Script روند اجرای کد را در همان قسمت متوقف می‌کند.
( ممکن است فایرباگ بصورت خودکار به پنل Script سوئیچ نکند و بعد از متوقف شدن برنامه هم اگر به پنل Script سوئیچ کنید نتیجه را نبینید. پس بهتر است قبل از تغییر یافتن پراپرتی مورد نظر و بعد از قرار دادن Breakpoint به پنل Script بروید. )


Context Menu
با راست کلیک کردن در قسمت‌های مختلف پنل، منوهای متفاوتی را خواهید دید. همچنین با راست کلیک کردن بروی مقادیر پراپرتی ها، منوی متناسب با آن مقدار را خواهید دید. مثلا اگر بروی یک تگ HTML در این پنل راست کلیک کنید، منویی که خواهید دید همان منویی است که در پنل HTML مشاهده می‌کردید.

 گزینه Context
توضیحات
Copy Name
Property List نام پراپرتی را در حافظه کپی می‌کند.
Copy Path Property List آدرس پراپرتی را در حافظه کپی می‌کند.
Copy Value
String and Number values محتوای پراپرتی را در حافظه کپی می‌کند.
Edit Property... Property List ( پراپرتی و توابع کاربر )
پراپرتی را به حالت ویرایش می‌آورد.
Delete Property Property List ( پراپرتی و توابع کاربر ) پراپرتی را حذف می‌کند.
Break On Property Change Property List ( پراپرتی و توابع کاربر ) مشابه پاراگرف قبلی.
Refresh Property List, Property Path محتویات پنل را بروزرسانی می‌کند.

برای توابع هم دو منوی اضافی وجود دارد:

    • ‪ Log Calls to "<function name>"
      فراخوانی‌های تابع مورد نظر را Log می‌کند. ( برای توضیحات بیشتر دستور monitor که از توابع خط فرمان است را ملاحظه بفرمایید. )
    • Copy Function
      نام و بنده‌ی تابع را در حافظه کپی می‌کند.
مطالب
کارهایی جهت بالابردن کارآیی Entity Framework #1
امروزه اهمیت استفاده از  Entity Framework بر هیچ کسی پوشیده نیست؛ اما در صورتی که به مفاهیم ابتدایی آن آشنایی نداشته باشید ممکن است در دام هایی بیفتید که استفاده از آن کم رنگ شود. در زیر به توصیه‌هایی جهت بالابردن کارآیی برنامه‌های مبتنی بر EF اشاره خواهیم کرد.
  • تنها دریافت رکوردهای مورد نیاز

EF راهی برای کار با اشیاء POCO، بدون آگاهی از مقادیرشان می‌باشد. اما هنگام فرآیند دریافت و یا به روزرسانی مقادیر این اشیاء از بانک اطلاعاتی، رفت و برگشت هایی انجام می‌شود که اطلاع از آنها بسیار حیاتی و ضروری است. به این فرآیند materiallization می‌گویند.
string city = "New York";
List<School> schools = db.Schools.ToList();
List<School> newYorkSchools = schools.Where(s => s.City == city).ToList();

در کد بالا ابتدا کلیه ردیف‌های جدول از دیتابیس به حافظه منتقل می‌شود و سپس برروی آنها کوئری مورد نظر اعمال می‌گردد که بشدت می‌تواند برای یک برنامه - خصوصا برنامه وب - به‌دلیل دریافت کلیه‌ی ردیف‌های جدول بسیار مخرب باشد. کوئری فوق را می‌توان به صورت زیر اصلاح کرد:

List<School> newYorkSchools = db.Schools.Where(s => s.City == city).ToList();
یا
IQueryable<School> schools = db.Schools;
List<School> newYorkSchools = schools.Where(s => s.City == city).ToList();
  • حداقل رفت و برگشت به دیتابیس

کد زیر را در نظر بگیرید:

string city = "New York";
List<School> schools = db.Schools.Where(s => s.City == city).ToList();
var sb = new StringBuilder();
foreach(var school in schools)
{
    sb.Append(school.Name);
    sb.Append(": ");
    sb.Append(school.Pupils.Count);
    sb.Append(Environment.NewLine);
}

هدف تکه کد بالا این است که تعداد دانش آموزان مدرسه‌های واقع در شهر New York را بدست آورد.

توجه داشته باشید:

  • یک مدرسه می‌تواند چندین دانش آموز داشته باشد (وجود رابطه یک به چند)
  • LazyLoading فعال است
  • تعداد مدرسه‌های شهر نیویورک 200 عدد می‌باشد

اگر کوئری بالا را به‌وسیله‌ی یک پروفایلر بررسی نمایید، متوجه خواهید شد 1 + 200 رفت و برگشت به دیتابیس صورت گرفته است که به "N+1 select problem" معروف است. 1 مرتبه جهت دریافت لیست مدرسه‌های شهر نیویورک و 200 مرتبه جهت دریافت تعداد دانش آموزان هر مدرسه.

بدلیل فعال بودن Lazy Loading، زمانیکه موجودیتی فراخوانی می‌شود، سایر موجودیت‌های وابسته به آن، زمانی از دیتابیس فراخوانی خواهند شد که به آن‌ها دسترسی پیدا کنید. در حلقه‌ی foreach هم به ازای هر مدرسه (200 مدرسه) شهر نیویورک یک رفت و برگشت انجام می‌شود.

اما راه حل در این مورد خاص استفاده از Eager Loading است. خط دوم کد را بصورت زیر تغییر دهید:

List<School> schools = db.Schools
    .Where(s => s.City == city)
    .Include(x => x.Pupils)
    .ToList();

حال با یک رفت و برگشت، همراه هر مدرسه اطلاعات مربوط به دانش آموزان وابسته‌ی آن نیز در دسترس خواهد بود.

  • تنها استفاده از ستون‌های مورد نیاز

فرض کنید قصد دارید نام و نام خانوادگی دانش آموزان یک مدرسه را بدست آورید.

int schoolId = 1;

List<Pupil> pupils = db.Pupils
    .Where(p => p.SchoolId == schoolId)
    .ToList();

foreach(var pupil in pupils)
{
    textBox_Output.Text += pupil.FirstName + " " + pupil.LastName;
    textBox_Output.Text += Environment.NewLine;
}
کد بالا تمام ستون‌های یک جدول را همراه با ستون‌های نام و نام خانوادگی جدول مربوطه را از دیتابیس فراخوانی می‌کند که باعث بروز 2 مشکل زیر می‌گردد:
  1. انتقال اطلاعات بلا استفاده که ممکن است باعث کاهش کارآیی Sql Server I/O و شبکه و اشغال حافظه‌ی کلاینت گردد.
  2. کاهش کارآیی ایندکس گذاری. فرض کنید برروی جدول دانش آموزان ایندکسی شامل 2 ستون نام و نام خانوادگی تعریف کرده‌اید. با انتخاب تمام ستونهای جدول توسط خط دوم (select * from...) به کارآیی ایندکس گذاری برروی این جدول آسیب زده‌اید. توضیح بیشتر در اینجا مطرح شده است.

اما راه حل:

var pupils = db.Pupils
    .Where(p => p.SchoolId == schoolId)
    .Select(x => new { x.FirstName, x.LastName })
    .ToList();
  • عدم تطابق نوع ستون با نوع خصیصه مدل

فرض کنید نوع ستون جدول دانش آموزان (VARCHAR(20 است و خصیصه کدپستی مدل دانش آموز مانند زیر تعریف شده است:

public string PostalZipCode { get; set; }

انتخاب نوع داده و تطابق نوع داده مدل با ستون جدول دارای اهمیت زیادی است و در صورت عدم رعایت، باعث کاهش کارآیی شدید می‌گردد. در کد زیر قصد دارید لیست نام و نام خانوادگی دانش آموزانی را که کدپستی آنها 90210 می‌باشد، بدست بیاورید.

string zipCode = "90210";
var pupils = db.Pupils
    .Where(p => p.PostalZipCode == zipCode)
    .Select(x => new {x.FirstName, x.LastName})
    .ToList();
کوئری بالا منجر به تولید SQL زیر می‌گردد: (نوع پارامتر ارسالی NVARCHAR است در حالی که ستون از نوع VARCHAR)

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

همانطور که در شکل بالا مشخص است عملیات index scan از سایر عملیات‌ها پرهزینه‌تر است. حال به بررسی علت به‌وجود آمدن این عملیات پرهزینه خواهیم پرداخت.

Index Scan زمانی رخ می‌دهد که اس کیو ال سرور مجبور است هر صفحه‌ی از ایندکس را بخواند و شرایط را (کدپستی برابر 90210) اعمال نماید و نتیجه را برگرداند. Index Scan بسیار هزینه بر است، چون اس کیو ال سرور، کل ایندکس را بررسی می‌نماید. نقطه‌ی مقابل و بهینه‌ی آن، Index Seek است که اس کیو ال سرور به صفحه‌ی مورد نظر ایندکسی که به شرایط نزدیک‌تر است، منتقل می‌گردد.

خب چرا اس کیو ال سرور Index Scan را بجای Index Seek انتخاب کرده است؟!

اشکالی در قسمت سمت چپ شکل بالا که به رنگ قرمز نمایش داده شده است، وجود دارد:

Type conversion: Seek Plan for CONVERT_IMPLICIT(nvarchar(20), [Extent1].[PostalZipCode],0)=[@p__linq__0]
[Extent1].[PostalZipCode]  بصورت غیر صریح به (NVARCHAR(20 تبدیل شده است. اما چرا؟
پارامتر کوئری تولید شده‌ی توسط EF از نوع NVARCHAR است و تبدیل نوع NVARCHAR پارامتر کدپستی، که محدوده‌ی اطلاعات بیشتری (Unicode Strings) را نسبت به نوع VARCHAR ستون دارد، به‌دلیل از دست رفتن اطلاعات امکان پذیر نیست. به‌همین جهت برای مقایسه‌ی پارامتر کدپستی با ستون VARCHAR ، اس کیو ال سرور باید هر ردیف ایندکس را از VARCHAR به NVARCHAR تبدیل نماید که منجر به Index Scan می‌شود. اما راه حل بسیار ساده این است که فقط نوع خصیصه را با ستون جدول یکسان کنید.
[Column(TypeName = "varchar")]
public string PostalZipCode { get; set; }

مطالب
3 نکته کاربردی TypeScript برای Angular
اگر چه من  این نکات را در حین کار کردن بر روی پروژه‌های انگیولار یافتم، اما همه آنها مشخصه‌های انگیولار نیستند؛ فقط کد‌های تایپ اسکریپت می‌باشند.


Eliminating the need to import interfaces 

من interface ‌ها را دوست دارم با این حال نمی‌خواهم هر بار آنها را import  کنم. تمایلی ندارم فایل‌های من بخاطر import ‌های چند خطی کثیف شوند (فقط به منظور strong typing )، اگر چه Visual Studio Code ویژگی auto-import را دارا می‌باشد. در حالت معمول به صورت زیر کار می‌کنیم :
// api.model.ts
export interface Customer {
    id: number;
    name: string;
}

export interface User {
    id: number;
    isActive: boolean;
}
و استفاده از آن  :
// using the interfaces
import { Customer, User } from './api.model'; 

export class MyComponent {
    cust: Customer; 
}
اگر به خط شماره 2 دقت کنید ، در صورتی که interface ‌های بیشتری استفاده شود، این خط بزرگتر می‌شود و کمی به‌هم ریختگی ایجاد می‌کند.

راه حل شماره 1 : استفاده از namespace 

با استفاده از namespaceها می‌توان نیاز به import فایل‌های interface را حذف کرد: 
// api.model.ts
namespace ApiModel {
    export interface Customer {
        id: number;
        name: string;
    }

    export interface User {
        id: number;
        isActive: boolean;
    }
}
و استفاده از آن :
// using the interfaces
export class MyComponent {
    cust: ApiModel.Customer; 
}
هم چنین با استفاده از namespaceها می‌توان خیلی بهتر interface‌ها را سازماندهی و گروه بندی کرد.

اجازه بدهید بگویم اگر شما فایل دیگری به نام مثلا api.v2.model.ts را داشته باشید و بخواهید interface ‌های جدیدی را به این فایل اضافه کنید، می‌توانید از همان نام namespace مشخص شده قبلی استفاده کنید:
// api.v2.model.ts
namespace ApiModel {
    export interface Order {
        id: number;
        total: number;
    }
}

برای استفاده از interface  جدیدا ایجاد شده، می‌توانید همانند مثال قبل کار کنید: ( استفاده از interface ‌ها با namespace های یکسان و فایل‌های متفاوت)
export class MyComponent {
    cust: ApiModel.Customer; 
    order: ApiModel.Order;
}

راه حل شماره 2 : استفاده از فایل‌های d

راه دیگر حذف کردن import ها، ایجاد یک فایل typescript  با پسوند d.ts. می‌باشد ( d مخفف declaration file در typescript می‌باشد). در ضمن نیازی به export کردن interface ‌ها در فایل‌های d نمی‌باشد:
// api.model.d.ts
interface Customer {
    id: number;
    name: string;
}
در زیر از Customer  بدون نیاز به import کردن استفاده شده است :
// using the interfaces of d file
export class MyComponent {
    cust: Customer; 
}

من راه حل شماره 1 را در مقابل راه حل شماره 2 پیشنهاد می‌کنم زیرا :
از فایل d معمولا برای کتابخانه‌های ثالث استفاده می‌شود.
namespace ‌ها این اجازه را به ما میدهند تا فایل‌ها را خیلی بهتر سازماندهی کنیم.
 
Making all interface properties optional  

این موضوع خیلی رایج است که شما از یک interface برای عملیات CRUD استفاده کنید. مثلا شما یک interface را به نام customer دارید که تمامی فیلد‌های آن در زمان ایجاد اجباری می‌باشند؛ اما در زمان به‌روز رسانی، همه آنها اختیاری هستند. آیا شما نیاز به دو interface برای مدیریت کردن این سناریو دارید؟ 

راه حل : استفاده از Partial 

Partial یک type است که خصوصیات یک شیء را اختیاری می‌کند. تعریف آن در فایل d پیش فرضی به نام lib.es5.d.ts قرار داده شده‌است:
// lib.es5.d.ts
type Partial<T> = {
    [P in keyof T]?: T[P];
};
چگونه می‌توان از آن استفاده کرد؟ به کدهای زیر توجه کنید: 
import { Customer } from './api.model';

export class MyComponent {
    cust: Partial<Customer>;  /

    ngOninit() {
        this.cust = { name: 'jane' };
    }
}

در کد بالا هیچ خطایی پرتاب نمی‌شود؛ به دلیل اینکه همه‌ی فیلد‌ها اختیاری شده‌اند (اگر Partial را حذف کنیم با خطا مواجه می‌شویم). 
اگر شما تعریف Partial را پیدا نکردید، می‌توانید یک فایل d را ایجاد کنید؛ مثلا با نام util.d.ts، سپس قطعه کد تعریف Partial را در آن قرار دهید.

Stop throwing me error, I know what I'm doing 

در بعضی از سناریو‌ها شما می‌خواهید به Typescript  بگویید که  "من می‌دانم دارم چکار می‌کنم لطفا اینجا بی خیال من شو".

راه حل : استفاده از ts-ignore comment@ 

از نگارش 2.6 به بعد Typescript، شما می‌توانید این کار را به منظور مانع شدن از ایجاد خطا  با استفاده از کامنت ts-ignore@  انجام دهید. 
برای مثال در کد زیر، Typescript خطای Unreachable code detected را پرتاب خواهد کرد:
if (false) {
    console.log('x');
}

شما می‌توانید با استفاده از کامنت ts-ignore@ مانع از پرتاب خطا شوید :
if (false) {
    // @ts-ignore
    console.log('x');
}

البته من به شما پیشنهاد می‌کنم که همیشه خطاهاتون را برطرف کنید؛ قبل از اینکه آن‌ها را ignore کنید. 
مطالب
بررسی اینترفیس ICommand در WPF
مدتی هست که مشغول مطالعه و یادگیری WPF از طریق مطالب سایت هستم؛ به همین خاطر تصمیم گرفتم مطلبی را حول محور اینترفیس ICommnad  گردآوری کنم و در اختیار کاربران سایت قرار دهم.

سرفصل‌های این مطلب :
• Command چیست
• اینترفیس ICommand چیست 
• چرا اینترفیس ICommand
• ایجاد UI مورد نیاز 
• چگونگی استفاده از ICommand 
• استفاده از INotifyPropertyChanged

Command چیست ؟
در برنامه نویسی WPF به هر کلاسی که اینترفیس ICommand را پیاده سازی کند، اصطلاحا Commnad گوییم. تفاوت کوچکی بین یک Event و Command وجود دارد. رخداد‌ها برای کنترل‌های UI ساخته و تخصیص داده می‌شوند؛ اما Command‌ها انتزاعی‌تر هستند و تمرکز آنها بر روی نحوه‌ی انجام کارها می‌باشد.
برای تعاملات در برنامه‌ها از Commandها و Event‌ها استفاده می‌کنیم. ما در WPF دو روش برای تعامل با UI داریم:
1- استفاده از Event‌ها و نوشتن کد‌های مورد نیاز در بخش CodeBehind (رعایت نکردن الگوی MVVM).
WPF تعداد زیادی RoutedEvent پیش ساخته (Built In) دارد که از آنها می‌توان در این روش استفاده کرد. 
2- استفاده از Command و درگیر کردن کدهای اجرایی نوشته شده در ViewModel با استفاده از Command ها.
در زمان استفاده از الگوی MVVM مجاز به نوشتن کد در بخش CodeBehind نیستیم. بنابراین از سیستم رخداد‌های طراحی شده‌ی در WPF که RoutedEvent می‌باشد، نمی‌توان استفاده کرد. به این خاطر که رخداد‌ها در ViewModel قابل دسترسی نمی‌باشد.

اینترفیس ICommand:
این اینترفیس سه عضو دارد که آن‌ها را در جدول زیر مشاهده می‌کنید:

نام عضو

توضیحات

Bool CanExecute(object parameter)

این تابع پارامتری از نوع object را دریافت می‌کند و یک مقدار bool را به خروجی تابع می‌فرستد. اگر مقدار خروجی متد، true  باشدcommand  اجرا خواهد شد و در غیر اینصورت اتفاقی رخ نخواهد داد. اغلب ازDelegate  ها به عنوان پارامتر این تابع استفاده می‌شود؛Delegate های پیش ساخته‌ای همچون Action,Predicate,Func

Event EventHandler CanExecuteChanged

این رویداد برای آگاه سازی UI که به Command متصل است، استفاده می‌شود .بر اساس خروجی تابع CanExecute، این رویداد اتفاق می‌افتد.

Void Execute(Object parameter)

این متد کار اصلی را در Command‌ها انجام می‌دهد. این متد تنها زمانی اجرا می‌شود که متدCanExecute  مقدار true را بازگرداند. این تابع پارامتری را از نوع object دریافت می‌کند، اما عموما ما یکDelegate  را به آن ارسال می‌کنیم. Delegate ارجاعی را به متدی، در خود نگاه می‌دارد که انتظار داریم در صورت اجرایcommand ، اجرا شود.


چرا اینترفیس ICommand :
هسته‌ی اصلی Command‌ها در WPF، اینترفیس ICommand می‌باشد. این اینترفیس به‌صورت گسترده‌ای در الگوی MVVM و Prism  استفاده شده است و استفاده‌ی از آن محدود به MVVM نمی‌باشد. تعداد زیادی Commnad بصورت پیش ساخته وجود دارند که این اینترفیس را پیاده سازی کرده‌اند .کلاس پایه RoutedCommand اینترفیس ICommand را پیاده سازی کرده است و WPF فرمان‌های زیر را فراهم کرده است:
• MediaCommnads
• ApplicationCommnads
• NavigationCommands
• ComponentCommnads
• EditingCommnads
که همگی از کلاس RoutedCommand استفاده کرده‌اند.
در این مطلب به دنبال ایجاد برنامه‌ای هستیم که حاصل جمع مفدار دو Textbox را پس از فشردن کلید جمع در یک textblock نمایش دهد.

ساخت UI مورد نیاز :
گام اول : 
با اجرای ویژوال استودیو، برنامه‌ای را با نام ICommnadSample ایجاد کنید. ساختار پروژه به شکل زیر است:
همانطور که می‌بینید View و ViewModel و در نهایت Command‌ها در پوشه‌های مجزایی ساماندهی شده‌اند.

گام دوم:
ابتدا قالب گرافیکی را مشخص می‌کنیم. در پوشه‌ی Views یک UserControl را به نام CalculatorView.xaml ایجاد کرده و کد زیر را در آن نوشتیم:
<Grid DataContext="{Binding Source={StaticResource calculatorVM}}" Background="#FFCCCC">
        <Grid.RowDefinitions>
            <RowDefinition Height="80"/>
            <RowDefinition/>
            <RowDefinition Height="80"/>
            <RowDefinition Height="44"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="4" FontSize="25"
               VerticalAlignment="Top" HorizontalAlignment="Center" Foreground="Blue" Content="ICommand Sample"/>
        <Label Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" 
               Margin="10,0,0,0" VerticalAlignment="Bottom" FontSize="20"  Content="First Input"/>
        <Label Grid.Row="0" Grid.Column="2" Grid.ColumnSpan="2" 
               Margin="10,0,0,0" VerticalAlignment="Bottom" FontSize="20"  Content="Second Input"/>

        <TextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Margin="10,0,0,0" FontSize="20" 
                 HorizontalAlignment="Left" Height="30"  Width="150" TextAlignment="Center" Text="{Binding FirstValue, Mode=TwoWay}"/>
        <TextBox Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2" Margin="10,0,0,0" FontSize="20"
                 HorizontalAlignment="Left"  Height="30" Width="150" TextAlignment="Center" Text="{Binding SecondValue, Mode=TwoWay}"/>

        <Rectangle Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="4" Fill="LightBlue"/>
        <Button Grid.Row="2" Grid.Column="0" Content="+"  Margin="10,0,0,0" HorizontalAlignment="Left" Height="50" Width="50" FontSize="30" Command="{Binding AddCommand}"/>
        
        <Label Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" FontSize="25" Margin="10,0,0,0" HorizontalAlignment="Left" Height="50"  Content="Result : "/>
        <TextBlock Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="2" FontSize="20" Margin="10,0,0,0" Background="BlanchedAlmond"
                   TextAlignment="Center"  HorizontalAlignment="Left" Height="36" Width="150" Text="{Binding Output}"/>
    </Grid>
برای استفاده از این UserControl در پنجره‌ی اصلی برنامه (فایل MainWindows.Xaml) به شکل زیر عمل می‌کنیم:
ابتدا فضای نام View را به فایل MainWindows.xaml اضافه می‌کنیم :
   xmlns:myview="clr-namespace:ICommnadSample.Views"
ایجاد تگ برای استفاده از View تولید شده در  Grid اصلی برنامه :
<Grid>
        <myview:CalculatorView/>
</Grid>

گام سوم :
همانطور که مشاهده می‌کنید، کنترل‌هایی که در عملیات انقیاد داده‌ها (DataBinding) شرکت می‌کنند، از طریق خاصیت Binding و معرفی خصوصیت مورد نظر مشخص می‌شوند.
برای این منظور در پوشه‌ی ViewModels و به کلاس CalculatorViewModel سه خصوصیت به‌همراه فیلد خصوصی، به شکل زیر اضافه می‌کنیم:
private double firstValue; 
private double secondValue;
private double output;
public double FirstValue
        {
            get { return firstValue; }
            set
            {
                firstValue = value;
                OnPropertyChanged("FirstValue");
            }
        }
        public double SecondValue
        {
            get { return secondValue; }
            set
            {
                secondValue = value;
                OnPropertyChanged("SecondValue");
            }
        }
        public double Output
        {
            get { return output; }
            set
            {
                output = value;
                OnPropertyChanged("Output");
            }
        }

چگونگی استفاده‌ی از اینترفیس ICommand :
برای ایجاد ارتباط بین Command ‌ها و UI می‌بایست اینترفیس ICommand توسط کلاس مورد نظر ما پیاده سازی شود. در ابتدا کلاسی با عنوان PlusCommnad  ایجاد و از اینترفیس مورد نظر ارث بری می‌کنیم.
هدف ما شبیه سازی رویداد کلیک دکمه‌ی موجود در صفحه با استفاده از Command می‌باشد.

گام چهارم:
پس از پیاده سازی اینترفیس لازم است تا کمی تغییر در بدنه متد‌ها ایجاد کنیم:
public class PlusCommand : ICommand
{
    private CalculatorViewModel calculatorViewModel;
    public PlusCommand(CalculatorViewModel vm)
    {
        calculatorViewModel = vm;
    }
    public bool CanExecute(object parameter)
    {
        return true;
    }
    public void Execute(object parameter)
    {
        calculatorViewModel.Add();
    }
    public event EventHandler CanExecuteChanged;
}
همانطور که می‌بینید در ابتدا فیلدی از جنس کلاس CalculatorViewModel ایجاد و از طریق سازنده‌ی کلاس آن را مقدار دهی کردیم (قصد داریم نمونه‌ای از ViewModel مورد نظر را به این کلاس ارسال کنیم).
در ادامه بصورت دستی (Hard Code) مقدار بازگردانده شده را برای تابع CanExecute به مقدار true  تغییر دادیم و متد تابع Execute را به شکلی تغییر دادیم تا تابع Add را در CalculatorViewModel، اجرا کند.

گام پنجم:
از کلاس PlusCommand در CalculatorViewModel، یک شیء ساخته و در سازنده‌ی CalculatorViewModel آن را مقدار دهی می‌کنیم: 
        private PlusCommand plusCommand;
        public CalculatorViewModel()
        {
            plusCommand = new PlusCommand(this);
        }

گام ششم:
در فایل CalculatorView ارجاعی را به فضای نام کلاس CalculatorViewModel ایجاد می‌کنیم :
   xmlns:vm="clr-namespace:ICommnadSample.ViewModels"
پس از اضافه کردن فضای نام، از تگ UserControl.Resource برای رجیستر کردن CalculatorViewModel با کلید calculatorVM جهت مشخص کردن منبع داده استفاده کردیم.
 <UserControl.Resources>
        <vm:CalculatorViewModel x:Key="calculatorVM" />
    </UserControl.Resources>

گام هفتم:
اضافه کردن تابع Add در CalculatorViewModel برای عملیات جمع :
public void Add()
{
   Output = firstValue + secondValue;
}

گام هشتم:
تعریف یک Command  برای عملیات جمع به نام AddCommand. این همان خصوصیتی است که باید بجای رویداد کلیک دکمه از طریق خاصیت Command موجود در کنترل و ویژگی Binding به کنترل متصل شود.
  public ICommand AddCommand {
            get
            {
                return plusCommand;
            }
        }

نحوه‌ی استفاده:
   Command="{Binding AddCommand}"
 
گام نهم :
برای تکمیل عملیات انقیاد داده‌ها، کلاسی به نام ViewModelBase تعریف شده است. این کلاس از اینترفیس INotifyPropertyChange ارث بری کرده و اعضای این کلاس را پیاده سازی کرده است.
  public class ViewModelBase:INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
پیاده سازی این اینترفیس سبب می‌شود تا کلاس‌های ViewModel ایی که احتیاج به این اینترفیس برای عملیات انقیاد داده‌ها دارند، تنها با ارث بری، از این ظرفیت استفاده کنند و نیازی به پیاده سازی این اینترفیس در هر کلاس نباشد.

گام دهم:
ارث بری کلاس CalculatorViewModel از کلاس ViewModelBase:
   public class CalculatorViewModel : ViewModelBase
در این مرحله هر کنترلی را که قصد داریم با تغییر منبع داده بروز شود و یا با تغییر وضعیتش منبع داده تغییر کند، اعلام می‌کنیم:
   OnPropertyChanged("FirstValue");
برای هر سه خصوصیت ViewModel کد زیر را در بلاک Set تکرار می‌کنیم (توجه شود که پارامتر ارسالی باید نام پراپرتی مورد نظر باشد)
کد کامل کلاس CalculatorViewModel به شکل زیر است:
public class CalculatorViewModel : ViewModelBase
    {
        private double firstValue;
        private double secondValue;
        private double output;
        private PlusCommand plusCommand;
        public CalculatorViewModel()
        {
            plusCommand = new PlusCommand(this);
        }

        public double FirstValue
        {
            get { return firstValue; }

            set
            {
                firstValue = value;
                OnPropertyChanged("FirstValue");
            }
        }
        public double SecondValue
        {
            get { return secondValue; }
            set
            {
                secondValue = value;
                OnPropertyChanged("SecondValue");
            }
        }
        public double Output
        {

            get { return output; }

            set
            {
                output = value;
                OnPropertyChanged("Output");
            }
        }


        public ICommand AddCommand
        {
            get
            {
                return plusCommand;
            }
        }

        internal void Add()
        {
            Output = firstValue + secondValue;
        }
    }


حال می‌توانید برنامه را اجرا و تست کنید:



برای درک بهتر عملیات انقیاد دادها می‌توانید به این مقاله مراجعه کنید.

مطالب
تعیین شماره نگارش IE مورد استفاده در Web Browser Control
Web Browser Control دات نت و کلا ویندوز (قابل استفاده در WPF، WinForms و یا حتی CHM Viewer توکار ویندوز) بر پایه IE نصب شده بر روی سیستم عمل می‌کند.
سؤال مهم!
این کنترل از چه نگارشی از IE به صورت پیش فرض برای پردازش HTML دریافتی استفاده می‌کند؟
پاسخ: از موتور پردازشی IE 7.0 !
و تفاوتی هم نمی‌کند که در حال حاضر IE 8.0, 9.0 و یا 10 بر روی سیستم شما نصب است؛ در هر حالت به IE 7.0 مقید شده است. علت را هم این مساله عنوان کرده‌اند که اگر این شماره نگارش را تغییر دهیم، ممکن است برنامه‌های قدیمی دیگر درست نمایش داده نشوند.

نحوه تغییر موتور پردازشی Web Browser Control

متاسفانه بجز ویرایش رجیستری ویندوز، راه حل دیگری برای تغییر موتور پردازشی پیش فرض Web Browser Control وجود ندارد.
بسته به نوع سیستم عامل نصب شده، یکی (حالت 32 بیتی) و یا هر دوی (حالت 64 بیتی) مداخل زیر باید اندکی تغییر کنند:
 32 bit -> HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION  
64 bit -> HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION
در هر دو حالت یک کلید جدید DWORD را ایجاد و نام کلید را دقیقا مساوی نام فایل exe برنامه خود قرار دهید. مقدار آن یکی از موارد ذیل می‌تواند باشد:
 Force IE10 -> 10001 (0x2711)
IE10 considering !DOCTYPE directives -> 10000 (0x02710)
Force IE9 -> 9999 (0x270F)
IE9 considering !DOCTYPE directives -> 9000 (0x2328)
Force IE8 -> 8888 (0x22B8)
IE8 considering !DOCTYPE directives  -> 8000 (0x1F40)
Force IE7 -> 7000 (0x1B58)
برای نمونه چند برنامه تنظیم شده در اینجا را ملاحظه می‌کنید:


در این لیست hh.exe را هم ملاحظه می‌کنید که همان CHM Viewer توکار ویندوز است و این مورد نیز در صورت عدم تنظیم فوق، از IE 7.0 استفاده خواهد کرد.

یک مثال: تنظیمات IIS بر روی ویندوز سرور 2003 جهت استفاده از IE 8.0
 Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\MAIN\FeatureControl\FEATURE_BROWSER_EMULATION]
"w3wp.exe"=dword:00001f40

نظرات مطالب
Url Routing در ASP.Net WebForms
فایل فیزیکی وجود نداره پسوندم برای جستجو تو گوگل اضافه کردم. تنظیمان مورد نظرم رو اضافه کردم  در اربطه handler بیشترم لطفا توضیح بدین ممنون میشم
stackoverflow
 از توضیحات بالام استفاده کردم ولی جوابی نگرفتم
نظرات مطالب
استفاده از pjax بجای ajax در ASP.NET MVC
مراجعه کنید به توضیحات قسمت «ب) تغییر فایل ViewStart برنامه ». اگر Layout یک View ذکر نشود، اطلاعات آن‌را از ViewStart دریافت می‌کند. اگر آن‌را صریحا ذکر کنید، همان کاری که در ViewStart برای تشخیص هدر ["Request.Headers["X-PJAX انجام شده، در این حالت باید به صورت دستی انجام و اضافه شود.
نظرات مطالب
EF Code First #11
{شما باید بتوانید یک Repository بسازید که حتی به عنوان محل ذخیره سازی از یک فایل Text استفاده کند} کاملا موافقم. و این همون چیزیه که ازش بعنوان لایه سرویس یاد کردم. توضیحات کامل رو تو کامنت های پایین تر دادم.
فکر کنم اختلاف رو نامگذاری ها و برداشت متفاوتی که از تعاریف داریم، باشه.
مطالب
توسعه برنامه‌های Cross Platform با Xamarin Forms & Bit Framework - قسمت هفدهم
در قسمت قبل بحث Style و Font را بررسی کردیم. در این قسمت قصد بررسی Animationها را داریم. Animation خود دارای دو قسمت است:
1- استفاده از Xamanimation 
2- استفاده از Lottie
Xamanimation به شما کمک می‌کند تا در Xaml، انیمیشن‌های خود را تعریف کنید. پس از نصب Package مربوطه، می‌توانید مثال زیر را تست کنید:
<Button
    x:Name="DeleteButton"
    BackgroundColor="Orange"
    Text="Delete">
    <Button.Triggers>
        <EventTrigger Event="Clicked">
            <bitView:SetPropertyAction Property="BackgroundColor" Value="Red" />
            <xamAnimation:BeginAnimation>
                <xamAnimation:BeginAnimation.Animation>
                    <xamAnimation:ColorAnimation
                        Target="{x:Reference DeleteButton}"
                        ToColor="Orange"
                        Duration="1000" />
                </xamAnimation:BeginAnimation.Animation>
            </xamAnimation:BeginAnimation>
        </EventTrigger>
    </Button.Triggers>
</Button>
در این مثال یک دکمه داریم که وقتی روی آن Click می‌کنیم، EventTrigger مربوطه اجرا می‌شود و ابتدا با کمک SetPropertyAction مقدار BackgroundColor دکمه روی Red تعیین می‌شود. سپس با Animation، از رنگ Red به Orange می‌رسیم؛ در طول 1000 میلی ثانیه. البته درست کردن Animation احتیاج به خلاقیت هم دارد(!) و این مثال فقط جنبه‌ی تکنیکی ماجرا را به شما توضیح می‌دهد. برای مشاهده مثال‌های بیشتر به سایت مربوطه مراجعه کنید.

در برخی مواقع Animationها به سادگی تغییر رنگ و Opacity و موقعیت اشیاء نیستند؛ اگر چه با ترکیب کردن همانها هم می‌توان کلی کارهای جالب کرد. برای انیمیشن‌های پیچیده‌تر می‌شود از Adobe After Effects استفاده کرد. پس از ساخت انیمیشن مربوطه، با استفاده از Lottie انیمیشن به یک فایل JSON تبدیل می‌شود. دقت کنید که Animationهای After Effects به صورت فیلم و Gif نیستند، بلکه در آنها توصیف یک Animation ذخیره می‌شود که این یک نقطه قدرت After Effects است. در سایت Lottiefiles می توانید تعداد زیادی از این JSON‌های آماده را دانلود کنید.
برای شروع ابتدا نسخه 2.6.3 پکیج  Com.Airbnb.Xamarin.Forms.Lottie را روی پروژه نصب می‌کنیم. ما برای تست، از این JSON استفاده کرده‌ایم و آن را در مسیرهای زیر قرار داده‌ایم:
XamApp.Android/Assets/Animations/LottieLogo1.json 
XamApp.UWP/Assets/Animations/LottieLogo1.json 
XamApp.iOS/Assets/Animations/LottieLogo1.json 
البته همانند فونت‌ها، برای این که یک فایل را سه بار در سورس کنترلر کپی نکنیم، از روش Add as link استفاده کرده‌ایم.
سپس از کد زیر برای نمایش فایل مربوطه استفاده می‌کنیم:
<lottie:AnimationView
    Animation="{OnPlatform UWP='Assets/Animations/LottieLogo1.json',
                                   Android='Animations/LottieLogo1.json',
                                   iOS='Animations/LottieLogo1.json'}" 
    AutoPlay="True"
    HeightRequest="500"
    HorizontalOptions="Center"
    Loop="True"
    VerticalOptions="Center"
    WidthRequest="500" />
برای بررسی بهتر مثال‌ها، آخرین وضعیت XamApp را Clone/Pull کنید و در App.xaml.cs درخواست کنید که صفحه Animations را ببینید. کدها نیز در فایل AnimationsView.xaml هستند.