مطالب
بررسی تغییرات Blazor 8x - قسمت یازدهم - قالب جدید پیاده سازی اعتبارسنجی و احراز هویت - بخش اول
قالب‌های پیش‌فرض Blazor 8x، به همراه قسمت بازنویسی شده‌ی ASP.NET Core Identity برای Blazor هم هستند که در این قسمت به بررسی نحوه‌ی عملکرد آن‌ها می‌پردازیم.


معرفی قالب‌های جدید شروع پروژه‌های Blazor در دات نت 8 به همراه قسمت Identity

در قسمت دوم این سری، با قالب‌های جدید شروع پروژه‌های Blazor 8x آشنا شدیم و هدف ما در آنجا بیشتر بررسی حالت‌های مختلف رندر Blazor در دات نت 8 بود. تمام این قالب‌ها به همراه یک سوئیچ دیگر هم به نام auth-- هستند که توسط آن و با مقدار دهی Individual که به معنای Individual accounts است، می‌توان کدهای پیش‌فرض و ابتدایی Identity UI جدید را نیز به قالب در حال ایجاد، به صورت خودکار اضافه کرد؛ یعنی به صورت زیر:

اجرای قسمت‌های تعاملی برنامه بر روی سرور؛ به همراه کدهای Identity:
dotnet new blazor --interactivity Server --auth Individual

اجرای قسمت‌های تعاملی برنامه در مرورگر، توسط فناوری وب‌اسمبلی؛ به همراه کدهای Identity:
dotnet new blazor --interactivity WebAssembly --auth Individual

برای اجرای قسمت‌های تعاملی برنامه، ابتدا حالت Server فعالسازی می‌شود تا فایل‌های WebAssembly دریافت شوند، سپس فقط از WebAssembly استفاده می‌کند؛ به همراه کدهای Identity:
dotnet new blazor --interactivity Auto --auth Individual

فقط از حالت SSR یا همان static server rendering استفاده می‌شود (این نوع برنامه‌ها تعاملی نیستند)؛ به همراه کدهای Identity:
dotnet new blazor --interactivity None --auth Individual

 و یا توسط پرچم all-interactive--، که interactive render mode را در ریشه‌ی برنامه قرار می‌دهد؛ به همراه کدهای Identity:
 dotnet new blazor --all-interactive --auth Individual

یک نکته: بانک اطلاعاتی پیش‌فرض مورد استفاده‌ی در این نوع پروژه‌ها، SQLite است. برای تغییر آن می‌توانید از پرچم use-local-db-- هم استفاده کنید تا از LocalDB بجای SQLite استفاده کند.


Identity UI جدید Blazor در دات نت 8، یک بازنویسی کامل است


در نگارش‌های قبلی Blazor هم امکان افزودن Identity UI، به پروژه‌های Blazor وجود داشت (اطلاعات بیشتر)، اما ... آن پیاده سازی، کاملا مبتنی بر Razor pages بود. یعنی کاربر، برای کار با آن مجبور بود از فضای برای مثال Blazor Server خارج شده و وارد فضای جدید ASP.NET Core شود تا بتواند، Identity UI نوشته شده‌ی با صفحات cshtml. را اجرا کند و به اجزای آن دسترسی پیدا کند (یعنی عملا آن قسمت UI اعتبارسنجی، Blazor ای نبود) و پس از اینکار، مجددا به سمت برنامه‌ی Blazor هدایت شود؛ اما ... این مشکل در دات نت 8 با ارائه‌ی صفحات SSR برطرف شده‌است.
همانطور که در قسمت قبل نیز بررسی کردیم، صفحات SSR، طول عمر کوتاهی دارند و هدف آن‌ها تنها ارسال یک HTML استاتیک به مرورگر کاربر است؛ اما ... دسترسی کاملی را به HttpContext برنامه‌ی سمت سرور دارند و این دقیقا چیزی است که زیر ساخت Identity، برای کار و تامین کوکی‌های مورد نیاز خودش، احتیاج دارد. صفحات Identity UI از یک طرف از HttpContext برای نوشتن کوکی لاگین موفقیت آمیز در مرورگر کاربر استفاده می‌کنند (در این سیستم، هرجائی متدهای XyzSignInAsync وجود دارد، در پشت صحنه و در پایان کار، سبب درج یک کوکی اعتبارسنجی و احراز هویت در مرورگر کاربر نیز خواهد شد) و از طرف دیگر با استفاده از میان‌افزارهای اعتبارسنجی و احراز هویت ASP.NET Core، این کوکی‌ها را به صورت خودکار پردازش کرده و از آن‌ها جهت ساخت خودکار شیء User قابل دسترسی در این صفحات (شیء context.User.Identity@)، استفاده می‌کنند.
به همین جهت تمام صفحات Identity UI ارائه شده در Blazor 8x، از نوع SSR هستند و اگر در آن‌ها از فرمی استفاده شده، دقیقا همان فرم‌های تعاملی است که در قسمت چهارم این سری بررسی کردیم. یعنی صرفا بخاطر داشتن یک فرم، ضرورتی به استفاده‌ی از جزایر تعاملی Blazor Server و یا Blazor WASM را ندیده‌اند و اینگونه فرم‌ها را بر اساس مدل جدید فرم‌های تعاملی Blazor 8x پیاده سازی کرده‌اند. بنابراین این صفحات کاملا یکدست هستند و از ابتدا تا انتها، به صورت یکپارچه بر اساس مدل SSR کار می‌کنند (که در اصل خیلی شبیه به Razor pages یا Viewهای MVC هستند) و جزیره، جزیره‌ای، طراحی نشده‌اند.

 
روش دسترسی به HttpContext در صفحات SSR

اگر به کدهای Identity UI قالب آغازین یک پروژه که در ابتدای بحث روش تولید آن‌ها بیان شد، مراجعه کنید، استفاده از یک چنین «پارامترهای آبشاری» را می‌توان مشاهده کرد:

