npm install @angular/cdk
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { DragDropModule } from '@angular/cdk/drag-drop'; import { FormsModule } from '@angular/forms'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, FormsModule, DragDropModule ], bootstrap: [ AppComponent ] }) export class AppModule {}
<div cdkDrag> I'm Draggable </div>
<div cdkDrag cdkDragLockAxis="x"> I'm Draggable </div>
در ابتدا یک مدل را ایجاد میکنیم:
export interface Todo { title: string; type?: string; }
فایل app.component.ts
export class AppComponent implements OnInit { public title = 'Darg and drop'; public model: Todo; public todo: Todo[]; public done: Todo[]; public cancelled: Todo[]; ngOnInit(): void { this.setDefalutValue(); } addItem(form, $event: Event) { $event.preventDefault(); if (form.valid) { if (this.model.type === 'todo') { this.todo.push({ title: this.model.title }); } else { this.done.push({ title: this.model.title }); } } else { alert('فرم معتبر نمیباشد . عنوان را وارد نمایید'); } } drop(event: CdkDragDrop<Todo[]>) { if (event.previousContainer === event.container) { moveItemInArray(event.container.data, event.previousIndex, event.currentIndex); } else { transferArrayItem(event.previousContainer.data, event.container.data, event.previousIndex, event.currentIndex); } } private setDefalutValue() { this.todo = [ { title: 'خرید مواد غذایی' }, { title: 'رفتن به خانه' }, { title: 'خوابیدن' } ]; this.done = [ { title: 'بیدار شدن' }, { title: 'مسواک زدن' }, { title: 'دوش گرفتن' }, { title: 'چک کردن ایمیل' } ]; this.cancelled = []; this.model = { title: null, type: 'todo' }; } }
در اینجا 3 آرایه یکی برای to-do و یکی برای Done و دیگری برای Cancelled ایجاد میکنیم و به هر کدام تعدادی آیتم را اضافه میکنیم.
addItem : زمانیکه فرم را submit میکنیم اجرا میشود .
drop : زمانی اجرا میشود که یک آیتم را Drag and Drop کنیم. در ایجا شرط event.previousContainer === event.container زمانی درست است که جابجایی در درون یک لیست باشد و هدف در این صورت، مرتب سازی است .
moveItemInArray : ایندکس آیتمها را در همان لیست تغیر میدهد (مرتب سازی).
transferArrayItem: آیتم را از یک لیست حذف و به لیست دیگری اضافه میکند.
فایل app.component.html
<div> <!-- فرم --> <div> <fieldset> <legend> اضافه کردن آیتم جدید </legend> <form #form="ngForm" (submit)="addItem(form,$event)"> <label></label> <input type="text" required name="title" #name="ngModel" [(ngModel)]="this.model.title"> <label></label> <select required name="type" #type="ngModel" [(ngModel)]="this.model.type"> <option value="todo"> انجام دادن </option> <option value="done"> انجام شده </option> </select> <input type="submit" value="ذخیره"> </form> </fieldset> </div> <!-- آیتمها --> <div> <fieldset> <legend> لیست آیتمها </legend> <div> <!-- انجام دادن --> <div> <p> انجام دادن </p> <div cdkDropList #todoList="cdkDropList" [cdkDropListData]="todo" [cdkDropListConnectedTo]="[doneList, cancelledList]" (cdkDropListDropped)="drop($event)"> <div *ngFor="let item of todo" cdkDrag> <p> {{ item.title | titlecase }} </p> </div> </div> </div> <!-- انجام شده --> <div> <p> انجام شده </p> <div cdkDropList #doneList="cdkDropList" [cdkDropListData]="done" [cdkDropListConnectedTo]="[todoList, cancelledList]" (cdkDropListDropped)="drop($event)"> <div *ngFor="let item of done" cdkDrag> <p> {{ item.title | titlecase }} </p> </div> </div> </div> <!-- انجام نشده --> <div> <p> انجام نشده </p> <div cdkDropList #cancelledList="cdkDropList" [cdkDropListData]="cancelled" [cdkDropListConnectedTo]="[todoList, doneList]" (cdkDropListDropped)="drop($event)"> <div *ngFor="let item of cancelled" cdkDrag> <p> {{ item.title | titlecase }} </p> </div> </div> </div> </div> </fieldset> </div> </div>
در ابتدا یک فرم داریم که در اینجا همه چیز مشخص است ( فرمهای مبتنی بر قالبها در Angular )
در ادامه 3 container را ایجاد میکنیم یکی برای to-do و یکی برای Done و در آخر یکی برای Cancelled
container ایجاد شده برای to-do :
<div cdkDropList #todoList="cdkDropList" [cdkDropListData]="todo" [cdkDropListConnectedTo]="[doneList, cancelledList]" (cdkDropListDropped)="drop($event)"> <div *ngFor="let item of todo" cdkDrag> <p> {{ item.title | titlecase }} </p> </div> </div>
توضیحات:
cdkDropList : یک container میباشد، برای آیتمهایی که قرار است Drag and Drop شوند.
todoList #:
id مربوط به container را مشخص میکند.
cdkDropListConnectedTo:
id مربوط به container های دیگری که میتواند آیتم های container جاری را بپذیرد.
cdkDropListData: مشخص کنند منبع داده است.
cdkDropListDropped: این رویداد زمانی اجرا میشود که Drag and Drop برای یک آیتم انجام شود.
cdkDrag: برای اینکه آیتمهای درون یک container قابلیت Drag and Drop را داشته باشند، این دایرکتیو را اضافه میکنیم.
تمام !
عدم authorization بر اساس Permissions
اگر میخواهید متد User.IsInRole به فیلد Permissions شما واکنش نشان دهد، باید لیست مربوطه، به لیست نقشها یا Claims آن کاربر اضافه شود. در غیراینصورت کار نمیکند ( فیلتر Authorize هم به همین صورت).
- Mvc5AuthorizeAttribute.cs دقیقا همان فیلتر Authorize اصلی است که برای واکنش نشان دادن به اطلاعات AJax ایی طراحی شده و اصلا اطلاعات Permissions را بررسی نمیکند.
- فیلتر Mvc5ClaimAccessAuthorizeAttribute.cs به اطلاعات Claim خاصی واکنش نشان میدهد.
استفاده از توابع Scalar بجای case
ظاهراً در تعداد رکوردهای پایین مشکلی نداره اما در تعداد رکوردهای بالا احتمال کاهش سرعت اجرا دور از ذهن نیست. به هر حال من دقیق تست نکردم اما روی شیوه دیگه هم دارم کار میکنم که اون توابع برگشتی از نوع جدول هست که با این شیوه اساساً فرق داره
معرفی پروژه Orchard
متغیرهای استاتیک و برنامههای ASP.NET
در کار شما آیا این لیست برای تمام کاربران یکسان است؟ آیا سطح دسترسی در کار نیست؟ آیا همه موارد مشابهی را مشاهده میکنند؟ اگر بله مشکلی ندارد، فقط در نظر داشته باشید که متغیرهای استاتیک thread safe نیستند. برای این موارد کلاس Cache قرار گرفته در فضای نام System.Web.Caching ، مطابق مستندات آن Thread safe است و read/write آن در یک محیط چند کاربره مشکل زا نیست: (+)
ضمنا در مورد طراحی سیستم چت خوب در ASP.NET در مورد COMET تحقیق کنید. این روش سربار کمی دارد چون سرور به کلاینت پیغام ارسال میکند نه اینکه کلاینت متناوبا سرور را چک کند که آیا پیغام جدیدی هست یا نه: (+)
تفاوت Desktop Application با Web Application
مدیریت سفارشی سطوح دسترسی کاربران در MVC
من کل مطالب Mvc 18 و بخش کوکیها را مطالعه کردم اما به دلیل نظرات مختلف متوجه نشدم راه اصولی چیه؟
برای هر کاربر یکسری اطلاعات وجود دارد که میشه در کوکیها ذخیره کرد مثل نام کاربری یا هر چیز دیگه ای که حتی اگر کاربر آنها را تغییر بده مهم نیستند و صرفا جنبه نمایش در صفحات را دارند اما یکسری اطلاعات هست که خیلی مهمه هستند مثل این که این کاربر مدیر هست یا خیر. این اطلاعات یا باید هر بار که نیاز هست از دیتابیس یا هر منبع دیگه ای واکشی بشه ویا در جایی ذخیره بشه که هر وقت خواستیم به اون دسترسی داشته باشیم.
پیشتر این نوع اطلاعات و در Session ذخیره میکردیم که از دید کاربر به دور بود ، اما برای پردازش موازی و انجام چک لیست تهیه شده بهتره که از Sessionها استفاده نشه،
خب حالا ذخیره این اطلاعات در کوکیها درسته؟ حتی اگر کد بشن باز خطرناکه ، چرا که یک کاربر اگر بتونه کوکی که مدیر بودن یا نبودن کاربر را مشخص میکند را تغییر بده میتونه به همه بخشها دسترسی پیدا کنه!
از طرفی صرفا مدیر بودن یا نبودن یک کاربر مطرح نیست ، اطلاعات زیادی هستند که مهم هستند و ذخیره اونها در Session میتونه منابع سرور و به خودش مشغول کنه!
روش درست چیه؟
- بهینه سازی زمان آغاز به کار برنامه
- کاهش صفحات کاری برنامه: از آنجا که برنامه از قبل کامپایل شده، فراهم کردن صفحه بندی از ابتدای کار امر چندان دشواری نخواهد بود؛ لذا در این حالت صفحه بندی حافظه به صورت پویاتری انجام میگردد. شیوهی کار به این صورت است که اسمبلیها به چندین پروسهی کاری کوچکتر تبدیل شده تا صفحه بندی هر کدام جدا صورت گیرد و محدودهی صفحه بندی کوچکتر میشود. در نتیجه کمتر نقصی در صفحه بندی دیده شده یا کلا دیده نخواهد شد. نتیجهی کار هم در یک فایل ذخیره میگردد که این فایل میتواند نگاشت به حافظه شود تا این قسمت از حافظه به طور اشتراکی مورد استفاده قرار گیرد و بدین صورت نیست که هر پروسهای برای خودش قسمتی را گرفته باشد.
%SystemRoot%\Assembly\NativeImages_v4.0.#####_64
معایب
احتمالا شما پیش خود میگویید این مورد فوق العاده امکان جالبی هست. کدها از قبل تبدیل شدهاند و دیگر فرآیند جیت صورت نمیگیرد. در صورتیکه ما تمامی امکانات یک CLR مثل مدیریت استثناءها و GC و ... را داریم، ولی غیر از این یک مشکلاتی هم به کارمان اضافه میشود که در زیر به آنها اشاره میکنیم:
عدم محافظت از کد در برابر بیگانگان: بعضیها تصور میکنند که این کد را میتوانند روی ماشین شخصی خود کامپایل کرده و فایل ngen را همراه با آن ارسال کنند. در این صورت کد IL نخواهد بود ولی موضوع این هست اینکار غیر ممکن است و هنوز استفاده از اطلاعات متادیتاها پابرجاست به خصوص در مورد اطلاعات چون reflection و serializationها . پس کد IL کماکان همراهش هست. نکتهی بعدی اینکه انتقال هم ممکن نیست؛ بنا به شرایطی که در مورد بعدی دلیل آن را متوجه خواهید شد.
از سینک با سیستم خارج میشوند: موقعیکه CLR، اسمبلیها را به داخل حافظه بار میکند، یک سری خصوصیات محیط فعلی را با زمانیکه عملیات تبدیل IL به کد ماشین صورت گرفته است، چک میکند. اگر این خصوصیات هیچ تطابقی نداشته باشند، عملیات JIT همانند سابق انجام میگردد. خصوصیات و ویژگیهایی که چک میشوند به شرح زیر هستند:
- ورژن CLR: در صورت تغییر، حتی با پچها و سرویس پک ها.
- نوع پردازنده: در صورت تغییر پردازنده یا ارتقا سخت افزاری.
- نسخه سیستم عامل : ارتقاء با سرویس پک ها.
- MVID یا Assemblies Identity module Version Id: در صورت کامپایل مجدد تغییر میکند.
- Referenced Assembly's version ID: در صورت کامپایل مجدد اسمبلی ارجاع شده.
- تغییر مجوزها: در صورتی که تغییری نسبت به اولین بار رخ دهد؛ مثلا در قسمت قبلی در مورد اجازه نامه اجرای کدهای ناامن صحبت کردیم. برای نمونه اگر در همین اجازه نامه تغییری رخ دهد، یا هر نوع اجازه نامه دیگری، برنامه مثل سابق (جیت) اجرا خواهد شد.
پی نوشت: در آپدیتهای دات نت فریم ورک به طور خودکار ابزار ngen صدا زده شده و اسمبلیها مجددا کمپایل و دخیره میشوند و برنامه سینک و آپدیت باقی خواهد ماند.
پس حتما نسخهی ngen شده و غیر ngen را بررسی کنید و کارآیی هر دو را با هم مقایسه کنید. برای بسیاری از برنامهها کاهش صفحه بندی یک مزیت و باعث بهبود کارآیی میشود. در نتیجه در این قسمت ngen برنده اعلام میشود.
توجه کنید برای سیستمهایی که در سمت سرور به فعالیت میپردازند، از آنجا که تنها اولین درخواست برای اولین کاربر کمی زمان میبرد و برای باقی کاربران درخواست با سرعت بالاتری اجرا میگردد و اینکه برای بیشتر برنامههای تحت سرور از آنجا که تنها یک نسخه در حال اجراست، هیچ مزیت صفحه بندی را ngen ایجاد نمیکند.
برای بسیاری از برنامههای کلاینت که تجربهی startup طولانی دارند، مایکروسافت ابزاری را به نام Managed Profile Guided Optimization Tool یا MPGO .exe دارد. این ابزار به تحلیل اجرای برنامه شما پرداخته و بررسی میکند که در زمان آغازین برنامه چه چیزهایی نیاز است. اطلاعات به دست آمده از تحلیل به سمت ngen فرستاده شده تا کد بومی بهینهتری تولید گردد. موقعیکه شما آماده ارائه برنامه خود هستید، برنامه را از طریق این تحلیل و اجرا کرده و با قسمتهای اساسی برنامه کار کنید. با این کار اطلاعاتی در مورد اجرای برنامه در داخل یک پروفایل embed شده در اسمبلی، قرار گرفته و ngen موقع تولید کد، این پروفایل را جهت تولید کد بهینه مطالعه خواهد کرد.
در مقالهی بعدی در مورد FCL صحبتهایی خواهیم کرد.