public class ModelStateFeatureFilter : IAsyncActionFilter { public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { var state = context.ModelState; // store state ... await next(); } }
مدیریت Instance در WCF
یه سوالی برام پیش اومده ممنون میشم راهنمایی فرمایید:
من یک سرویس WCF ایجاد کردم و اونو به شکل زیر تنظیم کردم :
[ServiceContract(SessionMode=SessionMode.Reqquired)]
[ServiceBehavior( InstanceContextMode = InstanceContextMode.PerSession)]
ممنون میشم راهنمایی نمایید
مدل EAV چیست؟
EAV مخفف ( Entity Attribute Value ) میباشد، مدلی از طراحی دیتابیس که کاربر را به آیتمهای ثابت محدود نمیکند، فرض کنید در یک فروشگاه میخواهید چندین کالا بفروشید هر کالا هم برای خودش ویژگیهای منحصر به فرد دارد، آیا با ویژگیهای ثابت برای کالاهای متفاوت میتوان پاسخگوی نیاز مشتری بود؟ یقینا پاسخ منفی خواهد بود.
موجودیت ( Entity ): در یک سیستم میتواند کالا، مشتری، فروشنده و... باشد.ویژگی ( Attribute ):برای کالا: رنگ، وزن و... برای مشتری:نام، تلفن،آدرس و... میباشد
مقدار( value ) : هر ویژگی برابر مقداری میباشد مثلا برای رنگها آبی، قرمز و.. میباشد
جداول پایه طراحی شده:
ورود داده ها:
شیوه ورود دادهها را برای موجودیت کالا بیان میکنیم
ابتدا کالا در جدول موجودیت ثبت میگردد
سپس عنوان ویژگیهای آن مانند رنگ، وزن و... در جدول ویژگیها ثبت میگردد.
مقدار هر ویژگی هم در جدول مقدارها ثبت میشود.
در زیر شیوه ذخیره به صورت شکل مشاهده میکنید.
شیوه خواندن داده ها:
این قسمت هم به راحتی با 2 inner join میتوان به کالا، ویژگیها و مقادیر آن دست پیدا کرد.
نکات:
نکته1: این 3 جدول را باید برای هر موجودیت قابل توسعه ایجاد کرد، مثلا برای کالا، مشتری و...
نکته2: میتوان برای گروه بندی کالاها و همچنین ویژگیها جداول جداگانه ایی تعریف کرد.
نکته3: از مهمترین ویژگیهای این تفکر قابل گسترش بودن سیستم میباشد.
نکته4: میتوان برای آیتم هایی مثل نمایش داده شود یا خیر، چیدمان نمایش و...آیتم هایی به جدول ویژگیها اضافه کرد.
نکته5: این مدل در نرم افزار magento استفاده شده است.
همچنین جهت مطالعه بیشتر ساختار دیتابیس مجنتو در لینک زیر میباشد.
MAGENTO_v1.0.19700---Database-Diagram.zip
منابع: Entity–attribute–value model
تغییرات مهم مقایسهی رشتهها در NET 5.0.
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <EnableNETAnalyzers>true</EnableNETAnalyzers> </PropertyGroup> </Project>
[*.cs] # CA1304: Specify CultureInfo # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1304 dotnet_diagnostic.CA1304.severity = error # CA1305: Specify IFormatProvider # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1305 dotnet_diagnostic.CA1305.severity = error # CA1307: Specify StringComparison for clarity # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1307 dotnet_diagnostic.CA1307.severity = error # CA1308: Normalize strings to uppercase # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1308 dotnet_diagnostic.CA1308.severity = error # CA1309: Use ordinal string comparison # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1309 dotnet_diagnostic.CA1309.severity = error # CA1310: Specify StringComparison for correctness # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1310 dotnet_diagnostic.CA1310.severity = error # CA1311: Specify a culture or use an invariant version # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1311 dotnet_diagnostic.CA1311.severity = error # CA1820: Test for empty strings using string length # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1820 dotnet_diagnostic.CA1820.severity = error # CA1834: Consider using 'StringBuilder.Append(char)' when applicable # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1834 dotnet_diagnostic.CA1834.severity = error # CA1858: Use 'StartsWith' instead of 'IndexOf' # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1858 dotnet_diagnostic.CA1858.severity = error # CA2249: Consider using 'string.Contains' instead of 'string.IndexOf' # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2249 dotnet_diagnostic.CA2249.severity = error # CA2251: Use 'string.Equals' # Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2251 dotnet_diagnostic.CA2251.severity = error
Value Types ارجاعی در C# 7.2
در انتهای نکتهی خروجی ref readonly عنوان شد که «در ابتدا قصد داشتند ref readonly را برای تعریف پارامترهای value type نیز بکار برند، اما این تصمیم با معرفی پارامترهای از نوع in جایگزین شد» اما ... مجددا به C# 12 اضافه شدهاست:
مثال زیر را درنظر بگیرید:
namespace CS8Tests; public class RefReadonlySample { public void Test() { var number = 5; Print(ref number); Console.WriteLine($"After Print -> Your number is {number}"); // Output: // Print -> Your number is 5 // After Print -> Your number is 6 } private void Print(ref int number) { Console.WriteLine($"Print -> Your number is {number}"); number++; } }
اگر بخواهیم از تغییرات پارامتر number در متد Print جلوگیری کنیم، میتوان از واژهی کلیدی in که در C# 7.2 ارائه شد، استفاده کرد:
private void Print(in int number)
error CS8331: Cannot assign to variable 'number' or use it as the right hand side of a ref assignment because it is a readonly variable
اکنون در C# 12 همین عمل را توسط واژههای کلیدی ref readonly نیز میتوان پیاده سازی کرد:
private void Print(ref readonly int number)
سؤال: چرا این تغییر در C# 12 رخ دادهاست، زمانیکه واژهی کلیدی in، دقیقا همین کار را انجام میداد؟
هدف، وضوح بیشتر API تولیدی و تاکید بر readonly بودن ارجاع دریافتی در این حالت و یکدستی قسمتهای مختلف زبان است.
همچنین واقعیت این است که یک چنین قابلیتهایی، استفادهی روزمرهای را در زبان #C ندارند و بیشتر هدف از وجود آنها، استفاده از API کتابخانههای C++/C در زبان #C است. برای مثال بجای اینکه تمام ارجاعات فقط خواندنی آنها را به پارامترهایی از نوع in تبدیل کنند (در کدهای قدیمی) که سبب بروز مشکلات عدم سازگاری میشود، اکنون میتوانند به سادگی refهای قدیمی تعریف شده را ref readonly کنند؛ بدون اینکه استفاده کنندگان با مشکلی مواجه شوند.
- چطور یک اپلیکیشن وب ASP.NET MVC 5 بسازید و آن را روی یک وب سایت Windows Azure منتشر کنید.
- چگونه از OAuth، OpenID و سیستم عضویت ASP.NET برای ایمن سازی اپلیکیشن خود استفاده کنید.
- چگونه از API جدید سیستم عضویت برای مدیریت اعضا و نقشها استفاده کنید.
- چگونه از یک دیتابیس SQL برای ذخیره دادهها در Windows Azure استفاده کنید.
توجه: برای تمام کردن این مقاله به یک حساب کاربری Windows Azure نیاز دارید، که بصورت رایگان میتوانید آن را بسازید. برای اطلاعات بیشتر به Windows Azure Free Trial مراجعه کنید.
در این مقاله:
- برپایی محیط توسعه (development environment)
- برپایی محیط Windows Azure
- ایجاد یک اپلیکیشن ASP.NET MVC 5
- توزیع اپلیکیشن روی Windows Azure
- افزودن یک دیتابیس به اپلیکیشن
- افزودن یک OAuth Provider
- استفاده از Membership API
- توزیع اپلیکیشن روی Windows Azure
- قدمهای بعدی
برپایی محیط توسعه
هنگامی که این مرحله با موفقیت به اتمام رسید، تمام ابزار لازم برای شروع به کار را در اختیار دارید.
برپایی محیط Windows Azure
وب سایت Windows Azure شما در یک محیط اشتراکی (shared) میزبانی میشود، و این بدین معنا است که وب سایتهای شما روی ماشینهای مجازی (virtual machines) اجرا میشوند که با مشتریان دیگر Windows Azure به اشتراک گذاشته شده اند. یک محیط میزبانی اشتراکی گزینه ای کم هزینه برای شروع کار با رایانشهای ابری است. اگر در آینده ترافیک وب سایت شما رشد چشم گیری داشته باشد، میتوانید اپلیکیشن خود را طوری توسعه دهید که به نیازهای جدید پاسخگو باشد و آن را روی یک ماشین مجازی اختصاصی (dedicated VMs) میزبانی کنید. اگر معماری پیچیدهتری نیاز دارید، میتوانید به یک سرویس Windows Azure Cloud مهاجرت کنید. سرویسهای ابری روی ماشینهای مجازی اختصاصی اجرا میشوند که شما میتوانید تنظیمات آنها را بر اساس نیازهای خود پیکربندی کنید.
- در پرتال مدیریتی Windows Azure روی Web Sites در قسمت چپ صفحه کلیک کنید، و گزینه New را برگزینید.
- روی Web Site و سپس Custom Create کلیک کنید.
- در مرحله Create Web Site در قسمت URL یک رشته وارد کنید که آدرسی منحصر بفرد برای اپلیکیشن شما خواهد بود. آدرس کامل وب سایت شما، ترکیبی از مقدار این فیلد و مقدار روبروی آن است.
- در لیست Database گزینه Create a free 20 MB SQL Database را انتخاب کنید.
- در لیست Region همان مقداری را انتخاب کنید که برای وب سایت تان انتخاب کرده اید. تنظیمات این قسمت مشخص میکند که ماشین مجازی (VM) شما در کدام مرکز داده (data center) خواهد بود.
- در قسمت DB Connection String Name مقدار پیش فرض DefaultConnection را بپذیرید.
- دکمه فلش پایین صفحه را کلیک کنید تا به مرحله بعد، یعنی مرحله Specify Database Settings بروید.
- در قسمت Name مقدار ContactDB را وارد کنید (تصویر زیر).
- در قسمت Server گزینه New SQL Database Server را انتخاب کنید. اگر قبلا دیتابیس ساخته اید میتوانید آن را از کنترل dropdown انتخاب کنید.
- مقدار قسمت Region را به همان مقداری که برای ایجاد وب سایت تان تنظیم کرده اید تغییر دهید.
- یک Login Name و Password مدیر (administrator) وارد کنید. اگر گزینه New SQL Database server را انتخاب کرده اید، چنین کاربری وجود ندارد و در واقع اطلاعات یک حساب کاربری جدید را وارد میکنید تا بعدا هنگام دسترسی به دیتابیس از آن استفاده کنید. اگر دیتابیس دیگری را از لیست انتخاب کرده باشید، اطلاعات یک حساب کاربری موجود از شما دریافت خواهد شد. در مثال این مقاله ما گزینه Advanced را رها میکنیم. همچنین در نظر داشته باشید که برای دیتابیسهای رایگان تنها از یک Collation میتوانید استفاده کنید.
دکمه تایید پایین صفحه را کلیک کنید تا مراحل تمام شود.
تصویر زیر استفاده از یک SQL Server و حساب کاربری موجود (existing) را نشان میدهد.
پرتال مدیریتی پس از اتمام مراحل، به صفحه وب سایتها باز میگردد. ستون Status نشان میدهد که سایت شما در حال ساخته شدن است. پس از مدتی (معمولا کمتر از یک دقیقه) این ستون نشان میدهد که سایت شما با موفقیت ایجاد شده. در منوی پیمایش سمت چپ، تعداد سایت هایی که در اکانت خود دارید در کنار آیکون Web Sites نمایش داده شده است، تعداد دیتابیسها نیز در کنار آیکون SQL Databases نمایش داده میشود.
یک اپلیکیشن ASP.NET MVC 5 بسازید
نوع پروژه را ASP.NET Web Application انتخاب کنید.
نکته: در تصویر بالا نام پروژه "MyExample" است اما حتما نام پروژه خود را به "ContactManager" تغییر دهید. قطعه کدهایی که در ادامه مقاله خواهید دید نام پروژه را ContactManager فرض میکنند.
در دیالوگ جدید ASP.NET نوع اپلیکیشن را MVC انتخاب کنید و دکمه Change Authentication را کلیک کنید.
گزینه پیش فرض Individual User Accounts را بپذیرید. برای اطلاعات بیشتر درباره متدهای دیگر احراز هویت به این لینک مراجعه کنید. دکمههای OK را کلیک کنید تا تمام مراحل تمام شوند.
تنظیم تیتر و پاورقی سایت
- فایل Layout.cshtml_ را باز کنید. دو نمونه از متن "My ASP.NET MVC Application" را با عبارت "Contact Manager" جایگزین کنید.
- عبارت "Application name" را هم با "CM Demo" جایگزین کنید.
اپلیکیشن را بصورت محلی اجرا کنید
اپلیکیشن شما فعلا آماده است و میتوانید آن را روی Windows Azure توزیع کنید. بعدا دیتابیس و دسترسی داده نیز اضافه خواهد شد.
اپلیکیشن را روی Windows Azure منتشر کنید
حال دیالوگ Import Publish Profile نمایش داده میشود.
یکی از متدهای زیر را استفاده کنید تا ویژوال استودیو بتواند به اکانت Windows Azure شما متصل شود.
- روی Sign In کلیک کنید تا با وارد کردن اطلاعات حساب کاربری وارد Windows Azure شوید.
- روی Manage subscriptions کلیک کنید تا یک management certificate نصب کنید، که دسترسی به حساب کاربری شما را ممکن میسازد.
در دیالوگ باکس Publish Web روی Publish کلیک کنید.
اپلیکیشن شما حالا در فضای ابری اجرا میشود. دفعه بعد که اپلیکیشن را منتشر کنید تنها فایلهای تغییر کرده (یا جدید) آپلود خواهند شد.
یک دیتابیس به اپلیکیشن اضافه کنید
کلاسهای مدل Contacts را اضافه کنید
نام کلاس را به Contact.cs تغییر دهید و دکمه Add را کلیک کنید.
کد فایل Contact.cs را با قطعه کد زیر مطابقت دهید.
using System.ComponentModel.DataAnnotations; using System.Globalization; namespace ContactManager.Models { public class Contact { public int ContactId { get; set; } public string Name { get; set; } public string Address { get; set; } public string City { get; set; } public string State { get; set; } public string Zip { get; set; } [DataType(DataType.EmailAddress)] public string Email { get; set; } } }
این کلاس موجودیت Contact را در دیتابیس معرفی میکند. داده هایی که میخواهیم برای هر رکورد ذخیره کنیم تعریف شده اند، بعلاوه یک فیلد Primary Key که دیتابیس به آن نیاز دارد.
یک کنترلر و نما برای دادهها اضافه کنید
در دیالوگ باکس Add Scaffold گزینه MVC 5 Controller with views, using EF را انتخاب کنید.
در دیالوگ Add Controller نام "CmController" را برای کنترلر وارد کنید. (تصویر زیر.)
در لیست Model گزینه (Contact (ContactManager.Models را انتخاب کنید.
در قسمت Data context class گزینه (ApplicationDbContext (ContactManager.Models را انتخاب کنید. این ApplicationDbContext هم برای اطلاعات سیستم عضویت و هم برای دادههای Contacts استفاده خواهد شد.
روی Add کلیک کنید. ویژوال استودیو بصورت خودکار با استفاده از Scaffolding متدها و Viewهای لازم برای عملیات CRUD را فراهم میکند، که همگی از مدل Contact استفاده میکنند.
فعالسازی مهاجرت ها، ایجاد دیتابیس، افزودن داده نمونه و یک راه انداز
در پنجره باز شده فرمان زیر را وارد کنید.
enable-migrations
فرمان enable-migrations یک پوشه با نام Migrations می سازد و فایلی با نام Configuration.cs را به آن اضافه میکند. با استفاده از این کلاس میتوانید دادههای اولیه دیتابیس را وارد کنید و مهاجرتها را نیز پیکربندی کنید.
در پنجره Package Manager Console فرمان زیر را وارد کنید.
add-migration Initial
فرمان add-migration initial فایلی با نام data_stamp> initial> ساخته و آن را در پوشه Migrations ذخیره میکند. در این مرحله دیتابیس شما ایجاد میشود. در این فرمان، مقدار initial اختیاری است و صرفا برای نامگذاری فایل مهاجرت استفاده شده. فایلهای جدید را میتوانید در Solution Explorer مشاهده کنید.
در کلاس Initial متد Up جدول Contacts را میسازد. و متد Down (هنگامی که میخواهید به وضعیت قبلی بازگردید) آن را drop میکند.
حال فایل Migrations/Configuration.cs را باز کنید. فضای نام زیر را اضافه کنید.
using ContactManager.Models;
حال متد Seed را با قطعه کد زیر جایگزین کنید.
protected override void Seed(ContactManager.Models.ApplicationDbContext context) { context.Contacts.AddOrUpdate(p => p.Name, new Contact { Name = "Debra Garcia", Address = "1234 Main St", City = "Redmond", State = "WA", Zip = "10999", Email = "debra@example.com", }, new Contact { Name = "Thorsten Weinrich", Address = "5678 1st Ave W", City = "Redmond", State = "WA", Zip = "10999", Email = "thorsten@example.com", }, new Contact { Name = "Yuhong Li", Address = "9012 State st", City = "Redmond", State = "WA", Zip = "10999", Email = "yuhong@example.com", }, new Contact { Name = "Jon Orton", Address = "3456 Maple St", City = "Redmond", State = "WA", Zip = "10999", Email = "jon@example.com", }, new Contact { Name = "Diliana Alexieva-Bosseva", Address = "7890 2nd Ave E", City = "Redmond", State = "WA", Zip = "10999", Email = "diliana@example.com", } ); }
این متد دیتابیس را Seed میکند، یعنی دادههای پیش فرض و اولیه دیتابیس را تعریف میکند. برای اطلاعات بیشتر به Seeding and Debugging Entity Framework (EF) DBs مراجعه کنید.
در پنجره Package Manager Console فرمان زیر را وارد کنید.
update-database
فرمان update-database مهاجرت نخست را اجرا میکند، که دیتابیس را میسازد. بصورت پیش فرض این یک دیتابیس SQL Server Express LocalDB است.
حال پروژه را با CTRL + F5 اجرا کنید.
همانطور که مشاهده میکنید، اپلیکیشن دادههای اولیه (Seed) را نمایش میدهد، و لینک هایی هم برای ویرایش، حذف و مشاهده جزئیات رکوردها فراهم میکند. میتوانید دادهها را مشاهده کنید، رکورد جدید ثبت کنید و یا دادههای قبلی را ویرایش و حذف کنید.
یک تامین کننده OAuth2 و OpenID اضافه کنید
استفاده از Membership API
using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.EntityFramework;
bool AddUserAndRole(ContactManager.Models.ApplicationDbContext context) { IdentityResult ir; var rm = new RoleManager<IdentityRole> (new RoleStore<IdentityRole>(context)); ir = rm.Create(new IdentityRole("canEdit")); var um = new UserManager<ApplicationUser>( new UserStore<ApplicationUser>(context)); var user = new ApplicationUser() { UserName = "user1", }; ir = um.Create(user, "Passw0rd1"); if (ir.Succeeded == false) return ir.Succeeded; ir = um.AddToRole(user.Id, "canEdit"); return ir.Succeeded; }
protected override void Seed(ContactManager.Models.ApplicationDbContext context) { AddUserAndRole(context); context.Contacts.AddOrUpdate(p => p.Name, // Code removed for brevity }
کدی موقتی برای تخصیص نقش canEdit به کاربران جدید Social Provider ها
await UserManager.AddToRoleAsync(user.Id, "CanEdit");
در ادامه مقاله اپلیکیشن خود را روی Windows Azure منتشر خواهید کرد و با استفاده از Google و تامین کنندگان دیگر وارد سایت میشوید. هر فردی که به آدرس سایت شما دسترسی داشته باشد، و یک حساب کاربری Google هم در اختیار داشته باشد میتواند در سایت شما ثبت نام کند و سپس دیتابیس را ویرایش کند. برای جلوگیری از دسترسی دیگران، میتوانید وب سایت خود را متوقف (stop) کنید.
در پنجره Package Manager Console فرمان زیر را وارد کنید.
Update-Database
فرمان را اجرا کنید تا متد Seed را فراخوانی کند. حال AddUserAndRole شما نیز اجرا میشود. تا این مرحله نقش canEdit ساخته شده و کاربر جدیدی با نام user1 ایجاد و به آن افزوده شده است.
محافظت از اپلیکیشن توسط SSL و خاصیت Authorize
در این قسمت شما با استفاده از خاصیت Authorize دسترسی به اکشن متدها را محدود میکنید. کاربران ناشناس (Anonymous) تنها قادر به مشاهده متد Index در کنترلر home خواهند بود. کاربرانی که ثبت نام کرده اند به متدهای Index و Details در کنترلر Cm و صفحات About و Contact نیز دسترسی خواهند داشت. همچنین دسترسی به متدهایی که دادهها را تغییر میدهند تنها برای کاربرانی وجود دارد که در نقش canEdit هستند.
خاصیت Authorize و RequireHttps را به اپلیکیشن اضافه کنید. یک راه دیگر افزودن این خاصیتها به تمام کنترلرها است، اما تجارب امنیتی توصیه میکند که این خاصیتها روی کل اپلیکیشن اعمال شوند. با افزودن این خاصیتها بصورت global تمام کنترلرها و اکشن متدهایی که میسازید بصورت خودکار محافظت خواهند شد، و دیگر لازم نیست بیاد داشته باشید کدام کنترلرها و متدها را باید ایمن کنید.
برای اطلاعات بیشتر به Securing your ASP.NET MVC App and the new AllowAnonymous Attribute مراجعه کنید.
فایل App_Start/FilterConfig.cs را باز کنید و متد RegisterGlobalFilters را با کد زیر مطابقت دهید.
public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); filters.Add(new System.Web.Mvc.AuthorizeAttribute()); filters.Add(new RequireHttpsAttribute()); }
خاصیت Authorize در کد بالا از دسترسی کاربران ناشناس به تمام متدهای اپلیکیشن جلوگیری میکند. شما برای اعطای دسترسی به متدهایی خاص از خاصیت AllowAnonymous استفاده خواهید کرد. در آخر خاصیت RequireHTTPS باعث میشود تا تمام دسترسیها به اپلیکیشن وب شما از طریق HTTPS صورت گیرد.
حالا خاصیت AllowAnonymous را به متد Index در کنترلر Home اضافه کنید. از این خاصیت برای اعطای دسترسی به تمامی کاربران سایت استفاده کنید. قسمتی از کد کنترلر Home را در زیر میبینید.
namespace ContactManager.Controllers { public class HomeController : Controller { [AllowAnonymous] public ActionResult Index() { return View(); }
یک جستجوی عمومی برای عبارت AllowAnonymous انجام دهید. همانطور که مشاهده میکنید این خاصیت توسط متدهای ورود و ثبت نام در کنترلر Account نیز استفاده شده است.
در کنترلر CmController خاصیت [("Authorize(Roles="canEdit] را به تمام متدهایی که با داده سر و کار دارند اضافه کنید، به غیر از متدهای Index و Details. قسمتی از کد کامل شده در زیر آمده است.
فعال سازی SSL برای پروژه
روی نام پروژه کلیک راست کنید و Properties را انتخاب کنید. در قسمت چپ گزینه Web را انتخاب کنید. حالا مقدار Project Url را به آدرسی که کپی کرده اید تغییر دهید. نهایتا تغییرات را ذخیره کنید و پنجره را ببندید.
حال پروژه را اجرا کنید. مرورگر شما باید یک پیام خطای اعتبارسنجی به شما بدهد. دلیلش این است که اپلیکیشن شما از یک Valid Certificate استفاده نمیکند. هنگامی که پروژه را روی Windows Azure منتشر کنید دیگر این پیغام را نخواهید دید. چرا که سرورهای مایکروسافت همگی لایسنسهای معتبری دارند. برای اپلیکیشن ما میتوانید روی Continue to this website را انتخاب کنید.
حال مرورگر پیش فرض شما باید صفحه Index از کنترلر home را به شما نمایش دهد.
اگر از یک نشست قبلی هنوز در سایت هستید (logged-in) روی لینک Log out کلیک کنید و از سایت خارج شوید.
روی لینکهای About و Contact کلیک کنید. باید به صفحه ورود به سایت هدایت شوید چرا که کاربران ناشناس اجازه دسترسی به این صفحات را ندارند.
روی لینک Register کلیک کنید و یک کاربر محلی با نام Joe بسازید. حال مطمئن شوید که این کاربر به صفحات Home, About و Contact دسترسی دارد.
روی لینک CM Demo کلیک کنید و مطمئن شوید که دادهها را مشاهده میکنید.
حال روی یکی از لینکهای ویرایش (Edit) کلیک کنید. این درخواست باید شما را به صفحه ورود به سایت هدایت کند، چرا که کاربران محلی جدید به نقش canEdit تعلق ندارند.
با کاربر user1 که قبلا ساختید وارد سایت شوید. حال به صفحه ویرایشی که قبلا درخواست کرده بودید هدایت میشوید.
اگر نتوانستید با این کاربر به سایت وارد شوید، کلمه عبور را از سورس کد کپی کنید و مجددا امتحان کنید. اگر همچنان نتوانستید به سایت وارد شوید، جدول AspNetUsers را بررسی کنید تا مطمئن شوید کاربر user1 ساخته شده است. این مراحل را در ادامه مقاله خواهید دید.
در آخر اطمینان حاصل کنید که میتوانید دادهها را تغییر دهید.
اپلیکیشن را روی Windows Azure منتشر کنید
در دیالوگ باز شده روی قسمت Settings کلیک کنید. روی File Publish Options کلیک کنید تا بتوانید Remote connection string را برای ApplicationDbContext و دیتابیس ContactDB انتخاب کنید.
اگر ویژوال استودیو را پس از ساخت Publish profile بسته و دوباره باز کرده اید، ممکن است رشته اتصال را در لیست موجود نبینید. در چنین صورتی، بجای ویرایش پروفایل انتشار، یک پروفایل جدید بسازید. درست مانند مراحلی که پیشتر دنبال کردید.
زیر قسمت ContactManagerContext گزینه Execute Code First Migrations را انتخاب کنید.
حال Publish را کلیک کنید تا اپلیکیشن شما منتشر شود. با کاربر user1 وارد سایت شوید و بررسی کنید که میتوانید دادهها را ویرایش کنید یا خیر.
حال از سایت خارج شوید و توسط یک اکانت Google یا Facebook وارد سایت شوید، که در این صورت نقش canEdit نیز به شما تعلق میگیرد.
برای جلوگیری از دسترسی دیگران، وب سایت را متوقف کنید
یک راه دیگر متوقف کردن وب سایت از طریق پرتال مدیریت Windows Azure است.
فراخوانی AddToRoleAsync را حذف و اپلیکیشن را منتشر و تست کنید
await UserManager.AddToRoleAsync(user.Id, "CanEdit");
دکمه Start Preview را فشار دهید. در این مرحله تنها فایل هایی که نیاز به بروز رسانی دارند آپلود خواهند شد.
وب سایت را راه اندازی کنید. سادهترین راه از طریق پرتال مدیریت Windows Azure است. توجه داشته باشید که تا هنگامی که وب سایت شما متوقف شده، نمیتوانید اپلیکیشن خود را منتشر کنید.
حال به ویژوال استودیو بازگردید و اپلیکیشن را منتشر کنید. اپلیکیشن Windows Azure شما باید در مرورگر پیش فرض تان باز شود. حال شما در حال مشاهده صفحه اصلی سایت بعنوان یک کاربر ناشناس هستید.
روی لینک About کلیک کنید، که شما را به صفحه ورود هدایت میکند.
روی لینک Register در صفحه ورود کلیک کنید و یک حساب کاربری محلی بسازید. از این حساب کاربری برای این استفاده میکنیم که ببینیم شما به صفحات فقط خواندنی (read-only) و نه صفحاتی که دادهها را تغییر میدهند دسترسی دارید یا خیر. بعدا در ادامه مقاله، دسترسی حسابهای کاربری محلی (local) را حذف میکنیم.
مطمئن شوید که به صفحات About و Contact دسترسی دارید.
لینک CM Demo را کلیک کنید تا به کنترلر CmController هدایت شوید.
روی یکی از لینکهای Edit کلیک کنید. این کار شما را به صفحه ورود به سایت هدایت میکند. در زیر قسمت User another service to log in یکی از گزینههای Google یا Facebook را انتخاب کنید و توسط حساب کاربری ای که قبلا ساختید وارد شوید.
حال بررسی کنید که امکان ویرایش اطلاعات را دارید یا خیر.
نکته: شما نمیتوانید در این اپلیکیشن از اکانت گوگل خود خارج شده، و با همان مرورگر با اکانت گوگل دیگری وارد اپلیکیشن شوید. اگر دارید از یک مرورگر استفاده میکنید، باید به سایت گوگل رفته و از آنجا خارج شوید. برای وارد شدن به اپلیکیشن توسط یک اکانت دیگر میتوانید از یک مرورگر دیگر استفاده کنید.
دیتابیس SQL Azure را بررسی کنید
توجه: اگر نمیتوانید گره SQL Databases را باز کنید و یا ContactDB را در ویژوال استودیو نمیبینید، باید مراحلی را طی کنید تا یک پورت یا یکسری پورت را به فایروال خود اضافه کنید. دقت داشته باشید که در صورت اضافه کردن Port Rangeها ممکن است چند دقیقه زمان نیاز باشد تا بتوانید به دیتابیس دسترسی پیدا کنید.
روی جدول AspNetUsers کلیک راست کرده و View Data را انتخاب کنید.
حالا روی AspNetUserRoles کلیک راست کنید و View Data را انتخاب کنید.
اگر شناسه کاربران (User ID) را بررسی کنید، مشاهده میکنید که تنها دو کاربر user1 و اکانت گوگل شما به نقش canEdit تعلق دارند.
Cannot open server login error
شما باید آدرس IP خود را به لیست آدرسهای مجاز (Allowed IPs) اضافه کنید. در پرتال مدیریتی Windows Azure در قسمت چپ صفحه، گزینه SQL Databases را انتخاب کنید.
دیتابیس مورد نظر را انتخاب کنید. حالا روی لینک Set up Windows Azure firewall rules for this IP address کلیک کنید.
هنگامی که با پیغام "?The current IP address xxx.xxx.xxx.xxx is not included in existing firewall rules. Do you want to update the firewall rules" مواجه شدید Yes را کلیک کنید. افزودن یک آدرس IP بدین روش معمولا کافی نیست و در فایروالهای سازمانی و بزرگ باید Range بیشتری را تعریف کنید.
مرحله بعد اضافه کردن محدوده آدرسهای مجاز است.
مجددا در پرتال مدیریتی Windows Azure روی SQL Databases کلیک کنید. سروری که دیتابیس شما را میزبانی میکند انتخاب کنید.
در بالای صفحه لینک Configure را کلیک کنید. حالا نام rule جدید، آدرس شروع و پایان را وارد کنید.
در پایین صفحه Save را کلیک کنید.
در آخر میتوانید توسط SSOX به دیتابیس خود متصل شوید. از منوی View گزینه SQL Server Object Explorer را انتخاب کنید. روی SQL Server کلیک راست کرده و Add SQL Server را انتخاب کنید.
در دیالوگ Connect to Server متد احراز هویت را به SQL Server Authentication تغییر دهید. این کار نام سرور و اطلاعات ورود پرتال Windows Azure را به شما میدهد.
در مرورگر خود به پرتال مدیریتی بروید و SQL Databases را انتخاب کنید. دیتابیس ContactDB را انتخاب کرده و روی View SQL Database connection strings کلیک کنید. در صفحه Connection Strings مقادیر Server و User ID را کپی کنید. حالا مقادیر را در دیالوگ مذکور در ویژوال استودیو بچسبانید. مقدار فیلد User ID در قسمت Login وارد میشود. در آخر هم کلمه عبوری که هنگام ساختن دیتابیس تنظیم کردید را وارد کنید.
حالا میتوانید با مراحلی که پیشتر توضیح داده شد به دیتابیس Contact DB مراجعه کنید.
افزودن کاربران به نقش canEdit با ویرایش جداول دیتابیس
حالا RoleId را کپی کنید و در ردیف جدید بچسبانید.
شناسه کاربر مورد نظر را از جدول AspNetUsers پیدا کنید و مقدار آن را در ردیف جدید کپی کنید. همین! کاربر جدید شما به نقش canEdit اضافه شد.
نکاتی درباره ثبت نام محلی (Local Registration)
- در کنترلر Account متدهای Register را ویرایش کنید و خاصیت AllowAnonymous را از آنها حذف کنید (هر دو متد GET و POST). این کار ثبت نام کاربران ناشناس و بدافزارها (bots) را غیر ممکن میکند.
- در پوشه Views/Shared فایل LoginPartial.cshtml_ را باز کنید و لینک Register را از آن حذف کنید.
- در فایل Views/Account/Login.cshtml نیز لینک Register را حذف کنید.
- اپلیکیشن را دوباره منتشر کنید.
قدمهای بعدی
<style> div,.content,table.main { color: red; } </style> <div>Text 1</div> <p>Text 2</p> <table class="main" border="1"> <tr> <td>Cell 1</td> <td>Cell 2</td> <td>Cell 3</td> </tr> <tr> <td>Cell 4</td> <td>Cell 5</td> <td>Cell 6</td> </tr> </table> <span class="content">Text 3</span> <h1>Text 4</h1>
|
|
|
|
| Selector | نسخه CSS |
Yes | Yes | Yes | Yes | Yes | S1,S2 | 1 |
<style> .content .tag { color: red; } h1#index { color: blue; } ul.list li.even { color: green; } </style> <h1 id="index">Index</h1> <h1>Header 1</h1> <div class="content"> Lorem ipsum dolor sit amet, <span class="tag">consectetuer</span> adipiscing elit. Maecenas porttitor congue massa. Fusce posuere, magna sed pulvinar ultricies, purus lectus malesuada libero, <span class="tag">sit</span> amet commodo magna eros quis urna. Nunc viverra <span class="tag">imperdiet</span> enim. Fusce est. </div> <h1>Header 2</h1> <div class="content"> <ul class="list"> <li>Item 1</li> <li class="even">Item 2</li> <li>Item 3</li> <li class="even">Item 4</li> <li>Item 5</li> <li class="even">Item 6</li> </ul> </div>
12- [attribute]
<style> [readonly] { background: green; } </style> <input type="text" value="Value 1" readonly="readonly"/> <input type="text"/>
|
|
|
|
| Selector | نسخه CSS |
3.1 | 9.6 | 7.0 | 2.0 | 4.0 | [attribute] | 2 |
13- [attribute=value]
<style> [lang=fa] { direction:rtl; } </style> <div lang="fa">متن 1</div>
|
|
|
|
| Selector | نسخه CSS |
3.1 | 9.6 | 7.0 | 2.0 | 4.0 | [attribute=value] | 2 |
14- [attribute=value i]
<style> [lang=fa] { direction:rtl; } </style> <div lang="FA">متن 1</div>
|
|
|
|
| Selector | نسخه CSS |
No | No | No | No | No | [attribute=value i] | 4 |
15- [attribute|=value]
<style> [class|=info] { color:red } </style> <div class="info">Text 1</div> <div class="infobar">Text 2</div> <div class="info bar">Text 3</div> <div class="info-bar">Text 4</div> <div class="btninfo">Text 5</div> <div class="btn info">Text 6</div> <div class="btn-info">Text 7</div> <div class="toolinfoicon">Text 8</div> <div class="tool info icon">Text 9</div> <div class="tool-info-icon">Text 10</div>
|
|
|
|
| Selector | نسخه CSS |
3.1 | 9.6 | 7.0 | 2.0 | 4.0 | [attribute|=value] | 2 |
16- [attribute^=value]
<style> [class^=info] { color: red; } </style> <div class="info">Text 1</div> <div class="infobar">Text 2</div> <div class="info bar">Text 3</div> <div class="info-bar">Text 4</div> <div class="btninfo">Text 5</div> <div class="btn info">Text 6</div> <div class="btn-info">Text 7</div> <div class="toolinfoicon">Text 8</div> <div class="tool info icon">Text 9</div> <div class="tool-info-icon">Text 10</div>
|
|
|
|
| Selector | نسخه CSS |
3.2 | 9.6 | 7.0 | 3.5 | 4.0 | [attribute^=value] | 3 |
17- [attribute~=value]
<style> [class~=info] { color: red; } </style> <div class="info">Text 1</div> <div class="infobar">Text 2</div> <div class="info bar">Text 3</div> <div class="info-bar">Text 4</div> <div class="btninfo">Text 5</div> <div class="btn info">Text 6</div> <div class="btn-info">Text 7</div> <div class="toolinfoicon">Text 8</div> <div class="tool info icon">Text 9</div> <div class="tool-info-icon">Text 10</div>
|
|
|
|
| Selector | نسخه CSS |
3.1 | 9.6 | 7.0 | 2.0 | 4.0 | [attribute~=value] | 2 |
18- [attribute*=value]
<style> [class*=info] { color: red; } </style> <div class="info">Text 1</div> <div class="infobar">Text 2</div> <div class="info bar">Text 3</div> <div class="info-bar">Text 4</div> <div class="btninfo">Text 5</div> <div class="btn info">Text 6</div> <div class="btn-info">Text 7</div> <div class="toolinfoicon">Text 8</div> <div class="tool info icon">Text 9</div> <div class="tool-info-icon">Text 10</div>
|
|
|
|
| Selector | نسخه CSS |
3.2 | 9.6 | 7.0 | 3.5 | 4.0 | [attribute*=value] | 3 |
19- [attribute$=value]
<style> [class$=info] { color: red; } </style> <div class="info">Text 1</div> <div class="infobar">Text 2</div> <div class="info bar">Text 3</div> <div class="info-bar">Text 4</div> <div class="btninfo">Text 5</div> <div class="btn info">Text 6</div> <div class="btn-info">Text 7</div> <div class="toolinfoicon">Text 8</div> <div class="tool info icon">Text 9</div> <div class="tool-info-icon">Text 10</div>
|
|
|
|
| Selector | نسخه CSS |
3.2 | 9.6 | 7.0 | 3.5 | 4.0 | [attribute$=value] | 3 |
در تهیه مثال Auto Mapping به کمک امکانات توکار NH 3.2 به این مورد نیاز پیدا کردم:
بتوان نوع متد جنریک را به صورت متغیر تعریف کرد و این نوع در زمان کامپایل برنامه مشخص نباشد. مثلا چیزی شبیه به این مثال:
using System;
namespace GenericsSample
{
class TestGenerics
{
public static void Print<T>(T data)
{
Console.WriteLine("Print<T>");
}
}
class Program
{
static void Main(string[] args)
{
var type = typeof(Nullable<int>);
TestGenerics.Print<type>(1);
}
}
}
این نوع فراخوانی متد Print در دات نت به صورت پیش فرض غیرمجاز است و نوع جنریک را نمیتوان به صورت متغیر معرفی کرد.
که البته این هم راه حل دارد و به کمک Reflection قابل حل است:
using System;
namespace GenericsSample
{
class TestGenerics
{
public static void Print<T>(T data)
{
Console.WriteLine("Print<T>");
}
}
class Program
{
static void Main(string[] args)
{
var nullableIntType = typeof(Nullable<>).MakeGenericType(typeof(int));
var method = typeof(TestGenerics).GetMethod("Print");
var genericMethod = method.MakeGenericMethod(new[] { nullableIntType });
genericMethod.Invoke(null, new object[] { 1 });
}
}
}
دو متد MakeGenericType و MakeGenericMethod برای ساخت پویای نوعهای جنریک و همچنین ارسال آنها به متدهای جنریک در دات نت وجود دارند که مثالی از نحوه استفاده از آنها را در بالا ملاحظه میکنید.
مثال دوم:
اگر کلاس TestGenerics نسخه غیرجنریک متد Print را هم داشت، چطور؟ مثلا:
class TestGenerics
{
public static void Print<T>(T data)
{
Console.WriteLine("Print<T>");
}
public static void Print(object data)
{
Console.WriteLine("Print");
}
}
اینبار اگر برنامه فوق را اجرا کنیم، پیغام Ambiguous match found را حین فراخوانی GetMoethod دریافت خواهیم کرد؛ چون دو متد با یک نام در کلاس یاد شده وجود دارند. برای حل این مشکل باید به نحو زیر عمل کرد:
using System;
using System.Linq;
namespace GenericsSample
{
class TestGenerics
{
public static void Print<T>(T data)
{
Console.WriteLine("Print<T>");
}
public static void Print(object data)
{
Console.WriteLine("Print");
}
}
class Program
{
static void Main(string[] args)
{
var nullableIntType = typeof(Nullable<>).MakeGenericType(typeof(int));
var method = typeof(TestGenerics).GetMethods()
.First(x => x.Name == "Print" && (x.GetParameters()[0]).ParameterType.IsGenericParameter);
var genericMethod = method.MakeGenericMethod(new[] { nullableIntType });
genericMethod.Invoke(null, new object[] { 1 });
}
}
}
GetMethods تمام متدها را بازگشت داده و سپس بر اساس متادیتای متدها، میتوان تشخیص داد که کدام یک جنریک است.
در این قسمت با تب Console آشنا خواهیم شد .
در قسمت قبل در مورد این تب گفتیم :
در این تب دو بخش وجود دارد :
در بخش Log هشدارها ، پیغامها ، درخواستهای XHR و ... نمایش داده میشوند .
بخش دیگر هم که در سمت راست قرار دارد ، مخصوص اجرای کدهای جاوا اسکریپت میباشد .
پس یک قسمت داریم برای نوشتن کدهای جاوا اسکریپت و یک قسمت هم برای مشاهدهی رویدادها .
اکنون 2 سوال مطرح میشود :
- برای اجرای یک کد در حالت معمول چگونه عمل میکنیم ؟
پاسخ : کدهای مورد نظر را بین تگ باز و بستهی script قرار میدهیم و صفحه مورد نظر را در مرورگر باز میکنیم و مرورگر کد را اجرا میکند . - در صورتی که کدهای ما خطا داشته باشند ، چگونه خطایابی میکنیم ؟
پاسخ : در بین کدهای نوشته شده چند alert قرار میدهیم و سعی میکنیم مشکل را پیدا کنیم .
همین 2 سوال اهمیت و قدرت فایرباگ و قسمت Console آن را برای ما آشکار میکند ، زیرا ما میتوانیم بدون Reload کردن صفحه ، کدهایمان را اجرا و نتیجه را مشاهده کنیم یا بوسیله توابع موجود خیلی ساده کدهایمان را خطایابی کنیم .
چگونه کدهای نوشته شده را سریع اجرا کنم ؟ کلید میانبر ( HotKey ) اجرای کدها چیست ؟
پاسخ : فشردن کلید CTRL + Enter
امتحان کنید :
کد زیر را در بخش کدنویسی تایپ کنید و بوسیله کلید میانبر گفته شده ، آن را اجرا کنید .
document.getElementsByTagName("div");
تصویر ذیل نتیجه اجرای کدی هست که اجرا کردیم .
چند نکته :
- قسمت هایی که با رنگ قرمز و یک دات ( . ) بعد از نام تگ قرار گرفته اند ، کلاسهای CSS ای هستند که المنت دارد .
- قسمت هایی که با رنگ آبی تیره و یک شارپ ( # ) بعد از نام تگ قرار گرفته اند ، ID تگها هستند .
- قسمت هایی که کمرنگ هستند ، المنت هایی هستند که در صفحه قابل نمایش نیستند .
- اگر یک تگ چند کلاس داشته باشد ، فقط اولین کلاس نمایش داده میشود .
دکمهها و حالتهای نمایش بخش کد نویسی
4 دکمه در قسمت کدنویسی وجود دارد :
- Run : اجرای کد
- Clear : خالی کردن بخش کد نویسی
- Copy : کپی کردن کد موجود در بخش کد نویسی در حافظه
- History : کدهای نوشته شده در نشست ( Session ) فعلی مرورگر
بخش کد نویسی میتواند به 2 شکل نمایش داده شود :
- بصورت جعبه چند خطی ( Command Editor )
- بصورت تک خطی ( Command Line )
9 دکمه هم در بالای بخش log وجود دارد ( به ترتیب از چپ به راست ) :
- دکمه ای با عنوان “Break On All Errors” . زمانی فعال شود ، در اولین اجرای یک کد از داخل صفحه ، به تب Script منتقل میشود و در خطی که کد در حال اجرا است توقف میکند .
- Clear : بخش log را خالی میکند .
- Persist : فعال بودن این دکمه باعث میشود که محتویات بخش Console در بارگزاری مجدد صفحه حفظ شود .
- Profile : بوسیله این گزینه میتوانید کدهای اجرایی خود در مدت زمان فعال بودن این دکمه ، تحت نظر بگیرید .
به این صورت که پس از غیر فعال کردن این دکمه ( کلیک مجدد بروی آن ) میتوانید تابعهای اجرا شده ، تعداد فراخوانی آنها ، مدت زمان اجرای هر یک ، میانگین زمان اجرای هر بار یک تابع و ... را مشاهده کنید . - 5 دکمهی بعدی هم برای فیلتر کردن Log هستند .
نمایش تعداد خطاهای اتفاق افتاده ، در نوار وضعیت ( Status Bar ) :
اگر در زمان فعال بودن فایرباگ ، در صفحه خطایی رخ دهد ، در نوار وضعیت عدد 1 را نمایش میدهد و به ازای هر خطای جدید ، یکی به تعداد خطاها اضافه میکند .
البته اگر از ورژنهای جدید فایرفاکس استفاده میکنید ، نوار وضعیت را نخواهید داشت و تعداد خطاها را در کنار آیکون فایرباگ خواهید داشت .
در کنار همه این امکانات ، فایرباگ یک مجموعه کامل از توابع کاربردی برای توسعه جاوا اسکریپت و خطایابی جاوا اسکریپت در اختیار ما میگذارد .
چند متد کمکی برای نوشتن Logهای مختلف در Console :
console.debug('This is a Debug message'); console.info('This is an Information'); console.warn('This is a Warning message'); console.error('This is an Error message');
در قسمت بعدی توابع مربوط به توسعه جاوا اسکریپت ( Command Line API & Console API ) در فایرباگ را بررسی خواهیم کرد .
Here’s a summary of what’s new in this preview release:
- Improved ASP.NET Core debugging experience
- Servers & middleware
-
IHttpSysRequestTimingFeature
- SNI hostname in
ITlsHandshakeFeature
-
IExceptionHandler
-
- Blazor
- New Blazor Web App project template
- Blazor router integration with endpoint routing
- Enable interactivity for individual components with Blazor Server
- Improved packaging of Webcil files
- Blazor Content Security Policy (CSP) compatibility
- API authoring
- Support for generic attributes
- SignalR
- SignalR seamless reconnect
- Native AOT
- Support for
AsParameters
and automatic metadata generation in compile-timed generated minimal APIs
- Support for
- Authentication and authorization
- Authentication updates in ASP.NET Core SPA templates
- New analyzer for recommended
AuthorizationBuilder
usage