@code {

    [CascadingParameter]
    public HttpContext HttpContext { get; set; } = default!;
متد ()AddRazorComponents ای که در فایل Program.cs اضافه می‌شود، کار ثبت CascadingParameter ویژه‌ی فوق را به صورت زیر انجام می‌دهد که در Blazor 8x به آن یک Root-level cascading value می‌گویند:
services.TryAddCascadingValue(sp => sp.GetRequiredService<EndpointHtmlRenderer>().HttpContext);
مقادیر آبشاری برای ارسال اطلاعاتی بین درختی از کامپوننت‌ها، از یک والد به چندین فرزند که چندین لایه ذیل آن واقع شده‌‌اند، مفید است. برای مثال فرض کنید می‌خواهید اطلاعات عمومی تنظیمات یک کاربر را به چندین زیر کامپوننت، ارسال کنید. یک روش آن، ارسال شیء آن به صورت پارامتر، به تک تک آن‌ها است و راه دیگر، تعریف یک CascadingParameter است؛ شبیه به کاری که در اینجا انجام شده‌است تا دیگر نیازی نباشد تا تک تک زیر کامپوننت‌ها این شیء را به یک لایه زیریرین خود، یکی یکی منتقل کنند.

در کدهای Identity UI ارائه شده، از این CascadingParameter برای مثال جهت خروج از برنامه (HttpContext.SignOutAsync) و یا دسترسی به اطلاعات هدرهای رسید (if (HttpMethods.IsGet(HttpContext.Request.Method)))، دسترسی به سرویس‌ها (()<HttpContext.Features.Get<ITrackingConsentFeature)، تامین مقدار Cancellation Token به کمک HttpContext.RequestAborted و یا حتی در صفحه‌ی جدید Error.razor که آن نیز یک صفحه‌ی SSR است، برای دریافت HttpContext?.TraceIdentifier استفاده‌ی مستقیم شده‌است.

نکته‌ی مهم: باید به‌خاطر داشت که فقط و فقط در صفحات SSR است که می‌توان به HttpContext به نحو آبشاری فوق دسترسی یافت و همانطور که در قسمت قبل نیز بررسی شد، سایر حالات رندر Blazor از دسترسی به آن، پشتیبانی نمی‌کنند و اگر چنین پارامتری را تنظیم کردید، نال دریافت می‌کنید.


بررسی تفاوت‌های تنظیمات ابتدایی قالب جدید Identity UI در Blazor 8x با نگارش‌های قبلی آن

مطالب و نکات مرتبط با قالب قبلی را در مطلب «Blazor 5x - قسمت 22 - احراز هویت و اعتبارسنجی کاربران Blazor Server - بخش 2 - ورود به سیستم و خروج از آن» می‌توانید مشاهده کنید.

در قسمت سوم این سری، روش ارتقاء یک برنامه‌ی قدیمی Blazor Server را به نگارش 8x آن بررسی کردیم و یکی از تغییرات مهم آن، حذف فایل‌های cshtml. ای آغاز برنامه و انتقال وظایف آن، به فایل جدید App.razor و انتقال مسیریاب Blazor به فایل جدید Routes.razor است که پیشتر در فایل App.razor نگارش‌های قبلی Blazor وجود داشت.
در این نگارش جدید، محتوای فایل Routes.razor به همراه قالب Identity UI به صورت زیر است:
<Router AppAssembly="@typeof(Program).Assembly">
    <Found Context="routeData">
        <AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(Layout.MainLayout)" />
        <FocusOnNavigate RouteData="@routeData" Selector="h1" />
    </Found>
</Router>
در نگارش‌های قبلی، این مسیریاب داخل کامپوننت CascadingAuthenticationState محصور می‌شد تا توسط آن بتوان AuthenticationState را به تمام کامپوننت‌های برنامه ارسال کرد. به این ترتیب برای مثال کامپوننت AuthorizeView، شروع به کار می‌کند و یا توسط شیء context.User می‌توان به User claims دسترسی یافت و یا به کمک ویژگی [Authorize]، دسترسی به صفحه‌ای را محدود به کاربران اعتبارسنجی شده کرد.
اما ... در اینجا با یک نگارش ساده شده سروکار داریم؛ از این جهت که برنامه‌های جدید، به همراه جزایر تعاملی هم می‌توانند باشند و باید بتوان این AuthenticationState را به آن‌ها هم ارسال کرد. به همین جهت مفهوم جدید مقادیر آبشاری سطح ریشه (Root-level cascading values) که پیشتر در این بحث معرفی شد، در اینجا برای معرفی AuthenticationState استفاده شده‌است.

در اینجا کامپوننت جدید FocusOnNavigate را هم مشاهده می‌کنید. با استفاده از این کامپوننت و براساس CSS Selector معرفی شده، پس از هدایت به یک صفحه‌ی جدید، این المان مشخص شده دارای focus خواهد شد. هدف از آن، اطلاع رسانی به screen readerها در مورد هدایت به صفحه‌ای دیگر است (برای مثال، کمک به نابیناها برای درک بهتر وضعیت جاری).

همچنین در اینجا المان NotFound را هم مشاهده نمی‌کنید. این المان فقط در برنامه‌های WASM جهت سازگاری با نگارش‌های قبلی، هنوز هم قابل استفاده‌است. جایگزین آن‌را در قسمت سوم این سری، برای برنامه‌های Blazor server در بخش «ایجاد فایل جدید Routes.razor و مدیریت سراسری خطاها و صفحات یافت نشده» آن بررسی کردیم.


روش انتقال اطلاعات سراسری اعتبارسنجی یک کاربر به کامپوننت‌ها و جزایر تعاملی واقع در صفحات SSR

مشکل! زمانیکه از ترکیب صفحات SSR و جزایر تعاملی واقع در آن استفاده می‌کنیم ... جزایر واقع در آن‌ها دیگر این مقادیر آبشاری را دریافت نمی‌کنند و این مقادیر در آن‌ها نال است. برای حل این مشکل در Blazor 8x، باید مقادیر آبشاری سطح ریشه را (Root-level cascading values) به صورت زیر در فایل Program.cs برنامه ثبت کرد:
builder.Services.AddCascadingValue(sp =>new Preferences { Theme ="Dark" });
پس از این تغییر، اکنون نه فقط صفحات SSR، بلکه جزایر واقع در آن‌ها نیز توسط ویژگی [CascadingParameter] می‌توانند به این مقدار آبشاری، دسترسی داشته باشند. به این ترتیب است که در برنامه‌های Blazor، کامپوننت‌های تعاملی هم دسترسی به اطلاعات شخص لاگین شده‌ی توسط صفحات SSR را دارند. برای مثال اگر به فایل Program.cs قالب جدید Identity UI عنوان شده مراجعه کنید، چنین سطوری در آن قابل مشاهده هستند
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddScoped<AuthenticationStateProvider, IdentityRevalidatingAuthenticationStateProvider>();
متد جدید AddCascadingAuthenticationState، فقط کار ثبت AuthenticationStateProvider برنامه را به صورت آبشاری انجام می‌دهد.
این AuthenticationStateProvider سفارشی جدید هم در فایل اختصاصی IdentityRevalidatingAuthenticationStateProvider.cs پوشه‌ی Identity قالب پروژه‌های جدید Blazor 8x که به همراه اعتبارسنجی هستند، قابل مشاهده‌است.

یا اگر به قالب‌های پروژه‌های WASM دار مراجعه کنید، تعریف به این صورت تغییر کرده‌است؛ اما مفهوم آن یکی است:
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddScoped<AuthenticationStateProvider, PersistingServerAuthenticationStateProvider>();
در این پروژه‌ها، یک AuthenticationStateProvider سفارشی دیگری در فایل PersistingServerAuthenticationStateProvider.cs ارائه شده‌است (این فایل‌ها، جزو استاندارد قالب‌های جدید Identity UI پروژه‌های Blazor 8x هستند؛ فقط کافی است، یک نمونه پروژه‌ی آزمایشی را با سوئیچ جدید auth Individual-- ایجاد کنید، تا بتوانید این فایل‌های یاد شده را مشاهده نمائید).

AuthenticationStateProviderهای سفارشی مانند کلاس‌های IdentityRevalidatingAuthenticationStateProvider و PersistingServerAuthenticationStateProvider که در این قالب‌ها موجود هستند، چون به صورت آبشاری کار تامین AuthenticationState را انجام می‌دهند، به این ترتیب می‌توان به شیء context.User.Identity@ در جزایر تعاملی نیز به سادگی دسترسی داشت.

یعنی به صورت خلاصه، یکبار قرارداد AuthenticationStateProvider عمومی (بدون هیچ نوع پیاده سازی) به صورت یک Root-level cascading value ثبت می‌شود تا در کل برنامه قابل دسترسی شود. سپس یک پیاده سازی اختصاصی از آن توسط ()<builder.Services.AddScoped<AuthenticationStateProvider, XyzProvider به برنامه معرفی می‌شود تا آن‌را تامین کند. به این ترتیب زیر ساخت امن سازی صفحات با استفاده از ویژگی attribute [Authorize]@ و یا دسترسی به اطلاعات کاربر جاری با استفاده از شیء context.User@ و یا امکان استفاده از کامپوننت AuthorizeView برای نمایش اطلاعاتی ویژه به کاربران اعتبارسنجی شده مانند صفحه‌ی Auth.razor زیر، مهیا می‌شود:
@page "/auth"

@using Microsoft.AspNetCore.Authorization

@attribute [Authorize]

<PageTitle>Auth</PageTitle>

<h1>You are authenticated</h1>

<AuthorizeView>
    Hello @context.User.Identity?.Name!
</AuthorizeView>

سؤال: چگونه یک پروژه‌ی سمت سرور، اطلاعات اعتبارسنجی خودش را با یک پروژه‌ی WASM سمت کلاینت به اشتراک می‌گذارد (برای مثال در حالت رندر Auto)؟ این انتقال اطلاعات باتوجه به یکسان نبودن محل اجرای این دو پروژه (یکی بر روی کامپیوتر سرور و دیگری بر روی مرورگر کلاینت، در کامپیوتری دیگر) چگونه انجام می‌شود؟ این مورد را در قسمت بعد، با معرفی PersistentComponentState و «فیلدهای مخفی» مرتبط با آن، بررسی می‌کنیم.
بازخوردهای پروژه‌ها
درج هر رکورد در هر صفحه
در صورتی که قصد داشته باشیم هر رکورد در یک صفحه مجزا نمایش داده شود از چه روشی باید استفاده کنیم؟
مطالب
بررسی بهبودهای پروسه‌ی Build در دات‌نت 8

در نگارش‌های اخیر دات‌نت، NET CLI. به همراه تغییرات قابل توجهی بوده‌است که در این مطلب و نظرات آن، موارد مهم این تغییرات را بررسی خواهیم کرد.

console logger بهبود یافته‌ی دات‌نت 8

یکی از تغییرات بسیار جالب توجه و مفید NET CLI. در دات‌نت 8، امکان دسترسی به خروجی لاگ‌های ساختار یافته‌ی اعمال خط فرمان آن است:

اگر پروژه‌ی خود را با استفاده از دستور dotnet build، کامپایل می‌کنید، خروجی پیش‌فرض این دستور خط فرمان، کلی و بدون ارائه‌ی جزئیات است؛ اما می‌توان آن‌را در دات‌نت 8، به شکل تصویر فوق، تغییر داد و به این مزایا رسید:

  • امکان مشاهده‌ی زمان کامپایل هر قسمت به صورت جداگانه
  • امکان مشاهده‌ی پویای درصد انجام عملیات
  • امکان مشاهده‌ی جزئیات کامپایل هر target framework به صورت مجزا
  • دسترسی به یک خروجی رنگی و زیباتر

این خروجی را که به صورت پیش‌فرض فعال نیست، می‌توان به دو صورت:

الف) سراسری و با اجرای دستور PowerShell زیر:

