نظرات مطالب
EF Code First #7
سلام
مدیریت روابط n-n در کلاسهای Poco به چه صورت است؟ من یک برنامه 2-tier دارم و برای Entity هایم state گرفتم و سمت کلاینت وضعیت entity‌ها رو مدیریت میکنم و سمت سرور اونا رو روی DBContext اعمال میکنم.
دو کلاس Role و Permission دارم که باهم رابطه n-n دارند؛ حال اگه یک Role  چند Permission داشته باشه و بخوام یکی از اونا رو حذف کنم و یا آپدیت کنم بهم پیغام خطا میده(An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single e ...) و داخل inner exception هم مینویسه ()Violation of PRIMARY KEY constraint 'PK_dbo.SecurityRolePermission'. Cannot insert duplicate key in object 'dbo.SecurityRolePermission'
یعنی در حالتهای آپدیت و حذف هم میخواد insert انجام بده (با ef profiler هم چک کردم)البته فکر کنم تا حدودی معلوم باشه چرا اینکار رو میکنه؛ چون مدیریتی روی state اون کلاس واسط(RolePermission) انجام نمیشه، ممکنه بگید چطوری این مشکل رفع میشه؟
نظرات مطالب
EF Code First #2
لطف کنید سؤالی رو که مطرح می‌کنید در حیطه مطلب جاری عنوان شده باشد و خارج از آن نباشد.
سؤال شما هم بحث کلاینت سروری است و نه بحث کلاینت تنها که EF روی آن مشغول به کار است.
- می‌شود در متد Seed ایی که در بالا توضیح دادم در SQL Server تریگر درست کرد. (که مثلا اگر کاربر دیگری به شرط اینکه این کاربر جزو کاربران تعریف شده در خود SQL Server باشد نه در برنامه شما، اتفاق خاصی رخ دهد. برنامه شما هم بدیهی است باید سرور را مدام چک کند تا از این مساله مطلع شود)- SQL Server مبحثی دارد به نام Service Broker : (^). توسط آن می‌توان از طریق سرور به کلاینت اطلاع رسانی کرد. بازهم خارج است از بحث یک ORM. یا تمام ORMهای موجود. - EF مبحثی دارد به نام Concurrency check که اگر شخصی در شبکه بر روی رکوردی که همین الان شما مشغول به کار هستید، تغییری را ایجاد کرد، به شما اطلاع رسانی کند. (در قسمت‌های بعدی بحث خواهد شد). البته این هم خودکار نیست. لازم است یک رفت و برگشت به سرور انجام شود.- entity framework auditing هم میسر است. خودکار نیست. در همان کلاس Context فوق که از DbContext مشتق می‌شود می‌توان متد تحریف شده public override int SaveChanges را تعریف کرد. در اینجا می‌توان به تمام تغییراتی که قرار است اعمال شوند دسترسی داشت. مثلا آن‌ها را در یک جدول مجزا ثبت کرد. بدیهی است برنامه بعدا نیاز خواهد داشت از این جدول گزارشگیری کند.
نظرات مطالب
متغیرهای استاتیک و برنامه‌های ASP.NET
آیا این امکان وجود دارد که یک متغییر که دارای ویژگی ThreadStatic است توسط دو Thread همزمان مورد استفاده قرار بگیرد؟ جواب Microsoft خیر است. پس اینچنین متغییری نیاز به ThreadSafe بودن و حتی lock (فارق از محیط اجرا) ندارد. مگر اینکه راه دیگری برای اجرای چند کد به صورت موازی در یک AppDomain علاوه بر Thread وجود داشته باشد. به عبارت دیگر من Thread را Atomic ترین شی موازی‌سازی می‌دانم. اشتباه می‌کنم؟

البته اینکه یک Thread لزوماً برای درخواستی بعدی استفاده نشود نیز مشکلی ایجاد نمی‌کند.

لینک‌ها را مطالعه کردم. ولی بازهم فکر می‌کنم مشکلی در استفاده از این روش نیست! با توجه به جمله‌ای که در بالا گفتم نمی‌دانم چه مشکلی می‌تواند از نظر Concurrency اتفاق بیفتد؟

