ublic class AppIdentityDbContext : IdentityDbContext<AppUser> { public AppIdentityDbContext() : base("IdentityDb") { } // DbSet Definition public DbSet<Product> Products { get; set; } static AppIdentityDbContext() { Database.SetInitializer<AppIdentityDbContext>(new IdentityDbInit()); } public static AppIdentityDbContext Create() { return new AppIdentityDbContext(); } }
مروری بر قابلیت جدید ASP.NET FriendlyUrls
معرفی ASP.NET Identity
[Authorize] public controller account { public ActionResult Index() { } public ActionResult Manage() { } [AllowAnonymous] public ActionResult Info() { } } [Authorize(Roles="Admin")] public controller admin { public ActionResult Index() { } }
مشکل در هدایت کاربر به صفحه لاگین
if (validate) { var manager = context.OwinContext.GetUserManager<TManager>(); var userId = getUserIdCallback(context.Identity); if (manager != null && userId != null) {
appBuilder.CreatePerOwinContext(() => ProjectObjectFactory.Container.GetInstance<IApplicationUserManager>());
appBuilder.CreatePerOwinContext( () =>ProjectObjectFactory.Container.GetInstance<ApplicationUserManager>());
In this webinar, we will show the benefits of using DevExpress Object-Relational Mapping Library - the eXpress Persistent Objects - with .NET Core 2. The presentation will quickly cover the basics for those new to DevExpress products, and will show how you can use our ORM to manage data in ASP.NET Core or Xamarin apps.
سری آموزشی مقدماتی Web API
Our beginner's guide to building Web APIs with ASP.NET Core is designed to provide you with the foundation you need to start building Web APIs with .NET in a collection of short, pragmatic collection of videos. Web APIs have become a critical component in almost every type of software we use today. In this introductory video series, we will walk you through the fundamental concepts you need to know to get started with building Web APIs using ASP.NET Core. We will cover topics such as routing, validation, working with data, and much more.
This post shows how to import and export .xls or .xlsx (Excel files) in ASP.NET Core. And when thinking about dealing with excel with .NET, we always look for third-party libraries or component. And one of the most popular .net library that reads and writes Excel 2007/2010 files using the Open Office Xml format (xlsx) is EPPlus. However, at the time of writing this post, this library is not updated to support .NET Core. But there exists an unofficial version of this library EPPlus.Core which can do the job of import and export xlsx in ASP.NET Core. This works on Windows, Linux and Mac.
معرفی DNTBreadCrumb
routes.MapRoute( "category_route", // Route name "MyControllerName/{category}/{productname}", // URL with parameters new { controller = "MyControllerName", action = "MyActionName", category = UrlParameter.Optional, productname = UrlParameter.Optional, area = "" } );
اجرای کوئریهای خام SQL بر روی بانک اطلاعاتی، توسط EF Core
گاهی از اوقات نیاز به استفادهی قابلیت خاصی از بانک اطلاعاتی مدنظر وجود دارد که توسط LINQ پشتیبانی نمیشود و یا کوئری SQL حاصل از LINQ to Entities آنچنان بهینه نیست. در یک چنین حالاتی راهی بجز نوشتن کوئریهای خام SQL وجود ندارد. امکان اجرای یک چنین کوئریهایی توسط EF Core پیش بینی شدهاست؛ اما با این محدودیتها:
- خروجی کوئری SQL، تنها باید معادل یکی از کلاسهای موجودیتهای شما باشد. قرار است این محدودیت در نگارش 1.1 برطرف شود.
- کوئری SQL نوشته شده باید تمام خواص موجودیتی را که قرار است به آن نگاشت شود، بازگشت دهد.
- نام ستونهای بازگشت داده شدهی توسط کوئری SQL باید با نام خواص موجودیت در حال کار، یکی باشند و برخلاف EF 6.x، از یک چنین عدم تطابقهایی صرفنظر نخواهد شد.
- کوئری SQL نوشته شده نباید به همراه اطلاعات ارتباطات موجودیتها باشد.
در اینجا برای نوشتن کوئریهای خام SQL میتوان از متد FromSql مرتبط با یکی از DbSetهای برنامه استفاده کرد:
var blogs = context.Blogs .FromSql("SELECT * FROM dbo.Blogs") .ToList();
var blogs = context.Blogs .FromSql("EXECUTE dbo.GetMostPopularBlogs") .ToList();
بنابراین رفتار EF Core اندکی متفاوت است با EF 6.x. در اینجا اگر میخواهید از عبارت SQL خود خروجی بگیرید، باید از یکی از DbSetهای خود شروع کنید و متد FromSql را بر روی آن فراخوانی نمائید. همچنین کوئری نوشته شده باید اولا تمام ستونهای آن DbSet رابازگشت دهد و به علاوه این ستونها دقیقا با نامهای خواص آن کلاس، تطابق داشته باشند.
علت این مسایل نیز به این دلیل است که بتوان نتیجهی کوئری را به صورت خودکار وارد سیستم change tracking کرد و همچنین کوئریهای ترکیبی LINQ را نیز در اینجا فعال کرد.
ارسال پارامترها به کوئریهای خام SQL
تنها حالتی در EF Core که مستعد به حملات تزریق SQL است، دقیقا همین مورد دور شدن از LINQ و نوشتن عبارات مستقیم SQL است. در اینجا برای نوشتن کوئریهای پارامتری دو حالت پیش بینی شدهاست:
الف) روش parameter place holders
در اینجا متد FromSql، بسیار شبیه به متد String.Format است، اما در عمل اینطور نیست و تمام place holders آن به صورت خودکار تبدیل به پارامتر میشوند:
var user = "johndoe"; var blogs = context.Blogs .FromSql("EXECUTE dbo.GetMostPopularBlogsForUser {0}", user) .ToList();
اگر میخواهید از پارامترهای نام دار استفاده کنید، با وهلهای از SqlParameter شروع کرده و سپس آنرا به متد FromSql ارسال کنید:
var user = new SqlParameter("user", "johndoe"); var blogs = context.Blogs .FromSql("EXECUTE dbo.GetMostPopularBlogsForUser @user", user) .ToList();
var results = _context.Contacts.FromSql( @"SELECT Id, Name Address, City, State, Zip FROM Contacts WHERE Name IN (@p0, @p1)", name1, name2);
مزیت کار کردن با SqlParameter این است که میتوان برای مثال Direction و SqlDbType را نیز صریحا ذکر کرد (بسته به نوع پارامترهای رویهی ذخیره شده):
var nameParameter = new SqlParameter { ParameterName = "@name", Value = "doc", Direction = ParameterDirection.Input, SqlDbType = SqlDbType.NVarChar };
امکان ترکیب کوئریهای SQL و LINQ نیز پیش بینی شدهاست
در کوئری ذیل، قسمت select از جدولی به صورت SQL و قسمت where و order by آن توسط LINQ تهیه شدهاند که در نهایت به یک کوئری ترجمه شده و بر روی بانک اطلاعاتی اجرا میشوند.
یک مثال جالب آن، امکان کوئری گرفتن از Table Value Functionها و سپس ترکیب آنها با LINQ است (این ترکیب، تنها یک کوئری SQL نهایی را تولید میکند):
var posts = context.Posts .FromSql("SELECT * FROM dbo.GetMatchingPostByTitle({0})", searchTerm) .Where(p => p.BlogId == 1) .OrderByDescending(p => p.CreateDate) .ToList();
واکشی ارتباطات یک موجودیت توسط SQL و LINQ
در ابتدای بحث در قسمت محدودیتهای کوئریهای SQL نوشته شده، ذکر شد «کوئری SQL نوشته شده نباید به همراه اطلاعات ارتباطات موجودیتها باشد». برای رفع این محدودیت میتوان از ترکیب SQL و LINQ به صورت ذیل استفاده کرد:
var searchTerm = ".NET"; var blogs = context.Blogs .FromSql("SELECT * FROM dbo.SearchBlogs {0}", searchTerm) .Include(b => b.Posts) .ToList();
اجرای عبارات SQL، بدون بازگشت مقداری
تا اینجا در مورد عبارات SQL از نوع Select و یا اجرای رویههای ذخیره شده، بحث شد. برای اجرای عبارات SQL ایی مانند update و delete میتوان از متد ExecuteSqlCommand مربوط به context.Database استفاده کرد:
context.Database.ExecuteSqlCommand("UPDATE dbo.People SET FirstName = 'Jane' WHERE PersonId = 30");
context.Database.ExecuteSqlCommand("usp_CreateShipper @p0, @p1", parameters: new[] { "hello", "world" });
اجرای عبارات SQL و دریافت خروجیهایی به غیر از موجودیتهای برنامه
در ابتدا بحث عنوان شد که محدودیت فعلی کوئریهای FromSQL که میتوانند خروجی را نیز ارائه دهند، مقید بودن آنها به DbSet در حال استفاده است و محدود بودن آنها به خواص کلاس متناظر تعریف شده. در این حالت اگر بخواهیم یک محاسبهی عددی را بازگشت دهیم چه باید کرد؟
متد ExecuteSqlCommand تنها وضعیت نهایی اجرای عملیات را بازگشت میدهد و FromSQL مقید است به DbSet متناظر. برای رفع این محدودیتها میتوان مستقیما به DbConnection دسترسی یافت و سپس کوئری گرفت؛ به نحو ذیل:
using (var connection = context.Database.GetDbConnection()) { connection.Open(); using (var command = connection.CreateCommand()) { command.CommandText = "SELECT COUNT(*) FROM Contacts"; var result = command.ExecuteScalar().ToString(); } }
در اینجا نیز برای بررسی ویژگیهای جاوا اسکریپت مدرن، یک پروژهی جدید React را ایجاد میکنیم.
> create-react-app sample-03 > cd sample-03 > npm start
همچنین چون در این قسمت خروجی UI نخواهیم داشت، تمام خروجی را در کنسول developer tools مرورگر خود میتوانید مشاهده کنید (فشردن دکمهی F12).
متد Array.map
در برنامههای مبتنی بر React، از متد Array.map برای رندر لیستها استفاده میشود و نمونههای بیشتری از آنرا در قسمتهای بعدی مشاهده خواهید کرد.
فرض کنید آرایهای از رنگها را داریم. اکنون میخواهیم لیستی را به صورت <li>color</li> به ازای هر آیتم آن، تشکیل دهیم:
const colors = ["red", "green", "blue"];
const items = colors.map(function(color) { return "<li>" + color + "</li>"; }); console.log(items);
این مثال را توسط arrow functions نیز میتوان بازنویسی کرد:
const items2 = colors.map(color => "<li>" + color + "</li>"); console.log(items2);
یک مرحلهی دیگر هم میتوانیم این قطعه کد را زیباتر کنیم؛ جمع زدن رشتهها در ES6 معادل بهتری پیدا کردهاست که template literals نام دارد:
const items3 = colors.map(color => `<li>${color}</li>`); console.log(items3);
Object Destructuring
فرض کنید شیء آدرس را به صورت زیر تعریف کردهایم:
const address = { street: "street 1", city: "city 1", country: "country 1" };
const street1 = address.street; const city1 = address.city; const country1 = address.country;
const { street, city, country } = address;
در اینجا باید نام متغیرهای تعریف شده با نام خواص شیء آدرس یکی باشند. همچنین ذکر تمامی این متغیرها نیز ضرورتی ندارد و برای مثال اگر فقط نیاز به street بود، میتوان تنها آنرا ذکر کرد.
اگر خواستیم نام متغیر دیگری را بجای نام خواص شیء آدرس انتخاب کنیم، میتوان از یک نام مستعار ذکر شدهی پس از : استفاده کرد:
const { street: st } = address; console.log(st);
Spread Operator
فرض کنید دو آرایهی زیر را داریم:
const first = [1, 2, 3]; const second = [4, 5, 6];
const combined = first.concat(second); console.log(combined);
در ES6 با استفاده از عملگر ... که spread نیز نام دارد، میتوان قطعه کد فوق را به صورت زیر بازنویسی کرد:
const combined2 = [...first, ...second]; console.log(combined2);
شاید اینطور به نظر برسد که بین دو راه حل ارائه شده آنچنانی تفاوتی نیست. اما مزیت قطعه کد دوم، سهولت افزودن المانهای جدید، به هر قسمتی از آرایه است:
const combined2 = [...first, "a", ...second, "b"]; console.log(combined2);
کاربرد دیگر عملگر spread امکان clone سادهی یک آرایهاست:
const clone = [...first]; console.log(clone);
به علاوه امکان اعمال آن به اشیاء نیز وجود دارد:
const firstObject = { name: "User 1" }; const secondObject = { job: "Job 1" }; const combinedObject = { ...firstObject, ...secondObject, location: "Here" }; console.log(combinedObject);
{name: "User 1", job: "Job 1", location: "Here"}
و امکان clone اشیاء توسط آن هم وجود دارد:
const clonedObject = { ...firstObject }; console.log(clonedObject);
کلاسها در ES 6
قطعه کد کلاسیک زیر را که کار ایجاد اشیاء را در جاوا اسکریپت انجام میدهد، در نظر بگیرید:
const person = { name: "User 1", walk() { console.log("walk"); } }; const person2 = { name: "User 2", walk() { console.log("walk"); } };
class Person { constructor(name) { this.name = name; } walk() { console.log("walk"); } }
باید دقت داشت که class Person تنها یک قالب است و const person ای که پیشتر تعریف شد، یک شیء. برای اینکه از روی قالب تعریف شدهی Person، یک شیء را ایجاد کنیم، به صورت زیر توسط واژهی کلیدی new عمل میشود:
const person3 = new Person("User 3"); console.log(person3.name); person3.walk();
یک نکته: در جاوا اسکریپت، کلاسها نیز شیء هستند! از این جهت که کلاسها در جاوا اسکریپت صرفا یک بیان نحوی زیبای تابع constructor هستند و توابع در جاوا اسکریپت نیز شیء میباشند!
ارث بری کلاسها در ES6
فرض کنید میخواهیم کلاس Teacher را به نحو زیر تعریف کنیم:
class Teacher { teach() { console.log("teach"); } }
class Teacher extends Person { teach() { console.log("teach"); } }
علت اینجا است که کلاس Teacher، نه فقط متد walk کلاس Person را به ارث بردهاست، بلکه سازندهی آنرا نیز به ارث میبرد:
const teacher = new Teacher("User 4");
console.log(teacher.name); teacher.teach(); teacher.walk();
در ادامه فرض کنید علاوه بر ذکر نام، نیاز به ذکر مدرک معلم نیز در سازندهی کلاس وجود دارد:
class Teacher extends Person { constructor(name, degree) {}
Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
class Teacher extends Person { constructor(name, degree) { super(name); this.degree = degree; } teach() { console.log("teach"); } }
const teacher = new Teacher("User 4", "MSc");
در برنامههای React، هر زمانیکه یک کامپوننت جدید تعریف میشود، کلاس آن، از کلاس پایهی کامپوننت، ارث بری خواهد کرد. به این ترتیب میتوان به تمام امکانات این کلاس پایه، بدون نیاز به تکرار آنها در کلاسهای مشتق شدهی از آن، دسترسی یافت.
ماژولها در ES 6
تا اینجا اگر مثالها را دنبال کرده باشید، تمام آنها را داخل همان فایل index.js درج کردهایم. به این ترتیب کم کم دارد مدیریت این فایل از دست خارج میشود. امکان تقسیم کدهای index.js به چندین فایل، مفهوم ماژولها را در ES6 تشکیل میدهد. برای این منظور قصد داریم هر کلاس تعریف شده را به یک فایل جداگانه که ماژول نامیده میشود، منتقل کنیم. از کلاس Person شروع میکنیم و آنرا به فایل جدید person.js و کلاس Teacher را به فایل جدید teacher.js منتقل میکنیم.
البته اگر از افزونههای VSCode استفاده میکنید، اگر کرسر را بر روی نام کلاس قرار دهید، یک آیکن لامپ مانند ظاهر میشود. با کلیک بر روی آن، منویی که شامل گزینهی move to a new file هست، برای انجام سادهتر این عملیات (ایجاد یک فایل جدید js، سپس انتخاب و cut کردن کل کلاس و در آخر کپی کردن آن در این فایل جدید) پیشبینی شدهاست.
هرچند این عملیات تا به اینجا خاتمه یافته به نظر میرسد، اما نیاز به اصلاحات زیر را نیز دارد:
- هنگام کار با ماژولها، اشیاء تعریف شدهی در آن به صورت پیشفرض، خصوصی و private هستند و خارج از آنها قابل دسترسی نمیباشند. به این معنا که class Teacher ما که اکنون در یک ماژول جدید قرار گرفتهاست، توسط سایر قسمتهای برنامه قابل مشاهده و دسترسی نیست.
- برای public تعریف کردن یک کلاس تعریف شدهی در یک ماژول، نیاز است آنرا export کنیم. انجام این کار نیز سادهاست. فقط کافی است واژهی کلیدی export را به پیش از class اضافه کنیم:
export class Teacher extends Person {
برای رفع این مشکل، باید این وابستگی را import کرد:
import { Person } from "./Person"; export class Teacher extends Person {
- مرحلهی آخر، اصلاح فایل index.js است؛ چون اکنون تعاریف Person و Teacher را نمیشناسد.
import { Person } from "./Person"; import { Teacher } from "./Teacher";
Exportهای پیشفرض و نامدار در ES6
اشیاء تعریف شدهی در یک ماژول، به صورت پیشفرض private هستند؛ مگر اینکه export شوند. برای مثال export class Teacher و یا export function xyz. به اینها named exports گویند. حال اگر ماژول ما تنها یک شیء عمومی شده را داشت (کلاسها هم شیء هستند!)، میتوان از واژهی کلیدی default نیز در اینجا استفاده کرد:
export default class Teacher extends Person {
import Teacher from "./Teacher";
در ادامه اگر یک export نامدار دیگر را به این ماژول اضافه کنیم (مانند تابع testTeacher):
import { Person } from "./Person"; export function testTeacher() { console.log("Test Teacher"); } export default class Teacher extends Person {
import Teacher, { testTeacher } from "./Teacher";
import React, { Component } from 'react';
یک نکته: اگر در VSCode داخل {}، دکمههای ctrl+space را فشار دهید، میتوانید منوی exportهای ماژول تعریف شده را مشاهده کنید.
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: sample-03.zip