[Environment]::SetEnvironmentVariable("MSBUILDTERMINALLOGGER", "auto", "User")

که متغیر محیطی MSBUILDTERMINALLOGGER را به auto تنظیم می‌کند،

ب) و یا با استفاده از سوئیچ tl-- به ازای هر دستور dotnet build، به صورت جداگانه‌ای فعال کرد:

dotnet build --tl

یک نکته: این قابلیت جالب و مهم، در دات نت 9، به صورت پیش‌فرض فعال است و نیازی به تنظیم خاصی ندارد.

نظرات اشتراک‌ها
اکلیپس و TFS
اطلاع دارید چرا روی ویندوز 8 پس از نصب Eclipse و TFS Plug-in برنامه Eclipse  هنگ می‌کند و موقع کار مشکل آفرین می‌شود ؟ ظاهرا در این مقاله هم از ویندوز 8 استفاده کرده ولی من موقع کار به مشکل خوردم! 
مطالب
xamarin.android قسمت اول
در ابتدای کار تشکر و سپاس از استاد دانشمند و پر مایه‌ام جناب مهندس رضا محمد پور که از محضر پر فیض تدریسشان، بهره‌ها برده‌ام.  
هدف از این سری آشنایی با زامارین اندروید میباشدکه آشنایی با سی شارپ پیش نیاز آن میباشد و ورژن ویژوال استودیو 2017 من در حال حاضر 15.7.4 می‌باشد.
 اولین پروژه را با زامارین شروع میکنیم. طبق معمول بعد از نصب ویژوال استودیو از گزینه File گزینه New Project را انتخاب میکنیم.

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

درقسمت بعدی گزینه BlankApp را انتخاب و در قسمت Minimum Android Version که با انتخاب آن میتوانیم ورژن گوشی‌های اندروید برای استفاده از این اپلیکیشن را انتخاب نماییم. به عنوان مثال با انتخاب اندروید 4.4 برنامه ما صرفا برای گوشی‌های اندورید 4.4 به بالا جواب میدهد. بعد از تایید، پروژه باز شده که با این solution روبرو میشویم.