در مورد تست، من هم با شما موافقم و تست کردن فقط با یک کاربر در یک مرورگر را مطمئناً تست کاملی نمی‌دانم. درواقع فقط با بررسی نقاط بحرانی و حالت‌های بحرانی در ذهنم موارد Concurrent را چک کرده‌ام. که البته حتماً سعی می‌کنم با استفاده از یک نرم‌افزار خوب یک محیط چند کاربره را شبیه‌سازی کنم.

راستی یک نکته خیلی مهم. در این روش هر شیی که DataContext را برای اولین بار به وجود آورده باید بعد از اتمام کارش خودش آنرا Dispose کند. تمامی عملیات کار با داده در یک بلاک using صورت می‌گیرد اما شیی که در using استفاده شده مانند یک شی Repository است که مدیریت DataContext را برعهده دارد اما در داخل تفاوت‌هایی برای بالابردن کارایی دارد.

البته اسرار من بر این روش به جای استفاده از HttpContext این است که: لایه دسترسی به داده به صورت BlackBox کاملا از لایه Presentaion جدا باشد. درواقع بدون پیاده‌سازی یک Interface یا چیزی شبیه آن بتوان از یک لایه داده «همزمان» توسط چند لایه دیگر (در یک پروژه) استفاده شود و البته برنامه‌نویس به دردسر نیفتد.
نظرات مطالب
چه زمانی بهتر است از Silverlight استفاده شود؟
- بله. هدفگیری اصلی سیلورلایت 4 ، LOB‌ است یا به قولی line of business applications . اگر به کتاب‌های سال 2010 مراجعه کنید تعداد کتاب‌هایی که در مورد LOB و SL4 منتشر شده قابل توجه است:
Pro Business Applications with Silverlight 4 - APress
Silverlight 4 Data and Services Cookbook - Packt Publishing
Microsoft Silverlight 4 Business Application Development - Packt Publishing
و ...

با استفاده از WCF RIA Services یا حتی WCF Services و غیره دسترسی کامل برای مثال به entity framework خواهید داشت. همچنین کاربران شما مجددا به تجربه‌ی کار با برنامه‌های دسکتاپ باز خواهند گشت، هر چند برنامه تحت وب است. قابلیت نصب خارج از مرورگر را هم دارد (مثل یک برنامه دسکتاپ معمولی).

- برای خارج از سازمان هم مشکلی نیست. چون برنامه شما یکبار فقط باید دریافت شود. بعد کش می‌شود و افزونه‌ی سیلورلایت به صورت خودکار هربار چک می‌کند که آیا برنامه روی سرور تغییر کرده یا نه. اگر خیر از کش خوانده خواهد شد و کاربر راه دور معطل نخواهد شد. همچنین با استفاده از MEF (managed extensibility framework) می‌شود قسمت‌های مختلف برنامه را به صورت افزونه درآورد. یعنی کاربری که نیاز به تمام قسمت‌ها را ندارد خوب لزومی هم ندارد که همه‌ی آن‌ها را دریافت کند.
مطالب
بررسی سایز و پسوند فایل آپلود شده قبل از ارسال به سرور
می توان قبل از اینکه کاربر فایلی را سمت سرور ارسال کند پسوند فایل را چک کرد و از یک رفت و برگشت بیهوده به سرور جلوگیری کرد .
یک پیاده سازی ساده به کمک jQuery :
var ext = $('#my_file_field').val().split('.').pop().toLowerCase();
if($.inArray(ext, ['gif','png','jpg','jpeg']) == -1) {
    alert('invalid extension!');
}
 
 در کد بالا ابتدا پسوند فایل انتخاب شده توسط کاربر پیدا می‌شود ، سپس به کمک متد inArray با آرایه ای از پسوند‌های دلخواه ما مقایسه می‌شود و در صورت معتبر نبودن پیغامی به کاربر نشان می‌دهد.
کد بالا را می‌توان در رویداد Change کنترل فایل یا در هنگام Post شدن Form اطلاعات قرار داد.
کاملا واضح است که این روش را می‌توان به راحتی دور زد و نباید به آن اکتفا کرد.
مثال این روش را اینجا بررسی کنید.
بررسی سایز فایل :
در اکثر برنامه‌های تحت وب کاربرها محدود به Upload فایل تا سایز خاصی هستند ، این مورد را هم می‌توان قبل از Upload کنترل و اعتبارسنجی کرد : 
//binds to onchange event of your input field
$('#myFile').bind('change', function() {

  //this.files[0].size gets the size of your file.
  alert(this.files[0].size);

});
این روش تا زمانی که کاربر JavaScript را غیر فعال نکرده قابل اطمینان است.
مطالب
خلاصه‌ای کاربردی در مورد Observable collection

