مفهوم Workspace در Angular
/projects apps .....applications..... libs .....libraries.....
نصب ابتدایی آن بسیار ساده است و نکته خاصی ندارد.
پس از نصب، یکبار VS.NET را بسته و سپس باز کنید. این قالب جدید، ذیل قسمت پروژههای ویندوز مرتبط با ویژوال سی شارپ، ظاهر خواهد شد:
در این حال اگر یک پروژه جدید را آغاز کنید، این قالب تدارک دیده شده، لایهها و قسمتهای مختلف را به صورت خودکار اضافه خواهد کرد:
نکته مهم! برنامه کامپایل نمیشود!
به عمد، جهت کاهش حجم قالب دریافتی فوق، فایلهای باینری آن پیوست نشدهاند. وگرنه باید بالای 30 مگابایت را دریافت میکردید که واقعا نیازی نیست.
اما اگر به هر پروژه داخل Solution دقت کنید، فایل متنی packages.config آن نیز پیوست شده است. به کمک این فایلها به سادگی میتوان تمام وابستگیها را از طریق NuGet بازیابی کرد.
برای این منظور ابتدا به اینترنت متصل شده (مهم) و سپس بر روی Solution کلیک راست کرده و گزینه فعال سازی Restore کلیه بستههای نیوگت را انتخاب کنید.
پس از اینکار، آخرین نگارش NuGet.exe از اینترنت دریافت و به پروژه اضافه میشود:
اکنون اگر Solution را Build کنید، اولین کاری که صورت خواهد گرفت، دریافت کلیه وابستگیها از سایت NuGet است. اندکی تامل کنید تا اینکار تمام شود.
پس از پایان کار دریافت، پوشه packages در کنار فایل sln پروژه ایجاد شده، تشکیل میشود.
یکبار وجود آنرا بررسی کنید.
اکنون اگر برنامه را Build کنید احتمالا پیغام میدهد که Fody را نمیتواند پیدا کند با اینکه دریافت شده و در پوشه packages موجود است. هر زمان، هر پیغام خطایی در مورد Fody مشاهده کردید، فقط یکبار VS.NET را بسته و باز کنید. مشکل حل میشود!
تنها کاری که پس از بازسازی پوشه packages بهتر است صورت گیرد (اختیاری است البته)، صدور دستور ذیل در خط فرمان پاور شل است:
PM> Update-Package
پس از اینکار، نیاز است یکبار VS.NET را بسته و مجددا باز کنید (مهم) تا تمام وابستگیها به درستی بارگذاری شوند. خصوصا بسته Fody که کار AOP را انجام میدهد. در غیر اینصورت موفق به Build پروژه نخواهید شد.
بنابراین به صورت خلاصه:
الف) یکبار گزینه فعال سازی Restore کلیه بستههای نیوگت را انتخاب کنید.
ب) پروژه را Build کنید تا وابستگیها را از سایت NuGet دریافت کند.
ج) دستور Update-Package را اجرا نمائید (اختیاری).
ج) VS.NET را پس از سه مرحله فوق، یکبار بسته و باز کنید.
در کل بستههای مورد استفاده به این شرح هستند:
PM> Install-Package MahApps.Metro -Pre PM> Install-Package MahApps.Metro.Resources PM> Install-Package EntityFramework PM> Install-Package structuremap PM> Install-Package PropertyChanged.Fody PM> Install-Package MvvmLight PM> Install-Package Microsoft.SqlServer.Compact
یک نکته جانبی
فید NuGet در VS.NET به Https تنظیم شده است. اگر دسترسی به Https برای شما به کندی صورت میگیرد فقط کافی است مسیر فید آنرا در منوی Tools، گزینهی Options، ذیل قسمت Package manager یافته و به http://nuget.org/api/v2 تغییر دهید؛ یعنی به Http خالی، بجای Https؛ تا سرعت دریافت بستههای NuGet مورد نظر افزایش یابند.
اجرای پروژه و برنامه
پس از این مراحل و Build موفقیت آمیز پروژه، برنامه را اجرا کنید. در اولین بار اجرای برنامه به صورت خودکار بانک اطلاعاتی به همراه ساختار جداول تشکیل میشوند. اما ... با خطای زیر مواجه خواهید شد:
The path is not valid. Check the directory for the database. [ Path = D:\...\bin\Debug\Db\db.sdf ]
<connectionStrings> <clear/> <add name="MyWpfFrameworkContext" connectionString="Data Source=|DataDirectory|\Db\db.sdf;Max Buffer Size=30720;File Mode=Read Write;" providerName="System.Data.SqlServerCE.4.0" /> </connectionStrings>
برای ورود به برنامه از نام کاربری Admin و کلمه عبور 123456 استفاده نمائید.
این کاربر پیش فرض در کلاس MyWpfFrameworkMigrations لایه دادههای برنامه، توسط متد addRolesAndAdmin اضافه شده است.
خوب! تا اینجا با نحوه نصب و راه اندازی این قالب جدید آشنا شدیم. در قسمتهای بعد، به جزئیات ارتباطات و نحوه استفاده از آن به عنوان پایه یک کار و پروژه جدید، خواهیم پرداخت.
به روز رسانی 1.1
جهت سازگاری با EF 6 ، StructureMap 3 و همچنین VS 2013، پروژه به روز شد: WpfFrmwork_1.1.zip
به روز رسانی نهایی
به روز شدهی این پروژه را بر اساس آخرین وابستگیهای آن از اینجا دریافت کنید.
نگاهی به افزونههای کار با اسناد در RavenDB
پیوست و بازیابی فایلهای باینری
امکان پیوست فایلهای باینری نیز به اسناد RavenDB وجود دارد. برای مثال به کلاس سؤالات قسمت اول این سری، خاصیت FileId را اضافه کنید:
public class Question { public string FileId { set; get; } }
using (var store = new DocumentStore { Url = "http://localhost:8080" }.Initialize()) { using (var session = store.OpenSession()) { store.DatabaseCommands.PutAttachment(key: "file/1", etag: null, data: System.IO.File.OpenRead(@"D:\Prog\packages.config"), metadata: new RavenJObject { { "Description", "توضیحات فایل" } }); var question = new Question { By = "users/Vahid", Title = "Raven Intro", Content = "Test....", FileId = "file/1" }; session.Store(question); session.SaveChanges(); } }
در این حالت اگر به خروجی دیباگ سرور نیز دقت کنیم، مسیر ذخیره سازی این نوع فایلها مشخص میشود:
Request # 2: PUT - 200 ms - <system> - 201 - /static/file/1
using (var store = new DocumentStore { Url = "http://localhost:8080" }.Initialize()) { using (var session = store.OpenSession()) { var question = session.Load<Question>("questions/97"); var file1 = store.DatabaseCommands.GetAttachment(question.FileId); Console.WriteLine(file1.Size); } }
وصله کردن اسناد
سند سؤالات قسمت اول و پاسخهای آن، همگی داخل یک سند هستند. اکنون برای اضافه کردن یک آیتم به این لیست، یک راه، واکشی کل آن سند است و سپس افزودن یک آیتم جدید به لیست پاسخها و یا در این حالت، جهت کاهش ترافیک سرور و سریعتر شدن کار، RavenDB مفهوم Patching یا وصله کردن اسناد را ارائه داده است. در این روش بدون واکشی کل سند، میتوان قسمتی از سند را وصله کرد و تغییر داد.
using (var store = new DocumentStore { Url = "http://localhost:8080" }.Initialize()) { using (var session = store.OpenSession()) { store.DatabaseCommands.Patch(key: "questions/97", patches: new[] { new PatchRequest { Type = PatchCommandType.Add, Name = "Answers", Value = RavenJObject.FromObject(new Answer{ By= "users/Vahid", Content="data..."}) } }); } }
افزونههای RavenDB
قابلیتهای ذکر شده فوق جهت کار با اسناد به صورت توکار در RavenDB مهیا هستند. این سیستم افزونه پذیر است و تاکنون افزونههای متعددی برای آن تهیه شدهاند که در اینجا به آنها Bundles گفته میشوند. برای استفاده از آنها تنها کافی است فایل DLL مرتبط را درون پوشه Plugins سرور، کپی کنیم. دریافت آنها نیز از طریق NuGet پشتیبانی میشود؛ و یا سورس آنها را دریافت کرده و کامپایل کنید. در ادامه تعدادی از این افزونهها را بررسی خواهیم کرد.
حذف آبشاری اسناد
PM> Install-Package RavenDB.Bundles.CascadeDelete -Pre
استفاده مهم این افزونه، حذف پیوستهای باینری اسناد و یا حذف اسناد مرتبط با یک سند، پس از حذف سند اصلی است (که به صورت پیش فرض انجام نمیشود).
یک مثال:
var comment = new Comment { PostId = post.Id }; session.Store(comment); session.Advanced.GetMetadataFor(post)["Raven-Cascade-Delete-Documents"] = RavenJToken.FromObject(new[] { comment.Id }); session.Advanced.GetMetadataFor(post)["Raven-Cascade-Delete-Attachments"] = RavenJToken.FromObject(new[] { "picture/1" }); session.SaveChanges();
نگهداری و بازیابی نگارشهای مختلف اسناد
PM> Install-Package RavenDB.Bundles.Versioning
با استفاده از قابلیت document versioning میتوان تغییرات اسناد را در طول زمان، ردیابی کرد؛ همچنین حذف یک سند، این سابقه را از بین نخواهد برد.
تنظیمات اولیه آن به این صورت است که توسط شیء VersioningConfiguration به سشن جاری اعلام میکنیم که چند نگارش از اسناد را ذخیره کند. اگر Exclude آن به true تنظیم شود، اینکار صورت نخواهد گرفت.
session.Store(new VersioningConfiguration { Exclude = false, Id = "Raven/Versioning/DefaultConfiguration", MaxRevisions = 5 });
بازیابی نگارشهای مختلف یک سند، صرفا از طریق متد Load میسر است و در اینجا شماره Id نگارش به انتهای Id سند اضافه میشود. برای مثال "blogposts/1/revisions/1" به نگارش یک مطلب شماره یک اشاره میکند.
برای بدست آوردن سه نگارش آخر یک سند باید از متد ذیل استفاده کرد:
var lastThreeVersions = session.Advanced.GetRevisionsFor<BlogPost>(post.Id, 0, 3);
در اینجا قرار است تک تک عناصر آرایهای از اعداد، با عدد 6 جمع شوند. روش متداول آن به این صورت است که حلقهای تشکیل شده و سپس تک تک عناصر این آرایه دریافت و با عدد 6 جمع میشوند. اما در حالت استفادهی از SIMD، هربار گروهی از عناصر این آرایه به صورت یک بردار درنظر گرفته میشوند (Multiple Data) و سپس با برداری حاوی مقدار 6 جمع میشوند (Single Instruction). اینبار این عملیات به صورت موازی، بر روی گروهی از اعداد انجام میشود و به همین دلیل نسبت به حالت کار بر روی یک المان از آرایه در هر مرحله، سرعت بیشتری دارد.
تفاوت چندریسمانی با SIMD چیست؟
شاید عنوان کنید که با وجود امکانات چندریسمانی چه نیازی به SIMD است؟ در حالت پردازشهای چند ریسمانی، یک یا چند کار بر روی چندین هستهی CPU به صورت موازی پردازش میشوند، اما SIMD امکان پردازش موازی را در یک هستهی CPU میسر میکند.
آیا CPU من از SIMD پشتیبانی میکند؟
SIMD instruction sets شامل افزونههای ذیل است:
• MMX - MultiMedia eXtensions • SSE - Streaming SIMD Extensions • SSE2 - Streaming SIMD Extensions 2 • SSE3 - Streaming SIMD Extensions 3 • SSSE3 - Supplemental Streaming SIMD Extensions 3 • SSE4.1 - Streaming SIMD Extensions 4.1 • SSE4.2 - Streaming SIMD Extensions 4.2 • AES-NI - Advanced Encryption Standard New Instructions • AVX - Advanced Vector eXtensions
در این برنامه، در برگهی CPU آن به قسمت instructions آن دقت کنید و موارد لیست شدهی در آن را با افزونههای فوق مقایسه نمائید.
پشتیبانی از SIMD در دات نت
با ارائهی دات نت 4.6 و RyuJIT جدید آن، امکان کار با دستورات SIMD در فضای نام System.Numerics.Vectors پیش بینی شدهاست. برای کار با آن باید بستهی نیوگت زیر را نصب کنید:
PM> Install-Package System.Numerics.Vectors
الف) نصب دات نت 4.6.x (دریافت دات نت 4.6.1 مخصوص یکپارچه شدن با ویژوال استودیو)
ب) به خواص پروژهی جاری مراجعه کرده و platform target را بر روی x64 قرار دهید. باید دقت داشت که RyuJIT جدید، برای سیستمهای 64 بیتی طراحی شدهاست.
ج) RyuJIT، در حالت release و انتخاب گزینهی optimize code (در همان برگهی خواص پروژه) است که کدهای ویژهی SIMD را تولید میکند.
د) نصب بستهی نیوگت System.Numerics.Vectors
در کل اگر برنامه را داخل دیباگر VS.NET اجرا کنید، مقدار Vector.IsHardwareAccelerated مساوی false خواهد بود. به همین جهت برنامه را در حالت release و 64 بیتی کامپایل کرده و خارج از محیط VS.NET اجرا کنید.
بررسی فضای نام جدید System.Numerics.Vectors
پشتیبانی از SIMD در دات نت به این معنا نیست که هر نوع کدی توسط RyuJIT به صورت خودکار تبدیل به SIMD instruction sets خواهد شد. برای این منظور نیاز است از نوعهای دادهای خاصی به همراه متدهای مرتبط با آنها استفاده کرد.
سری اول این نوعهای جدید برداری، به شرح زیر هستند:
var vector01 = new Vector2(x: 5F, y: 15F); var vector11 = new Vector3(x: 5F, y: 15F, z: 25F); var vector12 = new Vector3(x: 3F, y: 5F, z: 8F); var vector13 = new Vector4(x: 3F, y: 5F, z: 8F, w:1F);
var vector3 = vector11 - vector12; //استفاده از سربارگذاری عملگرها var vector4 = Vector3.Subtract(vector12, vector11);//ویا استفاده از متدهای متناظر vector3 = vector11 * vector12; vector4 = Vector3.Multiply(vector11, vector12); vector3 = vector11 / vector12; vector4 = Vector3.Divide(vector11, vector12); vector3 = vector11 + vector12; vector4 = Vector3.Add(vector11, vector12); var areEqual = (vector11 == vector12); var areNotEqual = (vector11 != vector12); var array = new float[3]; vector11.CopyTo(array);
علاوه بر اعمال متداول ریاضی، هر کدام از کلاسهای Vector دارای متدهای اضافی ویژهای مانند محاسبهی حداقل، حداکثر، جذر و غیره نیز میباشند:
vector3 = Vector3.Max(vector11, vector12); vector3 = Vector3.Min(vector11, vector12); vector3 = Vector3.SquareRoot(vector11); vector3 = Vector3.Abs(vector11); var dotProduct = Vector3.Dot(vector11, vector12);
سری دوم بردارهای قابل تعریف، از نوع <Vector<T هستند. برای مثال CPUهایی که از SSE2 پشتیبانی میکنند، قابلیت کار با نوعهای دادهای زیر را نیز دارا هستند:
Vector<double>.Length: 2 Vector<int>.Length: 4 Vector<long>.Length: 2 Vector<float>.Length: 4
private static int[] simpleIncrement(int[] values, int inc) { var results = new int[values.Length]; for (var i = 0; i < results.Length; i++) { results[i] = values[i] + inc; } return results; }
private static int[] simdIncrement(int[] values, int inc) { var vector = new Vector<int>(values); var vectorAddResults = vector + new Vector<int>(inc); var results = new int[values.Length]; vectorAddResults.CopyTo(results); return results; }
در مثال ذیل، نحوهی انتخاب Multiple data (گروهی از اعداد، بجای تک عدد) و سپس اعمال یک تک instruction را ملاحظه میکنید:
var valuesIn = new float[] { 4f, 16f, 36f, 64f, 9f, 81f, 49f, 25f, 100f, 121f, 144f, 16f, 36f, 4f, 9f, 81f }; var valuesOut = new float[valuesIn.Length]; for (var i = 0; i < valuesIn.Length; i += Vector<float>.Count) { var vectorIn = new Vector<float>(valuesIn, i); var vectorOut = Vector.SquareRoot(vectorIn); vectorOut.CopyTo(valuesOut, i); }
یک مثال تکمیلی
پیشنیازها
- مطالعهی سری کار با Angular CLI خصوصا قسمت نصب و قسمت ساخت برنامههای آن، پیش از مطالعهی این مطلب ضروری است.
- همچنین فرض بر این است که سری ASP.NET Core را نیز یکبار مرور کردهاید و با نحوهی برپایی یک برنامهی MVC آن و ارائهی فایلهای استاتیک توسط یک پروژهی ASP.NET Core آشنایی دارید.
ایجاد یک پروژهی جدید ASP.NET Core در VS 2017
در ابتدا یک پروژهی خالی ASP.NET Core را در VS 2017 ایجاد خواهیم کرد. برای این منظور:
- ابتدا از طریق منوی File -> New -> Project (Ctrl+Shift+N) گزینهی ایجاد یک ASP.NET Core Web application را انتخاب کنید.
- در صفحهی بعدی آن هم گزینهی «empty template» را انتخاب نمائید.
تنظیمات یک برنامهی ASP.NET Core خالی برای اجرای یک برنامهی Angular CLI
برای اجرای یک برنامهی مبتنی بر Angular CLI، نیاز است بر روی فایل csproj برنامهی ASP.NET Core کلیک راست کرده و گزینهی Edit آنرا انتخاب کنید.
سپس محتوای این فایل را به نحو ذیل تکمیل نمائید:
الف) درخواست عدم کامپایل فایلهای TypeScript
<PropertyGroup> <TargetFramework>netcoreapp1.1</TargetFramework> <TypeScriptCompileBlocked>true</TypeScriptCompileBlocked> </PropertyGroup>
ب) مشخص کردن پوشههایی که باید الحاق و یا حذف شوند
<ItemGroup> <Folder Include="Controllers\" /> <Folder Include="wwwroot\" /> </ItemGroup> <ItemGroup> <Compile Remove="node_modules\**" /> <Content Remove="node_modules\**" /> <EmbeddedResource Remove="node_modules\**" /> <None Remove="node_modules\**" /> </ItemGroup> <ItemGroup> <Compile Remove="src\**" /> <Content Remove="src\**" /> <EmbeddedResource Remove="src\**" /> </ItemGroup>
سپس دو پوشهی node_modules و src واقع در ریشهی پروژه را نیز به طور کامل از سیستم ساخت و توزیع VS 2017 حذف کردهایم. پوشهی node_modules وابستگیهای Angular را به همراه دارد و src همان پوشهی برنامهی Angular ما خواهد بود.
ج) افزودن وابستگیهای سمت سرور مورد نیاز
<ItemGroup> <PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" /> <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" /> <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" /> </ItemGroup> <ItemGroup> <DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="1.0.0" /> </ItemGroup> <ItemGroup> <!-- extends watching group to include *.js files --> <Watch Include="**\*.js" Exclude="node_modules\**\*;**\*.js.map;obj\**\*;bin\**\*" /> </ItemGroup>
در اینجا Watcher.Tools هم به همراه تنظیمات آن اضافه شدهاند که در ادامهی بحث به آن اشاره خواهد شد.
افزودن یک کنترلر Web API جدید
با توجه به اینکه دیگر در اینجا قرار نیست با فایلهای cshtml و razor کار کنیم، کنترلرهای ما نیز از نوع Web API خواهند بود. البته در ASP.NET Core، کنترلرهای معمولی آن، توانایی ارائهی Web API و همچنین فایلهای Razor را دارند و از این لحاظ تفاوتی بین این دو نیست و یکپارچگی کاملی صورت گرفتهاست.
using System.Collections.Generic; using Microsoft.AspNetCore.Mvc; namespace ASPNETCoreIntegrationWithAngularCLI.Controllers { [Route("api/[controller]")] public class ValuesController : Controller { // GET: api/values [HttpGet] [ResponseCache(NoStore = true, Location = ResponseCacheLocation.None)] public IEnumerable<string> Get() { return new string[] { "Hello", "DNT" }; } } }
تنظیمات فایل آغازین یک برنامهی ASP.NET Core جهت ارائهی برنامههای Angular
در ادامه به فایل Startup.cs برنامهی خالی جاری، مراجعه کرده و آنرا به نحو ذیل تغییر دهید:
using System; using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace ASPNETCoreIntegrationWithAngularCLI { public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddMvc(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { loggerFactory.AddConsole(); if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.Use(async (context, next) => { await next(); if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value) && !context.Request.Path.Value.StartsWith("/api/", StringComparison.OrdinalIgnoreCase)) { context.Request.Path = "/index.html"; await next(); } }); app.UseMvcWithDefaultRoute(); app.UseDefaultFiles(); app.UseStaticFiles(); } } }
در قسمت app.Use آن، تنظیمات URL Rewriting مورد نیاز جهت کار با مسیریابی برنامههای Angular را مشاهده میکنید. برای نمونه اگر کاربری در ابتدای کار آدرس /products را درخواست کند، این درخواست به سمت سرور ارسال میشود و چون چنین صفحهای در سمت سرور وجود ندارد، خطای 404 بازگشت داده میشود و کار به پردازش برنامهی Angular نخواهد رسید. اینجا است که تنظیم میانافزار فوق، کار مدیریت خروجیهای 404 را بر عهده گرفته و کاربر را به فایل index.html برنامهی تک صفحهای وب، هدایت میکند. به علاوه در اینجا اگر درخواست وارد شده، دارای پسوند باشد (یک فایل باشد) و یا با api/ شروع شود (اشاره کنندهی به کنترلرهای Web API برنامه)، از این پردازش و هدایت به صفحهی index.html معاف خواهد شد.
ایجاد ساختار اولیهی برنامهی Angular CLI در داخل پروژهی جاری
اکنون از طریق خط فرمان به پوشهی ریشهی برنامهی ASP.NET Core، جائیکه فایل Startup.cs قرار دارد، وارد شده و دستور ذیل را اجرا کنید:
>ng new ClientApp --routing --skip-install --skip-git --skip-commit
پس از تولید ساختار برنامهی Angular CLI، به پوشهی آن وارد شده و تمام فایلهای آن را Cut کنید. سپس به پوشهی ریشهی برنامهی ASP.NET Core جاری، وارد شده و این فایلها را در آنجا paste نمائید. به این ترتیب به حداکثر سازگاری ساختار پروژههای Angular CLI و VS 2017 خواهیم رسید. زیرا اکثر فایلهای تنظیمات آنرا میشناسد و قابلیت پردازش آنها را دارد.
پس از این cut/paste، پوشهی خالی ClientApp را نیز حذف کنید.
تنظیم محل خروجی نهایی Angular CLI به پوشهی wwwroot
برای اینکه سیستم Build پروژهی Angular CLI جاری، خروجی خود را در پوشهی wwwroot قرار دهد، تنها کافی است فایل .angular-cli.json را گشوده و outDir آنرا به wwwroot تنظیم کنیم:
"apps": [ { "root": "src", "outDir": "wwwroot",
فراخوانی کنترلر Web API برنامه در برنامهی Angular CLI
در ادامه صرفا جهت آزمایش برنامه، فایل src\app\app.component.ts را گشوده و به نحو ذیل تکمیل کنید:
import { Component, OnInit } from '@angular/core'; import { Http } from '@angular/http'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { constructor(private _httpService: Http) { } apiValues: string[] = []; ngOnInit() { this._httpService.get('/api/values').subscribe(values => { this.apiValues = values.json() as string[]; }); } }
سپس این آرایه را در فایل قالب این کامپوننت (src\app\app.component.html) استفاده خواهیم کرد:
<h1>Application says:</h1> <ul *ngFor="let value of apiValues"> <li>{{value}}</li> </ul> <router-outlet></router-outlet>
نصب وابستگیهای برنامهی Angular CLI
در ابتدای ایجاد پوشهی ClientApp، از پرچم skip-install استفاده شد، تا صرفا ساختار پروژه، جهت cut/paste آن با سرعت هر چه تمامتر، ایجاد شود. اکنون برای نصب وابستگیهای آن یا میتوان در solution explorer به گره dependencies مراجعه کرده و npm را انتخاب کرد. در ادامه با کلیک راست بر روی آن، گزینهی restore packages ظاهر میشود. و یا میتوان به روش متداول این نوع پروژهها، از طریق خط فرمان به پوشهی ریشهی پروژه وارد شد و دستور npm install را صادر کرد. بهتر است اینکار را از طریق خط فرمان انجام دهید تا مطمئن شوید که از آخرین نگارشهای این ابزار که بر روی سیستم نصب شدهاست، استفاده میکنید.
روش اول اجرای برنامههای مبتنی بر ASP.NET Core و Angular CLI
تا اینجا اگر برنامه را از طریق VS 2017 اجرا کنید، خروجی را مشاهده نخواهید کرد. چون هنوز فایل index.html آن تولید نشدهاست.
بنابراین روش اول اجرای این نوع برنامهها، شامل مراحل ذیل است:
الف) ساخت پروژهی Angular CLI در حالت watch
> ng build --watch
ب) اجرای برنامه از طریق ویژوال استودیو
اکنون که کار ایجاد محتوای پوشهی wwwroot برنامه انجام شدهاست، میتوان برنامه را از طریق VS 2017 به روش متداولی اجرا کرد:
یک نکته: میتوان قسمت الف را تبدیل به یک Post Build Event هم کرد. برای این منظور باید فایل csproj را به نحو ذیل تکمیل کرد:
<Target Name="AngularBuild" AfterTargets="Build"> <Exec Command="ng build" /> </Target>
تنها مشکل روش Post Build Event، کند بودن آن است. زمانیکه از روش ng build --watch به صورت مستقل استفاده میشود، برای بار اول اجرا، اندکی زمان خواهد برد؛ اما اعمال تغییرات بعدی به آن بسیار سریع هستند. چون صرفا نیاز دارد این تغییرات اندک و تدریجی را کامپایل کند و نه کامپایل کل پروژه را از ابتدا.
روش دوم اجرای برنامههای مبتنی بر ASP.NET Core و Angular CLI
روش دومی که در اینجا بررسی خواهد شد، مستقل است از قسمت «ب» روش اول که توضیح داده شد. برنامههای NET Core. نیز به همراه CLI خاص خودشان هستند و نیازی نیست تا حتما از VS 2017 برای اجرای آنها استفاده کرد. به همین جهت وابستگی Microsoft.DotNet.Watcher.Tools را نیز در ابتدای کار به وابستگیهای برنامه اضافه کردیم.
الف) در ادامه، VS 2017 را به طور کامل ببندید؛ چون نیازی به آن نیست. سپس دستور ذیل را در خط فرمان، در ریشهی پروژه، صادر کنید:
> dotnet watch run
>dotnet watch run [90mwatch : [39mStarted Hosting environment: Production Now listening on: http://localhost:5000 Application started. Press Ctrl+C to shut down.
ب) در اینجا چون برنامه بر روی پورت 5000 ارائه شدهاست، بهتر است دستور ng serve -o را صادر کرد تا بتوان به نحو سادهتری از سرور وب ASP.NET Core استفاده نمود. در این حالت برنامهی Angular CLI بر روی پورت 4200 ارائه شده و بلافاصله در مرورگر نیز نمایش داده میشود.
مشکل! سرور وب ما بر روی پورت 5000 است و سرور آزمایشی Angular CLI بر روی پورت 4200. اکنون برنامهی Angular ما، یک چنین درخواستهایی را به سمت سرور، جهت دریافت اطلاعات ارسال میکند: localhost:4200/api
برای رفع این مشکل میتوان فایلی را به نام proxy.config.json با محتویات ذیل ایجاد کرد:
{ "/api": { "target": "http://localhost:5000", "secure": false } }
>ng serve --proxy-config proxy.config.json -o
مزیت این روش، به روز رسانی خودکار مرورگر با انجام هر تغییری در کدهای قسمت Angular برنامه است.
نکته 1: بدیهی است میتوان قسمت «ب» روش دوم را با قسمت «الف» روش اول نیز جایگزین کرد (ساخت پروژهی Angular CLI در حالت watch). اینبار گشودن مرورگر بر روی پورت 5000 (و یا آدرس http://localhost:5000) را باید به صورت دستی انجام دهید. همچنین هربار تغییر در کدهای Angular، سبب refresh خودکار مرورگر نیز نمیشود که آنرا نیز باید خودتان به صورت دستی انجام دهید (کلیک بر روی دکمهی refresh پس از هر بار پایان کار ng build).
نکته 2: میتوان قسمت «الف» روش دوم را حذف کرد (حذف dotnet run در حالت watch). یعنی میخواهیم هنوز هم ویژوال استودیو کار آغاز IIS Express را انجام دهد. به علاوه میخواهیم برنامه را توسط ng serve مشاهده کنیم (با همان پارامترهای قسمت «ب» روش دوم). در این حالت تنها موردی را که باید تغییر دهید، پورتی است که برای IIS Express تنظیم شدهاست. عدد این پورت را میتوان در فایل Properties\launchSettings.json مشاهده کرد و سپس به تنظیمات فایل proxy.config.json اعمال نمود.
کدهای کامل این مطلب را از اینجا میتوانید دریافت کنید: ASPNETCoreIntegrationWithAngularCLI.zip
به همراه این کدها تعدادی فایل bat نیز وجود دارند که جهت ساده سازی عملیات یاد شدهی در این مطلب، میتوان از آنها استفاده کرد:
- فایل restore.bat کار بازیابی و نصب وابستگیهای پروژهی دات نتی و همچنین Angular CLI را انجام میدهد.
- دو فایل ng-build-dev.bat و ng-build-prod.bat بیانگر قسمت «الف» روش اول هستند. فایل dev مخصوص حالت توسعه است و فایل prod مخصوص ارائهی نهایی.
- دو فایل dotnet_run.bat و ng-serve-proxy.bat خلاصه کنندهی قسمتهای «الف» و «ب» روش دوم هستند.
1- نیاز به تواناییهای موجود در برنامههای Desktop را دارید اما همچنین نیاز است تا آنها را تحت وب نیز ارائه دهید.
یکی از دلایل اقبال به برنامههای تحت وب در سازمانها عدم نیاز به نصب آنها و توزیع هر چه سادهتر اینگونه برنامهها در شبکه است. تنها کافی است چند فایل را بر روی سرور به روز رسانی کنید و پس از آن تمام کلاینتها از آخرین نگارش برنامه شما بهرهمند خواهند شد (+). توزیع برنامههای سیلورلایت نیز به همین منوال است. علاوه بر آن استفاده از فناورهایی مانند MEF امکان ماژولار ساختن برنامه و دریافت آخرین ماژولهای تهیه شده (فایلهای XAP مجزای از برنامه به صورت افزونه) را بر اساس انتخاب و سطح دسترسی کاربر نیز میسر میسازد.
2- نیاز است تا یک برنامهی گرافیکی تمام عیار را تحت وب ارائه دهید.
تواناییهای XAML به همراه یکی از زبانهای دات نت جهت خلق جلوههای بصری، پویانمایی و گرافیکی بسیار بسیار فراتر از کتابخانههای جاوا اسکریپتی موجود هستند و نکتهی مهم آنها هم این است که لازم نیست حتما یک متخصص مثلا جاوا اسکریپت باشید تا بتوانید برای مثال پویانمایی را ارائه دهید. امکان استفاده از انواع و اقسام قلمها و قرار دادن آنها در برنامه، امکان استفاده از گرافیک برداری و غیره را نیز لحاظ کنید.
3- برنامهی شما نیاز است تا از طریق وب توزیع شود اما نیاز به سطح دسترسی بیشتری نسبت به یک برنامهی وب معمولی دارد.
تمام برنامههای توزیع شده از طریق مرورگرها محدود به سطوح دسترسی آنها نیز هستند. اما امکان نصب خارج از مرورگر برنامههای سیلورلایت نیز وجود دارد. در این حالت میتوان در صورت نیاز و همچنین تائید صریح کاربر، به سطوح دسترسی بیشتری دست یافت. برای مثال دسترسی به اسکنر در یک برنامهی وب متداول بیمعنا است. اما سیلورلایت 4 در حالت اجرای در خارج از مرورگر امکان تعامل با اشیاء COM را نیز دارد.
4- برنامهی وب شما نیاز است تا مدت زمان زیادی فعال باقی بماند.
یک برنامه دریافت ایمیل یا یک برنامه مونیتورینگ را در نظر بگیرید. اینگونه برنامهها باید مرتبا بدون نیاز به دخالت کاربر، فعال باقی بمانند و با سرور ارتباط داشته باشند. نوشتن اینگونه برنامهها با HTML و جاوا اسکریپت و فناوریهای مشابه واقعا مشکل بوده و نیاز به دانش فنی بالایی دارند. اما این مساله و حیات یک برنامه سیلورلایت تا زمانیکه مرورگر بسته نشده است جزو خواص اولیه اینگونه برنامهها است.
5- از مشکلات مدیریت حالت در برنامههای متداول وب به تنگ آمدهاید.
اگر برای مثال برنامه نویس ASP.NET باشید حتما با مباحث State management آشنایی دارید (از سشن و کوکی گرفته تا ViewState (ایی که همه به نحوی قصد کوچک کردن آنرا دارند!) و غیره). تمام اینها هم برای این است که بتوان تجربهی کاری برنامههای دسکتاپ را در محیط مرورگرها شبیه سازی کرد. این مشکلات در سیلورلایت حل شده است. یک برنامهی سیلورلایت State full است نه Stateless . همچنین اگر از حافظهای هم استفاده میکند این مورد در سمت کاربر است و نه سمت سرور و نه منقضی شدن زود هنگام سشنها و صدها ترفند برای مقیاس پذیری همین مسالهی بسیار کوچک با تعداد کاربران بالا در برنامههای متداول وب.
به عبارتی تصور کنید که برنامهی دسکتاپ سالهای قبل شما هم اکنون داخل مرورگر دارد اجرا میشود و چیزی به نام وب سرور وجود ندارد که پس از نمایش صفحهی وب شما، کلیهی اشیاء مرتبط با آنرا در سمت سرور تخریب کند چون باید پاسخگوی کاربران همزمان بیشماری باشد و منابع سرور هم محدود است. (سیلورلایت یک فناوری سمت کاربر است. بنابراین وب سرور صرفا نقش توزیع آنرا به عهده دارد یا حداکثر ارائهی یک وب سرویس جهت تعاملات بعدی مانند کار با بانک اطلاعاتی)
6- نیاز دارید تا برنامهی وب شما تحت تمام مرورگرها به یک شکل به نظر برسد و همچنین رفتار یکسانی هم داشته باشد.
هیچ وقت روزی را فراموش نمیکنم که حین پرداخت الکترونیکی بانک XYZ به کمک مرورگر فایرفاکس، دکمهی پرداخت در مرحلهی آخر، کار نمیکرد! هر چقدر روی آن کلیک میکردم اتفاقی نمیافتاد! تراکنش برگشت خورد و همین خرید ساده با مرورگر IE به سادگی انجام شد.
با سیلورلایت این مشکلات را نخواهید داشت زیرا کار نمایش برنامه شما توسط افزونهی مربوطه صورت میگیرد و این افزونه مستقل است از نوع مرورگر شما.
7- نیاز است برنامهی وب شما در حالت آفلاین هم کار کند.
برنامههای سیلورلایت تنها زمانیکه نیاز به دریافت یا ثبت اطلاعاتی از سرور داشته باشند، باید آنلاین باشند. همچنین این برنامهها دسترسی به مفهوم جدیدی به نام Isolated Storage دارند که در آن میتوان اطلاعات را به ازای هر کاربر آن هم با ضریب امنیتی بالا بر روی هارد شخص ذخیره کرد و زمان آنلاین شدن برنامه آنها را به سرور انتقال داد.
8- برنامه وب شما نیاز است تا با فایلهای مالتی مدیا تعامل داشته و آنها را پخش کند.
حتی تگ Video در HTML5 نیز به پای تواناییهای مالتی مدیا در Silverlight مانند smooth streaming, multicasting, editing, video brushes نمیرسد. برای مثال با استفاده از video brushes میتوان یک فایل ویدیویی در حال پخش را بر روی یک وجه یک شیء در حال پویانمایی نقاشی و نمایش داد.
9- نیاز به پشتیبانی از multi-touch در برنامهی وب شما وجود دارد.
برخلاف HTML ، تعاملات multi-touch در Silverlight میسر است.
10- نیاز به ایجاد برنامههای بازی تحت وب دارید.
به طور قطع میتوان بازییهایی در حد Pong را با جاوا اسکریپت هم ایجاد کرد، اما اگر نیاز به تولید بازیهایی جدیتر وجود داشت برای مثال انتقال بازی Quake به محیط وب، Silverlight در این زمینه هم حرفهای زیادی برای گفتن دارد (+).
11- نیاز به تولید برنامهی دسکتاپ چند سکویی دارید.
سیلورلایت هم اکنون تحت ویندوز، MAC OS-X ، لینوکس و ... پشتیبانی میشود (+). همچنین برنامههای سیلورلایت قابلیت اجرای در خارج از مرورگر را هم دارند.
با سیلورلایت دیگر نیازی نخواهد بود تا کاربران لینوکسی ابتدا Wine را نصب کنند تا بتوانند از یک برنامهی ویندوزی که انتقال پذیر نیست در لینوکس هم بتوانند استفاده کنند؛ چون پروژهی مون لایت لینوکسی برای این منظور مهیا است.
12- نیاز به تولید برنامههای تحت وب سریع و با کارآیی بالا دارید.
فایلهای نهایی Silverlight با توجه به ماهیت کامپایل شدهی آنها به طور قطع از کدهای جاوا اسکریپتی سمت کلاینت که باید توسط مرورگر تفسیر و پردازش شوند (و هر کدام هم از موتور خاص خودشان استفاده میکنند)، سریعتر اجرا میشوند (+).
13- از پیچیدگیهای پیاده سازی برنامههای متداول وب خسته شدهاید.
هنوز هم با تمام پیشرفتهای حاصل، تولید برنامههای وب پیشرفته مشکل است. از یک طرف ناسازگاری یک سری از مرورگرها با یک سری از قابلیتها را باید در نظر داشت، تا فراگیری فریم ورکهای Ajax و غیره تا مشکل بودن طراحی کنترلهای جدید فراتر از آن چیزی که HTML استاندارد ارائه میدهد. بله، به طور قطع دانش فنی بالایی در این زمینه در طی سالیان تولید شده است، اما باز هم فراگیری و تسلط به آنها زمان قابل توجهی را طلب میکند.
در سیلورلایت کلیه تعاملات با شبکه به صورت پیش فرض غیرهمزمان است (همان ایدهی اصلی Ajax) همچنین با توجه به state full بودن اینگونه برنامهها، عملا برنامه نویسها بدون درگیر شدن با مفاهیم اجکسی و مدیریت حالت، برنامهی پیشرفتهی وبی را در مدت زمان کوتاهی تولید کردهاند و این برنامه در تمام مرورگرهایی که قابلیت بارگذاری افزونهی سیلورلایت را دارند به یک شکل و کیفیت اجرا میشود.
14- در زمینه میزان مصرف پهنای باند ملاحظاتی ویژهای وجود دارد.
یک برنامهی سیلورلایت تنها یکبار باید دریافت شود. پس از آن در سمت کاربر کش خواهد شد (تا زمان به روز رسانی بعدی برنامه در سرور). همین مساله در دفعات بعدی مراجعه کاربر به سایت نقش قابل توجهی را در کاهش میزان مصرف پهنای باند (یا به قولی میزان کمتر data transfer) کلی دارد.
15- فرصت کافی برای فراگیری انبوهی از فناوریهای مختلف را ندارید!
بله! برای ایجاد یک برنامهی تحت وب که کاربر آن پس از مشاهده بگوید WOW نیاز است به HTML ، JS ، CSS ، AJAX ، یکی از فناوریهای سمت سرور و ... مسلط بود (علاوه بر اینکه باید بدانید فلان کد JS در IE کار میکند اما در فایرفاکس خیر. فایرفاکس فلان قسمت CSS را پشتیبانی میکند اما IE خیر! و ...).
اما برای استفاده از سیلورلایت فقط کافی است به XAML و یکی از زبانهای دات نت مانند سی شارپ یا VB.NET مسلط باشید (البته هیچ وقت از دست ASP.NET خلاص نخواهید شد! حداقل در حد راه اندازی یک وب سرویس یا مفاهیم امنیتی آن).
این مورد خصوصا برای افرادی که برنامه نویس دسکتاپ هستند اما علاقمندند تا برنامهی وب نیز تولید کنند بسیار مهم است. با حداقل آموزش میتوانند تواناییهای خود را به وب نیز گسترش دهند. علاوه بر آن عمدهی دانش Silverlight شما جهت تولید برنامههای WPF (با توجه به اینکه Silverlight فرزند WPF محسوب میشود) یا Windows phone 7 و غیره نیز میتواند بکار گرفته شود.
16- نیاز به اجرای کدهای چند ریسمانی در سمت کاربر دارید.
تا این لحظه پشتیبانی رسمی از مباحث چند ریسمانی در JavaScript و استانداردهای مرتبط با آن وجود ندارد. Silverlight به اکثر امکانات Threading موجود در دات نت فریم ورک دسترسی داشته و دانش فعلی شما قابل انتقال است.
و دست آخر باید به نکته اشاره کرد که هدف از Silverlight ساخت وب سایت معمولی نیست. این نوع کارها را با همان ابزارهای متداول انجام دهید. هدف اصلی آن ساخت برنامه است (Application در مقابل Web site). مشتریهای اصلی این نوع برنامهها هم بیشتر سازمانها و اینترانتهای پر سرعت و بستهی آنها هستند که نه نگران حجم افزونهی سیلورلایت هستند و نه مشکلی با حجم برنامهی سیلورلایت شما در یک شبکهی داخلی پر سرعت دارند.
Learn .NET MAUI while Creating a Contacts App in .NET 7 - YouTube
00:00:00 Introduction
00:02:54 What is .NET MAUI
00:06:13 Prepare Development Environment & Create first project.
00:11:50 Project Structure of .Net Maui
00:19:49 Three elements of stateful .Net Maui app
00:23:12 Page, Layout & View, Namespaces
00:32:23 URL based navigation - .Net Maui
00:50:31 Basics of ListView and Data Binding in .Net Maui
01:05:19 Events Handling of ListView in .Net Maui
01:16:15 Parameters in URL based Navigation & Static Repository in .Net Maui
01:34:56 Stacklayout for Edit Contact page in .Net Maui
01:52:08 View Contact Details & Update Contact (.Net Maui)
02:06:01 Observable Collection
02:14:19 Field Validation with .Net Maui CommunityToolkit
02:26:18 Reusable Control in .Net Maui
02:39:42 Grid Layout and Use reusable control in .Net Maui
02:52:44 ContextActions & MenuItems in ListView for .Net Maui
03:03:05 SearchBar in .NetMaui