- قسمت Properties را اگر بازکنیم، با دو گزینه روبرو میشویم که یکی فایل android manifest هست و اگر روی properties آن کلیک و ویژگی‌هایی را انتخاب کنیم، بطور خودکار بر روی manifest تاثیر میگذارند. در قسمت‌های بعد در این رابطه جداگانه بحث خواهیم کرد.

- در قسمت Asset که به معنای منابع اندروید می‌باشد، به عنوان مثال صفحات Razor، فونت و یا صفحات HTML و یا عکس و یا ... را می‌توانیم قرار دهیم.

- در قسمت Resource که پوشه‌های آن layout ،mipmap ،values و resource.designer میباشند، در پوشه layout می‌توانیم صفحات استاندارد اندروید را شروع به طراحی کنیم. درقسمت mipmap عکس‌ها و یا فایل‌های xml ایی را که قرار است استفاده کنیم، در پروژه قرار میدهیم. در قسمت value که بیشتر برای انتخاب و تغییر تم یا استفاده از Resource‌ها (همانند Asp.mvc که استفاده میکردیم) است که البته با ساختاری متفاوت در اندروید از آن‌ها استفاده میکنیم، قرار میگیرند.

- در قسمت Resource.Designer که در مطالب بعد با آن آشنا خواهید شد، تمامی آیتم‌های انتخابی از جمله Layout ها  و عکس‌ها و... با ذخیره کردن در این قسمت دخیره میشوند که بعد با رفرنس دادن از طریق resource پروژه میتوانیم از عکس‌ها و لی‌آوت‌ها در کد نویسی استفاده کنیم.

- در انتها جهت معرفی به mainactivity می‌رسیم که یک صفحه است شامل المنت‌ها و اجزای مختلف و کاربر میتواند با آن ارتباط برقرار کند. 

  [Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)]
    public class MainActivity : AppCompatActivity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.activity_main);
        }
    }  
  همانطور که مشاهده میکنید اکتیویتی ما از AppCompatactivity ارث بری کرده، همانند ارث بری که در mvc از controller‌ها داشتیم. در قسمت Attribute که به نام اکتیویتی تعریف شده است، برچسب یا همان Lable را که در زمان اجرا به نام اکتیویتی می‌دهد، مشاهده می‌کنید. در قسمت تم، میتوان تمی را که برای آن از قبل نوشته شده‌است و به یک اکتیویتی اختصاص داد، قرار داد. در ضمن این نکته را یاد آوری کنم زمانیکه اکتیویتی ما از Appcompatactivity ارث بری میکند، انتخاب تم اجباری میباشد.

- در گزینه بعدی Mainluncher را میبینیم که تعیین کننده‌ی نقطه شروع اکتیویتی ما در بین اکتیویتی‌های دیگر می‌باشد.


بدیهی است درایور‌های مربوطه به گوشی اندروید را باید تهیه کرد که در سایت مربوط به سازنده و یا در سایت‌های دیگر میتوانید دانلود کنید.  اولین برنامه را می‌نویسیم که هدف از آن، اجرای 10 دکمه بصورت داینامیک هست و اینکه با کلیک بر روی هر کدام از دکمه‌ها، رنگ آن آبی شود.

  protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            LinearLayout ln;
            Button btn;
            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.activity_main);
            for (int i = 0; i < 5; i++)
            {
             btn = new Button(this);
             btn.Text = i.ToString();
             ln= FindViewById<LinearLayout>(Resource.Id.linearLayout1);
             btn.Click += Btn_Click;
             ln.AddView(btn);
            }
        }
        private void Btn_Click(object sender, System.EventArgs e)
        {
            Button btntest = sender as Button; 
            btntest.SetBackgroundColor(Android.Graphics.Color.Blue);
        }
    }
در قسمت تعریف دکمه منظور از This این می‌باشد که این دکمه برای اکتیویتی جاری است و Findview by id که می‌بینید، من در قسمت لی‌آوت activity main، یک LinearLayout و یک Id را قرار داده ام که البته id باید منحصر بفرد باشد و با findviewbyid آی‌دی linearlayout را که قرار داده‌ام، پیدا و استفاده کردم که کد‌های آن را در زیر میتوانید مشاهده کنید.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:minWidth="25px"
    android:minHeight="25px">
    <LinearLayout
        android:orientation="vertical"
        android:minWidth="25px"
        android:minHeight="25px"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/linearLayout1" />
</RelativeLayout>
اکنون اولین برنامه را می‌تونید تست و اجرا کنید: AppTrainng-1.zip
مطالب
توسعه اپلیکیشن‌های Node.js در ویژوال استودیو
آشنایی با Node.js

Node.js یک پلت‌فرم جاوا اسکریپتی سمت سرور است که ابتدا توسط Ryan Dahl در سال 2009 معرفی گردید. از Node.js جهت ساخت اپلیکیشن‌های مقیاس‌پذیر تحت شبکه و با زبان برنامه‌نویسی جاوا اسکریپت در سمت سرور استفاده می‌شود. Node.js در پشت صحنه از ران‌تایم V8 استفاده می‌کند؛ یعنی همان ران‌تایمی که درون مرورگر کروم استفاده شده است. Node.js در واقع یک wrapper برای این موتور V8 است؛ جهت ارائه‌ی قابلیت‌های بیشتری برای ایجاد برنامه‌های تحت شبکه. یکی از مزایای Node.js سریع بودن آن است. دلیل آن نیز این است که به صورت کامل توسط کدهای C تهیه شده است (البته می‌توانید در این آدرس benchmark مربوط به ASP.NET Core 1.0 و مقایسه‌ی آن با دیگر پلت‌فرم‌ها را نیز بررسی کنید).

چه نوع اپلیکیشن‌های را می‌توان با Node.js توسعه داد؟

  • سرور WebSocket جهت توسعه‌ی اپلیکیشن‌های بلادرنگ
  • فایل آپلودر سریع در سمت کلاینت
  • Ad Server
  • و ...