Observable collection در WPF را می‌توان نوعی لیست جنریک ویژه تعریف کرد که زمانیکه به کنترلی بایند شد، کنترل را از تغییرات خودش آگاه می‌کند. برای مثال اگر آیتمی به این لیست اضافه شد بلافاصله آن آیتم را در کنترل مقید به آن نیز خواهید دید، به همین ترتیب در مورد ویرایش و یا حذف یک آیتم، بدون نیاز به کوچکترین تماسی با کنترل مورد نظر. برای مثال اگر مقدار یک خاصیت را تغییر دادید، بلافاصله بدون اینکه به کنترل مقید به آن اعلام کنیم که لطفا این مورد ویژه را برای من تغییر بده، شاهد نتیجه‌ی نهایی خواهیم بود.



اما استفاده‌ی پیشرفته از این لیست جنریک ویژه به همینجا ختم نشده و حین اضافه کردن کمی پیچیدگی به برنامه مشکلات عدیده‌ای بروز می‌کنند که آن‌ها را جهت دسترسی ساده‌ی بعدی در زیر لیست می‌کنم:

الف) اصلا Observable collection چیست؟ چکار می‌کند؟
List vs ObservableCollection vs INotifyPropertyChanged in Silverlight

ب) نمی‌توانم از این مجموعه‌ی اشیای خودآگاه سازنده در یک ترد استفاده کنم. مشکل کجاست؟
این روزها نمی‌توان یک برنامه‌ی دسکتاپ خوب را بدون استفاده از تردها متصور شد. اما به محض سعی در به روز رسانی این لیست جنریک در یک ترد دیگر (ترد دیگر منظور هر تردی بجز ترد اصلی برنامه است که کار مدیریت رابط کاربر را به عهده دارد) خطای زیر ظاهر می‌شود:
This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread

راه حل:
Adding to an ObservableCollection from a background thread

ج) یکی از خاصیت‌های یک شیء این لیست جنریک ویژه را تغییر داده‌ام. اما هیچ تغییری در کنترل بایند شده به آن مشاهده نمی‌کنم. مشکل در کجاست؟
راه حل: پیاده سازی اینترفیس INotifyPropertyChanged را فراموش کرده‌اید:
Data Binding in WPF with the Monostate Pattern

د) خوب، این که خیلی دردسر دارد! راه ساده‌تری برای تعریف این موارد نیست؟!
هوشمندانه‌ترین روشی که برای حل این مساله تابحال دیده‌ام:
An easier way to manage INotifyPropertyChanged

ه) زمانیکه این یک لیست جنریک خودآگاه سازنده را به یک مثلا listview بایند می‌کنم، دیگر نمی‌توانم با استفاده از متد clear items آن کنترل، نسبت به خالی کردن نمای ظاهری آن اقدام کنم. چکار باید کرد؟
خطای مشاهده شده:
Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead

راه حل:
همان Observable collection اصلی را تخلیه کنید، UI به صورت خودکار به روز خواهد شد.

و) اضافه کردن رنجی از اطلاعات به آن به صورتی یکباره ممکن است کند باشد. چه باید کرد؟
راه حل:
AddRange for ObservableCollection in Silverlight 3