لازم به ذکر است، Node.js یک فریم‌ورک تحت وب نیست و همچنین قرار نیست یک جایگزین برای دیگر فریم‌ورک‌ها مانند ASP.NET MVC و... باشد. در حالت کلی هدف آن انجام یک‌سری اعمال سطح پائین شبکه‌ایی است. البته کتابخانه‌هایی برفراز Node.js نوشته شده‌اند که آن را تبدیل به یک وب‌فریم‌ورک خواهند کرد (+).
قبل از شروع به کار با Node.js، باید تفاوت blocking code و non-blocking code را بدانید. فرض کنید قرار است محتویات یک فایل را در خروجی نمایش دهیم. در حالت اول یعنی blocking code، باید ابتدا فایل را از فایل سیستم بخوانیم و آن را به یک متغیر انتساب دهیم و در نهایت محتویات متغیر را در خروجی چاپ کنیم. در این‌حالت تا زمانیکه فایل از فایل سیستم خوانده نشود، نمی‌توان محتویات آن را در خروجی نمایش داد. اما در حالت non-blocking فایل را از فایل سیستم می‌خوانیم و هر زمانیکه عملیات خواندن فایل به اتمام رسید می‌توانیم محتویات فایل را در خروجی نمایش دهیم. یعنی برخلاف حالت قبل، در این روش بلاک شدن کد به ازای عملیات زمانبر را نخواهیم داشت. در این روش عبارت هر زمانیکه عملیات خواندن فایل به اتمام رسید یک callback تلقی می‌شود. یعنی تا وقتیکه فایل از فایل سیستم خوانده شود، به دیگر عملیات رسیدگی خواهیم کرد و به محض اتمام خوانده شدن فایل، عملیات نمایش در خروجی را فراخوانی خواهیم کرد. در نتیجه برای حالت blocking این چنین کدی را خواهیم داشت:
var contents = fs.readFileSync('filePath');
console.log(content);
console.log('Doing something else');
همچنین برای حالت non-blocking نیز این چنین کدی را خواهیم داشت:
fs.readFile('filePath', function (err, contents) {
   console.log(contents);
});
console.log('Doing something else');

برای شروع به کار با Node.js می‌توانید با مراجعه به وب‌سایت رسمی آن، آن‌را دانلود و بر روی سیستم خود نصب کنید. بعد از نصب Node می‌توانیم از طریق command line وارد shell آن شوید و دستورات جاوا اسکریپتی خود را اجرا نمائید:


احتمالاً به این نوع استفاده‌ی از Node.js که به REPL معروف است، نیازی نداشته باشید. در واقع هدف بررسی نصب بودن ران‌تایم بر روی سیستم است. با استفاده از فرمان node نیز می‌توان یک فایل جاوا اسکریپتی را اجرا کرد. برای اینکار یک فایل با نام test.js را با محتویات زیر درون VS Code ایجاد کنید:



سپس دستور node test.js را وارد کنید:



همانطور که مشاهده می‌کنید نتیجه‌ی فایل عنوان شده، در خروجی نمایش داده شده است. در حالت کلی تمام کاری که نود انجام می‌دهد، ارائه یک Execution engine برای جاوا اسکریپت می‌باشد. 


استفاده از Node.js در ویژوال استودیو


برای کار با Node.js درون ویژوال استودیو باید ابتدا افزونه‌ی Node.js Tools را برای ویژوال استودیو نصب کنید. بعد از نصب این افزونه‌، تمپلیت Node.js در زمان ایجاد یک پروژه برای شما نمایش داده خواهد شد:

 


برای شروع، تمپلیت Blank Node.js Console Application را انتخاب کرده و بر روی OK کلیک کنید. با اینکار یک پروژه با ساختار زیر برایمان ایجاد خواهد شد: 



همانطور که ملاحظه می‌کنید، یک فایل با نام app.js درون تمپلیت ایجاد شده، موجود است. app.js در واقع نقطه‌ی شروع برنامه‌‌مان خواهد بود. همچنین دو فایل دیگر نیز با نام‌های README.md، جهت افزودن توضیحات و یک فایل با نام package.json، جهت مدیریت وابستگی‌های برنامه به پروژه اضافه شده‌اند. اکنون می‌توانیم شروع به توسعه‌ی برنامه‌ی خود درون ویژوال استودیو کنیم. همچنین می‌توانیم از قابلیت‌های debugging ویژوال استودیو نیز بهره ببریم: 



اگر مسیر پروژه‌ی ایجاد شده‌ی فوق را درون windows explorer باز کنید خواهید دید که ساختار آن شبیه به یک پروژه‌ی Node.js می‌باشد. با این تفاوت که دو آیتم دیگر همانند دیگر پروژه‌های ویژوال استودیو نیز به آن اضافه شده است که طبیعتاً می‌توانید در حین کار با سورس کنترل، از انتشار آنها صرفنظر کنید.



لازم به ذکر است پروژه‌ی ایجاد شده‌ی فوق را نیز می‌توانید همانند حالت عادی، از طریق command line و همانند پروژه‌های Node.js اجرا کنید: 

node app.js


در واقع از ویژوال استدیو می‌توانیم به عنوان یک ابزار برای دیباگ پروژه‌های Node.js استفاده کنیم. لازم به ذکر است، Visual Studio Code نیز امکان دیباگ اپلیکیشن‌های Node.js را در اختیارمان قرار می‌دهد. در نتیجه در مواقعیکه نسخه‌ی کامل ویژوال استودیو در دسترس نیست نیز می‌توانیم از VS Code برای دیباگ برنامه‌هایمان استفاده کنیم:


نظرات مطالب
React 16x - قسمت 1 - معرفی و شروع به کار
سلام
در بروزرهای قدیمی مثل ie 11 هیچ خروجی نمایش داده نمی‌شود
بسته react-app-polyfill و نصب کرم و در index.js هم خطوط زیر و اضافه کردم ولی باز در ie خروجی ندارم
import 'react-app-polyfill/ie11';
import 'react-app-polyfill/stable'; 
نظرات مطالب
کمی شوخی با IE6
کلا باید IE نابود شود !!

ما را هلاک میکنه تازه اگر مشتری ....

آقا تو این پست هم افزونه فارسی برای این جور شوخی ها برای وردپرس ارائه شده است ...

http://asmane.org/?p=9

توصیه میکنم معرفی کنیدش و نشر دهید تا مردم بی خیال IE شوند ...

یکی از خوانندگان همیشگی وبلاگت ....
مطالب
AngularJS #2
بهتر است قبل از این که به ادامه‌ی آموزش بپردازم، دو نکته را متذکر شوم:
1) روند آموزشی این فریمورک از کل به جز است؛ به این معنا که ابتدا تمامی قابلیت‌های اصلی فریمورک را به صورت کلی و بدون وارد شدن به جزئیات بیان می‌کنم و پس از آن، جزئیات را در قالب مثال‌هایی واقعی بیان خواهم کرد.
2) IDE مورد استفاده بنده Visual Studio 2012 است. همچنین از ابتدا پروژه را با ASP.NET MVC شروع می‌کنم. شاید بگویید که می‌شود Angular را بدون درگیر شدن با مباحث ASP.NET MVC بیان کرد؛ اما پاسخ من این است که این مثال‌ها باید قابل پیاده‌سازی در نرم‌افزارهای واقعی باشند و یکی از بسترهای مورد علاقه‌ی من ASP.NET MVC است. اگرچه باز هم تاکید می‌کنم که کلیه‌ی مباحث ذکرشده، برای کلیه‌ی زبان‌های سمت سرور دیگر هم قابل استفاده است و هدف من در اینجا بیان یک سری چالش‌ها در ASP.NET MVC است.

نحوه‌ی دریافت AngularJS
1) NuGet Package Manager
2) دریافت از وب‌سایت angularjs.org

دریافت از طریق Nuget Package Manager
روش ارجح افزودن کتابخانه‌های جانبی در یک پروژه‌ی واقعی، استفاده از NuGet Package Manager است. دلیل آن هم بارها بیان‌شده است از جمله: باخبر شدن از آخرین به‌روزرسانی کتابخانه‌ها، دریافت وابستگی‌های کتاب‌خانه‌ی مورد نظر و نبودن محدودیت تحریم برای دریافت فایل‌ها است.
روش کار هم بسیار ساده است، کافی است که بر روی پروژه کلیک راست کرده و گزینه‌ی Manage NuGet Packages را انتخاب کنید و با جست جو angularjs نسبت به نصب آن اقدام نمایید.
اگر هم با ابزارهای گرافیکی رابطه‌ی خوبی ندارید، می‌توانید از Package Manager Console فراهم‌شده توسط NuGet استفاده کنید. کافی است در کنسول پاورشل آن عبارت زیر را تایپ کنید:
Install-Package angularjs

پس از نصب angularjs، شاهد تغییراتی در پوشه‌ی Scripts پروژه‌ی خودخواهید بود. تعداد زیادی فایل جاوا اسکریپت که با عبارت angular شروع‌شده‌اند، به این پوشه اضافه شده است. در حال حاضر ما تنها به فایل angular.js نیاز داریم و احتیاجی به فایل‌های دیگر نیست.
همچنین یک پوشه به نام i18n نیز اضافه شده است که برای مباحث Globalization و Internationalization به کار گرفته می‌شود. 
 
دریافت از سایت angularjs.org
برای دریافت Angular از وب سایت رسمی‌اش، به angularjs.org مراجعه کنید؛ اما گویا به دلیل تحریم‌ها این سایت برای IP ایران مسدود شده است (البته افرادی نیز بدون مشکل به آن دسترسی دارند). دکمه‌ی Download را فشار داده و در نهایت کلید دریافت را بزنید. اگر نسخه‌ی کامل آن را دریافت کنید، لیستی از مستندات AngularJS را نیز در فایل دریافتی، خواهید داشت. در هر صورت این روش برای استفاده از angular دریک پروژه‌ی واقعی توصیه نمی‌شود.
پس به عنوان یک best practice، همیشه کتاب‌خانه‌های جانبی را با NuGet دریافت و نصب کنید. رفع موانع تحریم‌ها، یکی از مزایای مهم آن است.
   
پس از دریافت angular،  نوشتن برنامه‌ی معروف Hello, World به وسیله‌ی آن ، می‌تواند بهترین شروع باشد؛ اما اگر اجازه بدهید، نوشتن این برنامه را در قالب توضیح قالب‌های سمت کلاینت انجام دهیم.
   
قالب‌های سمت کلاینت (Client Side Templates)
در برنامه‌های وب چند صفحه‌ای و یا اکثر وب سایت‌های معمول، داده‌ها و کدهای HTML، در سمت سرور اصطلاحا سرهم و مونتاژ شده و خروجی نهایی که HTML خام است به مرورگر کاربر ارسال می‌شود. با یک مثال بیشتر توضیح می‌دهم: در ASP.NET MVC معمولا از لحظه‌ای که کاربر صفحه‌ای را درخواست می‌کند تا زمانی که پاسخ خود را در قالب HTML می‌بیند، این فرآیند طی می‌شود: ابتدا درخواست به Controller هدایت می‌شود و سپس اطلاعات مورد نیاز از پایگاه داده خوانده‌شده و در قالب یک Model به View که یک فایل HTML ساده است، منتقل می‌شود. سپس به کمک موتور نمایشی Razor، داده‌ها در جای مناسب خود قرار می‌گیرند و در نهایت، خروجی که HTML خام است به مرورگر کلاینت درخواست‌کننده ارسال می‌شود تا در مرورگر خود نتیجه را مشاهده نماید. روال کار نیز در اکثر SPA‌های معمول و یا اصطلاحا برنامه‌های AJAX، باکمی تغییر به همین شکل است.
 اما در Angular داستان به شکل دیگری اتفاق می‌افتد؛ Angular قالب HTML و داده‌ها را به صورت جداگانه از سرور دریافت می‌کند و در مرورگر کاربر آن‌ها را سرهم و مونتاژ می‌کند. بدیهی است که در اینجا قالب، یک فایل HTML ساده و داده‌ها می‌تواند به فرم JSON باشد. در نتیجه کار سرور دیگر فراهم کردن قالب و داده‌ها برای کلاینت است و بقیه‌ی ماجرا در سمت کلاینت رخ می‌دهد.
خیلی خوب، مزیت این کار نسبت به روش‌های معمول چیست؟ اگر اجازه بدهید این را با یک مثال شرح دهم:
در بسیاری از سایت ها، ویژگی ای به نام اسکرول نامحدود وجود دارد. در همین سایت نیز دکمه ای با عنوان بیشتر در انتهای لیستی از مطالب، برای مشاهده‌ی ادامه‌ی لیست قرار گرفته است. سعی کنید پس از فشردن دکمه‌ی بیشتر، داده‌های دریافتی از سرور را مشاهده کنید. پس از انجام این کار مشاهده خواهید کرد که پاسخ سرور HTML خام است. اگر تعداد 10 پست از سرور درخواست شود، 10 بار محتوای HTML تکراری نیز دریافت خواهد شد؛ در صورتی که ساختار HTML یک پست هم کفایت می‌کرد و تنها داده‌ها در آن 10 پست متفاوتند؛ چرا که قالب کار مشخص است و فقط به ازای هر پست باید آن داده‌ها در جای مناسب خود قرار داد.
دیدگاه‌های یک پست هم به خوبی با Angular قابل پیاده سازی است. قالب HTML یک دیدگاه را برای angular تعریف کرده و داده‌های مناسب که احتمالا JSON خام است از سرور دریافت شود. نتیجه‌ی این کار هم صرفه جوی در پهنای باند مصرفی و افزایش فوق العاده‌ی سرعت است، همچنین در صورت نیاز می‌توان داده‌ها و قالب‌ها راکش کرد تا مراجعه به سرور به حداقل برسد.
 چگونگی انجام این کار در AngularJs به صورت خلاصه به این صورت است که در angular یک directive به نام ng-repeat تعریف شده است که مانند یک حلقه‌ی foreach برای HTML عمل می‌کند. شما در داخل حلقه، قالب را مشخص می‌کنید و به ازای تعداد داده‌ها، آن حلقه تکرار می‌شود و بر روی داده‌ها پیمایش صورت می‌گیرد.