بازخوردهای دوره
طراحی روابط و ارجاعات در RavenDB
Timeline یک جدول نیست؛ یک گزارش هست از اطلاعات موجود (گزارش از اینکه یک کاربر به چه بلاگ‌هایی علاقمند است). به ازای هر View جدید مورد نیاز از بانک اطلاعاتی، یک جدول جدید ایجاد نمی‌کنند. همچنین در اینجا چیزی به نام جدول نداریم. این بانک اطلاعاتی، سندگرا است. هر رکورد آن یک سند JSON است و مجموعه‌ای از آن‌ها تا حدودی شبیه به یک جدول بانک اطلاعاتی رابطه‌ای است (تا حدودی از این جهت که هر سند JSON آن می‌تواند ساختار متفاوتی با قبلی داشته باشد، یا نداشته باشد؛ بسته به انتخاب و طراحی). در مورد «denormalized references» در متن بحث شده: «... بنابراین بهترین حالت استفاده از روش denormalized references محدود خواهد شد به موارد ذیل ... ». یعنی همه جا قرار نیست کار رفع نرمال سازی در بانک‌های اطلاعاتی NoSQL سندگرا انجام شود. سه مورد مهم دارد که در بحث ذکر شده‌است.
در اینجا برای طراحی حالت بلاگ‌های مورد علاقه یک شخص در RavenDB فقط کافی است از مفهوم Includes آن استفاده کنید (نمونه آن «Includeهای یک به چند» در بحث). داخل کلاس User، یک آرایه شبیه به SupplierIds (مثال زده شده) به نام FavoriteBlogIds خواهید داشت. بارگذاری و گزارشگیری از آن برای نمایش لیست این بلاگ‌ها و سپس مطالب آن‌ها، مانند مثال‌های Include و Load ایی است که ارائه شد.
بنابراین در اینجا به چیزی مانند دو جدول مجزای کاربران و جدول ذخیره سازی لیست بلاگ‌های محبوب آن‌ها نیازی نیست. لیست و آرایه Idهای بلاگ‌های مورد علاقه‌ی یک کاربر، داخل سند JSON همان کاربر قرار می‌گیرد.
نظرات مطالب
چگونگی گزارشگیری از Business Objects مانند List توسط StimulSoft
این روش بسیار زمانبر است؛ تصور کنید می‌خواهید از چندین جدول با تعداد فیلد‌های زیاد گزارش‌های مختلف تهیه کنید. اگر قرار به ایجاد دستی همه‌ی این فیلد‌ها در BO باشد که فاتحه وقت شما خوانده است و همچنین احتمال خطای شما در انتخاب نام و نوع فیلد بسیار خواهد بود.
برای انجام بهتر این کار در Stimul Report باید ابتدا لیست جنریک مورد نظر را به گزارش ارسال کنیم و سپس آن را در حالت Design نمایش داده و پس از ایجاد عناصر گزارش آن را در محل مورد نظر ذخیره نماییم. (لیست ارسالی به صورت خودکار در گزارش‌ساز نشان داده خواهد شد و تنها کاری که باید کنید گرفتن و کشیدن فیلدهای مورد نظر به داخل Data-Header-Footer ریپورت است).
برای مثال (با فرض استفاده از reportViewer):
stiReportMain.Dictionary.Report.BusinessObjectsStore.Clear();
reportViewer.Report.BusinessObjectsStore.Clear();
stiReportMain.RegBusinessObject("MyCategory", "documents", list);
stiReportMain.Design();
(کد فوق فقط برای طراحی گزارش است و باید یکبار اجرا شود).
پس از اجرای برنامه و طراحی گزارش مورد نظر آن را ذخیره می‌کنیم و برای استفاده کافی‌است از کد زیر استفاده کنیم:
stiReportMain.Dictionary.Report.BusinessObjectsStore.Clear();
reportViewer.Report.BusinessObjectsStore.Clear();
stiReportMain.RegBusinessObject("MyCategory", "documents", list);
stiReportMain.Dictionary.SynchronizeBusinessObjects();
stiReportMain.Compile();
stiReportMain.RenderWithWpf(true); //Or Render();
نکته ۱: documents لیست جنریک دریافتی از EF یا هر ORM دیگست.
نکته ۲:در صورتی که از شی StiReport استفاده کنید حتی نیاز به دادن آدرس فایل گزارش نخواهید داشت و فایل گزارش درون برنامه شما ذخیره خواهد شد. برای ویرایش آن نیز می‌توانید از فلش ظاهر شده کنار StiReport آن را ویرایش و مجددا ذخیره کنید.
مطالب
با کمک link blog ها در زمان خود صرفه جویی کنید