البته این مثال‌ها فقط دو نمونه از کاربرد این ویژگی در دنیای واقعی بود و مطمئن باشید که در مقالات آینده مثال‌های زیادی از این موضوع را پیاده‌سازی خواهیم کرد.
بهتر است که دیگر خیلی وارد جزئیات نشویم و اولین برنامه‌ی خود را به کمک angularjs بنویسیم. این برنامه، همان برنامه‌ی معروف Hello ,World است؛ اما در این برنامه به جای نوشتن یک Hello, World ساده در صفحه، آن را با ساختار angularjs پیاده‌سازی می‌کنیم.
در داخل ویژوال استادیو یک فایل HTML ساده ایجاد کنید و کد‌های زیر را داخل آن بنویسید.
<!DOCTYPE html>
<html ng-app>
<head>
    <title>Sample 1</title>
</head>
<body>
    <div ng-controller="GreetingController">
        <p>{{greeting.text}}, World!</p>
    </div>

    <script src="../Scripts/angular.js"></script>
    <script>
        function GreetingController($scope) {
            $scope.greeting = {
                text: "Hello"
            };
        }
    </script>
</body>
</html>
سپس فایل فوق را در مرورگر اجرا کنید. بله؛ عبارت Hello, World را مشاهده خواهید کرد. یک بار دیگر خاصیت text  را در scope.greeting$ به hi تغییر بدهید و باز هم نتیجه را مشاهده کنید.
این مثال در نگاه اول خیلی ساده است، اما دنیایی از مفاهیم angular را در بر دارد. شما خواص جدیدی را برای عناصر HTML مشاهده می‌کنید: ng-app، ng-controller، آکلود‌ها و عبارت درون آن و متغیر scope$ به عنوان پارامتر.
حال بیایید ویژگی‌ها و مفاهیم جالب کدهای نوشته شده را بررسی کنیم؛ چرا که فرصت برای بررسی ng-app و بقیه‌ی موارد نا آشنا زیاد است:

- هیچ id و یا class برای عناصر html در نظر گرفته نشده تا با استفاده از آنها، رویدادی را برای عناصر مورد نظر مشخص کنیم.

- وقتی در GreetingController مقدار greeting.text را مشخص کرده ایم، باز هم هیچ رویدادی را صدا نزده و یا مشخص نکرده ایم.

- GreetingController یک کلاس ساده‌ی جاوا اسکریپت (POJO) است و از هیچ چیزی که توسط angular فراهم شده باشد، ارث بری نکرده است.

- اگر به متد سازنده‌ی کلاس GreetingController دقت کنید، متغیر scope$ به عنوان پارامتر تعریف شده است. نکته‌ی جالب این است که ما هیچ گاه به صورت دستی سازنده‌ی کلاس GreetingController را صدا نزده ایم و حتی درون سازنده هم scope$ را ایجاد نکرده ایم؛ پس چگونه توانسته ایم خاصیتی را به آن نسبت داده و برنامه به خوبی کار کند. بهتر است برای پاسخ به این سوال خودتان دست به کار شوید؛ ابتدا نام متغیر scope$ را به نام دلخواه دیگری تغییر دهید و سپس برنامه را اجرا کنید. بله برنامه دیگر کار نمی‌کند. دلیل آن چیست؟ همان طور که گفتم Angular دارای یک سیستم تزریق وابستگی توکار است و در اینجا نیز scope$ به عنوان وابستگی در سازنده‌ی  این کلاس مشخص شده است تا نمونه‌ی مناسب آن توسط angular به کلاس GreetingController ما تزریق شود؛ اما چرا به نام آن یعنی scope$ حساس است؟ به این دلیل که زبان جاوا اسکریپت یک زبان پویا است و نوع در آن مطرح نیست؛ angular مجبور است که از نام پارامترها برای تزریق وابستگی استفاده می‌کند. در مقالات آینده چگونگی عملکرد سیستم تزریق وابستگی angular را به تشریح بیان می‌کنم.

- همچنین همان طور که در مورد قبلی نیز به آن اشاره کردم، ما هیچ گاه خود دستی سازنده‌ی GreetingController را صدا نزدیم و جایی نیز نحوه‌ی صدا زدن آن را مشخص نکرده ایم.

 تا همین جا فکر کنم کاملا برای شما مشخص شده است که ساختار فریمورک Angular با تمامی کتاب خانه‌های مشابه متفاوت است و با ساختاری کاملا اصولی و حساب شده طرف هستیم. همچنین در مقالات آینده توجه شما را به قابلیت‌هایی بسیار قدرتمند‌تر جلب خواهم کرد.
   
MVC ،MVP ، MVVM و یا MVW
 در بخش اول این مقاله، الگوی طراحی پیشنهادی فریمورک Angular را MVC بیان کرده‌ام؛ اما همان طور که گفته بودم AngularJS از انقیاد داده دوطرفه (Two Way Data Binding) نیز به خوبی پشتیبانی می‌کند و به همین دلیل عده ای آن را یک MVVM Framework تلقی می‌کنند. حتی داستان به همین جا ختم نمی‌شود و عده ای آن را به چشم MVP  Framework  نیز نگاه می‌کنند. در ابتدا سایت رسمی AngularJS الگوی طراحی مورد استفاده را MVC بیان می‌نمود ولی در این چند وقت اخیر عنوانش را به MVW Framework تغییر داده است.
MVW مخفف عبارت Model View Whatever هست و کاملا مفهومش مشخص است. Model و View بخش‌های مشترک تمام الگو‌ها بودند و تنها بخش سوم مورد اختلاف توسعه دهندگان بود؛ در نتیجه انتخاب آن را بر عهده‌ی استفاده کننده قرار داده اند و تمام امکانات لازم برای پیاده‌سازی این الگو‌های طراحی را فراهم کرده اند. در طی این مقالات صرف نظر از تمام الگوهای طراحی فوق، من بیشتر بر روی MVC تمرکز خواهم کرد.
الگوی طراحی MVC در سال 1970 به عنوان بخشی از زبان برنامه نویسی Smalltalk معرفی شد و از همان ابتدا به سرعت محبوبیت زیادی در بین محیط‌های توسعه‌ی دسکتاپی از قبیل ++C و Java  که رابط کاربری گرافیکی به نوعی در آن‌ها دخیل است، پیدا کرد.
تفکر MVC این را بیان می‌کند که باید جداسازی واضح و روشنی بین مدیریت داده‌ها (Model)، منطق برنامه (Controller) و نمایش داده‌ها به کاربر (View) وجود داشته باشد و در اصل هدفش جداسازی اجزای رابط کاربری به بخش هایی مجزا است.
     