این مطلب در حقیقت خلاصه و چکیده‌ی RSS‌ خوانی‌های دو سال اخیر بنده است.
برخلاف فوروم‌های ایرانی که سعی می‌کنند نقش تمام رسانه‌ها را به صورت یکجا بازی کنند، برای مشاهده مقالات جدید یا اخبار به روز فناوری‌های مرتبط، راهی بجر وبلاگ خواندن وجود ندارد (یک استثناء اینجا وجود دارد و آن‌هم مباحث وارز است. در این یک مورد هم بیشتر فوروم‌های خارجی فعال هستند تا وبلاگ‌های آن‌ها).
خوب، در ابتدا هر سایتی که به نظر با کیفیت است به لیست RSS reader ما اضافه می‌شود و همینطور هر روز این لیست بیشتر و بیشتر خواهد شد. ابتدا روزی نیم ساعت RSS خوانی خواهید داشت بعد می‌شود روزی 2 ساعت و بعد از یک مدتی هم از کنترل خارج می‌شود.
در لابلای تمام این سایت‌هایی که من الان جمع آوری کرده‌ام و تعدادشان به چند هزار(!) می‌رسد، چند سایت (حدود 30 سایت) هستند که اصطلاحا link blog نام دارند و به صورتی پیوسته، خلاصه‌ی مفید وبلاگ‌های روز را ارائه می‌دهند (که پشتکار آن‌ها قابل ستایش است).
اکنون کار من بجای روزی چند ساعت زیر و رو کردن مطالب RSS feed وبلاگ‌هایی که ثبت کرده‌ام، صرفا به مرور سریع این link blog ها خلاصه می‌شود و انصافا گنجینه‌ای با ارزش هستند (خصوصا از این جهت که کار دست بوده و خودکار تهیه نمی‌شوند).
برای import ساده‌ی این لیست، فایل opml آن‌ها ‌را از آدرس زیر می‌توانید دریافت کنید.


این مجموعه برای راه اندازی یک سایت خبری کفایت می‌کند ...

نظرات مطالب
اعتبارسنجی مبتنی بر JWT در ASP.NET Core 2.0 بدون استفاده از سیستم Identity
سلام. وقت بخیر. من سیاست دسترسی پویا رو به jwt اضافه کردم. کلیه Claimها رو  به accesstoken اضافه میکنم و درست هم عملیات دسترسی چک میشود.
{"jti":"26bdfd20-104f-45d4-a4e1-111044808041",
"iss":"http://localhost:5000/",
"iat":1531729854,
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier":"1",
"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name":"Vahid",
"DisplayName":"وحید",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/serialnumber":"046fb152a7474043952475cfa952cdc9",
"http://schemas.microsoft.com/ws/2008/06/identity/claims/userdata":"1",
"DynamicPermission":[":MyProtectedApi2:Get",
":MyProtectedEditorsApi:Get",
":MyProtectedApi3:Get",
":MyProtectedApi4:Get"],
"http://schemas.microsoft.com/ws/2008/06/identity/claims/role":["Admin",
"Editor",
"User"],
"nbf":1531729855,
"exp":1531729975,
"aud":"Any"}
 فقط این Claimها که در توکن اضافه میشود در سمت سرور از روی توکن ارسالی کاربر چک میشود؟
 public bool CanUserAccess(ClaimsPrincipal user, string area, string controller, string action)
        {
            var currentClaimValue = $"{area}:{controller}:{action}";
            var securedControllerActions = _mvcActionsDiscoveryService.GetAllSecuredControllerActionsWithPolicy(ConstantPolicies.DynamicPermission);
            if (!securedControllerActions.SelectMany(x => x.MvcActions).Any(x => x.ActionId == currentClaimValue))
            {
                throw new KeyNotFoundException($@"The `secured` area={area}/controller={controller}/action={action} with `ConstantPolicies.DynamicPermission` policy not found. Please check you have entered the area/controller/action names correctly and also it's decorated with the correct security policy.");
            }

            if (!user.Identity.IsAuthenticated)
            {
                return false;
            }

            if (user.IsInRole("Admin"))
            {
                // Admin users have access to all of the pages.
                return true;
            }

            // Check for dynamic permissions
            // A user gets its permissions claims from the `ApplicationClaimsPrincipalFactory` class automatically and it includes the role claims too.


            //for check user has claim for access to action
            return user.HasClaim(claim => claim.Type == ConstantPolicies.DynamicPermissionClaimType &&
                                          claim.Value == currentClaimValue);
        }
امکان دستکاری توسط کاربر وجود ندارد؟ اگر اینطور است چطور این دسترسی‌ها رو در سمت سرور بعد از login در حافظه سرور ذخیره کنیم برای دفعات بعد؟