شاید این سوال برای شما پیش بیاید که چرا باید چنین الگویی را در برنامه‌ها پیاده کرد؟
احتمالا تا کنون از بین برنامه هایی که نوشته اید، رابط کاربری بیشتر از آن‌ها را نیز خودتان مجبور شده اید طراحی کنید؛ به این دلیل که برنامه‌ی شما بدون رابط کاربری قابل اجرا شدن نبوده است. اجرای برنامه‌ی شما منوط به وجود تعدادی دکمه و textbox و ... بوده است و به قولی منطق برنامه به رابط گرافیکی گره خورده بوده است. پس می‌توان گفت که پیاده‌سازی الگوی طراحی وقتی ضرورت پیدا می‌کند که رابط گرافیکی، قسمتی از برنامه‌ی شما را تشکیل دهد.
آیا با وجود زبان‌های طراحی ساده ای مثل HTML و XAML و ... احتیاجی است که برنامه نویس وقت خود را صرف طراحی رابط کاربری کند؟ مسلما خیر، چون دیگر با این امکانات یک طراح هم از پس این کار به خوبی و یا حتی بهتر بر می‌آید. دیگر وظیفه‌ی برنامه نویس نوشتن کد‌های مربوط به منطق برنامه است. کدهایی که بدون UI هم قابل تست شدن باشد و به راحتی بتوان برای آن‌ها آزمون‌های واحد نوشت. برنامه نویس باید این را در نظر بگیرد که UI وجود ندارد و حتی ممکن است هیچ گاه هم ایجاد نشود و  این کد‌ها تبدیل به یک کتابخانه شود و مورد استفاده قرار بگیرد تا در یک برنامه با رابط کاربری گرافیکی.
در MVC، روال عمومی کار به این شکل است که View داده‌ها را از Model دریافت می‌کند و به کاربر نمایش می‌دهد. وقتی که کاربر با کلیک کردن و تایپ کردن با برنامه ارتباط برقرار می‌نماید، Controller به این درخواست‌ها پاسخ می‌دهد و داده‌های موجود در Model را به روز رسانی می‌کند. در نهایت هم Model  تغییرات خود را به View منعکس می‌کند تا View آن چه را که پیش از آن نمایش می‌داده است، تغییر دهد و View را از تغییرات رخ داده آگاه نماید.
اما در برنامه‌های Angular قضیه از چه قرار است؟ در Angular، قالب HTML  یا اگر بخواهم دقیق‌تر بگویم (Document Object Model(DOM معادل View است؛ کلاس‌های جاوا اسکریپتی نقش Controller را دارند؛ و خواص اشیای جاوا اسکریپتی و یا حتی خود اشیا نقش Model را بر عهده دارند.

ساختار بخشیدن به برنامه با استفاده MVC یک مزیت مهم دیگر نیز دارد: ساختار کار کاملا مشخص است و هر کسی نمی‌تواند به صورت سلیقه ای آن را پیاده سازی کند. با یک مثال این موضوع را تشریح می‌کنم: اگر کسی پروژه‌ی بنده را که با ASP.NET MVC نوشتم، بررسی کند، اصلا احساس غریبی نمی‌کند و به راحتی می‌تواند آن را توسعه دهد. دلیل این موضوع این است که ASP.NET MVC یک ساختار مشخص را به توسعه دهندگان اجبار کرده است و هر کسی این ساختار را رعایت کند و با آن آشنا باشد، به راحتی می‌تواند با آن کار کند. توسعه دهنده می‌داندکه من Model را کجا تعریف کرده ام، Controller مربوط به هر View کجاست و در کدام قسمت با پایگاه داده ارتباط برقرار کرده‌ام؛ اما در مورد کد‌های JavaScript و سمت کلاینت چه طور؟ توسعه دهنده ای که می‌خواهد کار من را ادامه بدهد دچار وحشت می‌شود! الگوی مشخصی وجود ندارد؛ معلوم نیست که کجا DOM را دستکاری کرده‌ام، در کدام قسمت با سرور ارتباط برقرار شده و... به قول معروف با یک اسپاگتی کد تمام عیار طرف می‌شود. AngularJS این مشکل را حل نموده و ساختار خاصی را سعی کرده به شما دیکته کند و تا حد ممکن دست شما را نیز باز گذاشته است. جدا از همه‌ی اینها، برنامه‌های مبتنی بر Angular به راحتی نگه داری  و تست می‌شوند و بدون هیچ دغدغه ای آن‌ها را می‌توان توسعه داد.
   
در حاشیه
شاید در هنگام دریافت فایل angularjs و افزودن آن به پروژه‌ی خود شروع به اعتراض کرده اید که نسخه‌ی فشرده شده‌ی آن 87 کیلو بایت حجم دارد در صورتی که این حجم در کتابخانه‌های مشابه ممکن است حتی به 10 کیلوبایت هم نرسد. اگر دقت کرده باشید من در بیان AngularJS از واژه‌ی کتاب خانه استفاده نکردم و فقط از واژه‌ی فریمورک استفاده کردم. بله نمی‌شود angular را با کتاب خانه هایی مقایسه کرد که مهمترین ویژگی خود را Data Binding می‌دانند. AngularJS یک بستر کاری قدرتمند است که تمام راه حل‌های موجود را در خود جمع کرده است. تیم توسعه دهنده‌ی آن هم هیچ ادعایی ندارد و می‌گویند که ما هیچ چیزی را خودمان اختراع نکرده ایم، بلکه راه حل‌های عالی را برگزیدیم، تفکرهای خوب را ارتقا بخشیده و در فریمورک خود استفاده کردیم و حتی از ایده‌های خوب دیگر کتاب خانه‌ها هم استفاده کرده ایم. بنابر این نباید به حجم آن در مقابل توانایی هایی که دارد اعتراض کرد.
   
همچنین به نظر می‌آید که AngularJS یک فریمورک پیچیده است. ولی من همیشه بین پیچیده و پیچیده شده تفاوت قائل می‌شوم. به نظر شخصی خودم Angular به دلیل مشکلات خاص و پیچیده ای که حل می‌کند پیچیده است و پیچیده شده نیست. اگر آن را پیچیده شده حس می‌کنید، تنها دلیلش، نحوه‌ی آموزش دادن بنده است، تمام سعی خود را می‌کنم که مفاهیم را تا حد ممکن ساده بیان کنم و امیدوارم در آینده که با مثال‌های بیشتری روبرو می‌شوید، این مفاهیم به کارتان بیاید.
     
در مقاله‌ی بعدی به مفاهیم انقیاد داده، تزریق وابستگی، هدایت گر‌ها (Directives) و سرویس‌ها در AngularJS می‌پردازم.