اشتراکها
با استفاده از مونو امکان اجرای برنامههای دات نت تحت لینوکس وجود دارند. در ادامه سعی خواهیم کرد تا نگارش 3 آنرا بر روی اوبونتو نصب کنیم. مونو 3 تا دات نت 4 و نیم را پشتیبانی میکند.
دریافت اوبونتو
برای دریافت اوبونتو به آدرس ذیل مراجعه نمائید.
نسخه سرور آن GUI ندارد (هرچند بعدا در طی یک بسته 450 مگابایتی قابل نصب است). نسخه دسکتاپ آن به همراه GUI نیز هست. البته برای نصب دات نت بر روی آن این مساله تفاوتی نمیکند. برای نصب آزمایشی و مجازی آن هم میتوانید برای مثال از VMWare workstation استفاده کنید؛ بدون اینکه نیاز داشته باشید این توزیع خاص لینوکس را واقعا بر روی کامپیوتر خود نصب کنید.
در تمام قسمتهای ذیل فرض بر این است که ترمینال خط فرمان لینوکس را گشودهاید و همچنین سیستم به اینترنت وصل است.
دریافت Git و Curl
ابتدا دستور زیر را در خط فرمان لینوکس اجرا کنید تا سیستم بستههای لینوکس به روز شده و همچنین یک سری پیشنیاز مانند git ، curl و امثال آن نصب شوند (کتابخانه curl جهت استفاده در محیطهای برنامه نویسی کاربرد دارد و همچنین برنامه پیشرفتهای است برای کار با وب و دریافت فایلها):
نصب آخرین نگارش Mono و وابستگیهای آن
در ادامه نوبت به نصب آخرین نگارش مونو است. از روش متداول ذیل برای نصب مونو استفاده نکنید :
این دستور نگارش 2.10.8.1 را تا این تاریخ بر روی سیستم شما نصب خواهد کرد و اگر پیشتر مونو را به این روش نصب کردهاید، با استفاده از دستور ذیل آنرا حذف کنید:
برای دسترسی به آخرین نگارش نگارش مونو، نیاز است آنرا از روی سورس آن کامپایل کنیم. اسکریپت کامل نصب آنرا در آدرس ذیل میتوانید پیدا کنید:
و یا اگر آدرس فوق برقرار نبود از اینجا: install_mono-3.0-sh
برای نمونه جهت نصب mono نگارش 3 از اسکریپت install_mono-3.0.sh به نحو ذیل استفاده خواهیم کرد (این دستورات را به ترتیب در ترمینال لینوکس اجرا کنید):
این پروسه مدتی طول خواهد کشید (تا تمام بستههای لازم از اینترنت دریافت شوند). استفاده از اسکریپت فوق کار را بسیار ساده کرده و بسیاری از مراحل لازم نصب مونو را یکجا در خود به همراه دارد. مونو 3 تا دات نت 4 و نیم را پشتیبانی میکند.
بعد از اجرای فرمان فوق به خطای ذیل خواهید رسید:
این مورد مشکلی است که در نگارش 3.0.10 رخ داده و فراموش کردهاند که یک پوشه را کپی کنند (در نگارشهای قبلی آن این مشکل وجود نداشته و با توجه به آگاه شدن از آن، در نگارشهای بعدی نیز نباید مشکلی باشد).
برای رفع آن ابتدا به مسیر ذیل وارد شوید (پوشه build/mono-3.0.10/po)، فایل mcs را حذف (این مورد در اصل یک پوشه است و نه یک فایل) و سپس بسته اصلی mono را از github دریافت کنید. آنرا unzip کرده و کل پوشه mcs داخل آنرا به درون پوشه po جاری کپی کنید. سپس فایل zip دریافت شده را حذف کنید:
البته برای اینکه وقت شما زیاد تلف نشود، پوشه mcs نگارش 3.0.10 را از آدرس ذیل دریافت و پس از unzip درون پوشه mono-3.0/build/mono-3.0.10/po کپی کنید. (6 سطر فوق هم نیازی به اجرا ندارند)
پس از باز سازی پوشه مفقود mcs، باید مرحله «building mono packages» موجود در فایل install_mono-3.0.sh اجرا شود. برای این منظور، فایل final-build-mono-3.0.sh را از آدرس ذیل دریافت و در کنار فایل install_mono-3.0.sh موجود کپی کنید.
سپس در خواص این فایل، مجوز execute را نیز فعال نمائید. اکنون آنرا اجرا کنید:
فایل final-build-mono-3.0.sh در حقیقت همان فایل install_mono-3.0.sh اصلی است. با این تفاوت که قسمت ابتدای فایل که در آن وابستگیهای لازم از اینترنت دریافت میشدند، حذف شده است. چون پیشتر اینکار را انجام داده بودیم (با اجرای اولیه آن).
اکنون مدتی صبر کنید تا کار کامپایل نهایی تمام بستههای دریافت شده پس از اجرای اسکریپت final-build-mono-3.0.sh انجام شود.
آزمایش Mono نصب شده
برای اینکه مطمئن شویم، Mono درست نصب شده است، دستور زیر را در خط فرمان صادر کنید:
برای اینکه این مسیر را به Path لینوکس اضافه کنیم تا قادر شویم فرمان mono را در هر مسیری اجرا کنیم، ابتدا دستور ذیل را اجرا کرده
و سپس در ادیتور باز شده، مسیر و عبارات ذیل را به انتهای مقدار جاری اضافه کنید:
بعد ctrl+x را زده، به پیام ذخیره سازی تغییرات پاسخ مثبت دهید. سپس نیاز است یکبار logoff و login کنید تا این تغییرات اعمال شوند.
یک نکته تکمیلی:
اگر به صفحه نگارشهای رسمی Mono 3.x مراجعه کنید، نگارشهای جدیدتری را نیز میتوانید ملاحظه کنید. فایلهای قابل نصب آنها نیر در آدرسهای ذیل قرار دارند:
برای استفاده از اسکریپت install_mono-3.0.sh با این نگارشهای جدیدتر فقط کافی است تعاریف ذیل را بر اساس شماره نگارش بستههای جدید اصلاح کنید:
دریافت اوبونتو
برای دریافت اوبونتو به آدرس ذیل مراجعه نمائید.
نسخه سرور آن GUI ندارد (هرچند بعدا در طی یک بسته 450 مگابایتی قابل نصب است). نسخه دسکتاپ آن به همراه GUI نیز هست. البته برای نصب دات نت بر روی آن این مساله تفاوتی نمیکند. برای نصب آزمایشی و مجازی آن هم میتوانید برای مثال از VMWare workstation استفاده کنید؛ بدون اینکه نیاز داشته باشید این توزیع خاص لینوکس را واقعا بر روی کامپیوتر خود نصب کنید.
در تمام قسمتهای ذیل فرض بر این است که ترمینال خط فرمان لینوکس را گشودهاید و همچنین سیستم به اینترنت وصل است.
دریافت Git و Curl
ابتدا دستور زیر را در خط فرمان لینوکس اجرا کنید تا سیستم بستههای لینوکس به روز شده و همچنین یک سری پیشنیاز مانند git ، curl و امثال آن نصب شوند (کتابخانه curl جهت استفاده در محیطهای برنامه نویسی کاربرد دارد و همچنین برنامه پیشرفتهای است برای کار با وب و دریافت فایلها):
sudo apt-get update && sudo apt-get -y install git-core curl python-software-properties sudo apt-get install build-essential automake checkinstall intltool git
نصب آخرین نگارش Mono و وابستگیهای آن
در ادامه نوبت به نصب آخرین نگارش مونو است. از روش متداول ذیل برای نصب مونو استفاده نکنید :
sudo apt-get install mono-complete
sudo apt-get purge mono-runtime
و یا اگر آدرس فوق برقرار نبود از اینجا: install_mono-3.0-sh
برای نمونه جهت نصب mono نگارش 3 از اسکریپت install_mono-3.0.sh به نحو ذیل استفاده خواهیم کرد (این دستورات را به ترتیب در ترمینال لینوکس اجرا کنید):
mkdir mono-3.0 cd mono-3.0 wget --no-check-certificate https://github.com/nathanb/iws-snippets/raw/master/mono-install-scripts/ubuntu/install_mono-3.0.sh chmod 755 install_mono-3.0.sh ./install_mono-3.0.sh
بعد از اجرای فرمان فوق به خطای ذیل خواهید رسید:
config.status: error: cannot find input file: `po/mcs/Makefile.in.in'
برای رفع آن ابتدا به مسیر ذیل وارد شوید (پوشه build/mono-3.0.10/po)، فایل mcs را حذف (این مورد در اصل یک پوشه است و نه یک فایل) و سپس بسته اصلی mono را از github دریافت کنید. آنرا unzip کرده و کل پوشه mcs داخل آنرا به درون پوشه po جاری کپی کنید. سپس فایل zip دریافت شده را حذف کنید:
cd mono-3.0/build/mono-3.0.10/po rm mcs wget https://github.com/mono/mono/archive/master.zip unzip master.zip mv mcs/ mono-3.0/build/mono-3.0.10/po rm -rf mono-master master.zip
پس از باز سازی پوشه مفقود mcs، باید مرحله «building mono packages» موجود در فایل install_mono-3.0.sh اجرا شود. برای این منظور، فایل final-build-mono-3.0.sh را از آدرس ذیل دریافت و در کنار فایل install_mono-3.0.sh موجود کپی کنید.
سپس در خواص این فایل، مجوز execute را نیز فعال نمائید. اکنون آنرا اجرا کنید:
./final-build-mono-3.0.sh
اکنون مدتی صبر کنید تا کار کامپایل نهایی تمام بستههای دریافت شده پس از اجرای اسکریپت final-build-mono-3.0.sh انجام شود.
آزمایش Mono نصب شده
برای اینکه مطمئن شویم، Mono درست نصب شده است، دستور زیر را در خط فرمان صادر کنید:
/opt/mono-3.0/bin/mono -V
برای اینکه این مسیر را به Path لینوکس اضافه کنیم تا قادر شویم فرمان mono را در هر مسیری اجرا کنیم، ابتدا دستور ذیل را اجرا کرده
sudo nano /etc/environment
:/opt/mono-3.0/bin
بعد ctrl+x را زده، به پیام ذخیره سازی تغییرات پاسخ مثبت دهید. سپس نیاز است یکبار logoff و login کنید تا این تغییرات اعمال شوند.
یک نکته تکمیلی:
اگر به صفحه نگارشهای رسمی Mono 3.x مراجعه کنید، نگارشهای جدیدتری را نیز میتوانید ملاحظه کنید. فایلهای قابل نصب آنها نیر در آدرسهای ذیل قرار دارند:
برای استفاده از اسکریپت install_mono-3.0.sh با این نگارشهای جدیدتر فقط کافی است تعاریف ذیل را بر اساس شماره نگارش بستههای جدید اصلاح کنید:
PACKAGES=("mono-3.0.10" "libgdiplus-2.10.9" "gtk-sharp-2.12.11" "xsp-2.10.2" "mod_mono-2.10") URLS=("http://download.mono-project.com/sources/mono/mono-3.0.10.tar.bz2" "http://download.mono-project.com/sources/libgdiplus/libgdiplus-2.10.9.tar.bz2" "http://download.mono-project.com/sources/gtk-sharp212/gtk-sharp-2.12.11.tar.bz2" "http://download.mono-project.com/sources/xsp/xsp-2.10.2.tar.bz2" "http://download.mono-project.com/sources/mod_mono/mod_mono-2.10.tar.bz2")
با سلام. در سمت api وقتی میخوام Id کاربر رو از claim بخونم "sub" رو بهم خالی برمیگردونه !
var ownerId = this.User.Claims.FirstOrDefault(claim => claim.Type == "sub")?.Value; var response = await httpClient.GetAsync($"api/v1/orders/GetOrderByIdAsync?id={ownerId}");
public static IEnumerable<Client> Clients => new List<Client> { new Client { ClientId = "oidcClient", ClientName = "Example Client Application", ClientSecrets = new List<Secret> {new Secret("VQGBtSDEK7tzIzSJyfCYqdHDTQHt7kD2VQ1hHWnY7Dw=".Sha256())}, // change me! AllowedGrantTypes = GrantTypes.Hybrid, RedirectUris = new List<string> {"https://localhost:6001/signin-oidc"}, PostLogoutRedirectUris = new List<string> { "https://localhost:6001/signout-callback-oidc" }, AllowedScopes = new List<string> { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile, IdentityServerConstants.StandardScopes.Email, IdentityServerConstants.StandardScopes.Address, "role", "api.ordering.manager" }, RequirePkce=false, AllowOfflineAccess = true } };
public static IEnumerable<IdentityResource> Resources => new List<IdentityResource> { new IdentityResources.OpenId(), new IdentityResources.Profile(), new IdentityResources.Email(), new IdentityResources.Address(), new IdentityResource { Name = "role", UserClaims = new List<string> {"role"} } };
نظرات مطالب
اتصال SQL Server به MySQL
دو نکته تکمیلی:
- برای انتقال کل اطلاعات یک جدول از SQL Server به MySQL لینک شده با اجرای فقط یک کوئری:
insert into openquery(mysql, 'select f1,f2 from testdb.testtable') select f1,f2 from testdb.dbo.myTable
در اینجا testdb.testtable مربوط به طرف MySQL است و testdb.dbo.myTable مربوط به طرف SQL Server .
- کوئری گرفتن از Linked server به صورت زیر هم میتواند باشد (بر اساس دیتابیس پیش فرض ذکر شده در پروایدر استرینگ):
SELECT * FROM mysql...testtable
- برای انتقال کل اطلاعات یک جدول از SQL Server به MySQL لینک شده با اجرای فقط یک کوئری:
insert into openquery(mysql, 'select f1,f2 from testdb.testtable') select f1,f2 from testdb.dbo.myTable
در اینجا testdb.testtable مربوط به طرف MySQL است و testdb.dbo.myTable مربوط به طرف SQL Server .
- کوئری گرفتن از Linked server به صورت زیر هم میتواند باشد (بر اساس دیتابیس پیش فرض ذکر شده در پروایدر استرینگ):
SELECT * FROM mysql...testtable
تنظیم یک Sequence به صورت زیر
modelBuilder.HasSequence<int>("OrderNumbers", schema: "shared") .StartsAt(1000).IncrementsBy(5);
modelBuilder.Entity<PrimaryKeyWithSequence>(entity => { entity.Property(e => e.PrimaryKeyWithSequenceId).HasDefaultValueSql("NEXT VALUE FOR [PrimaryKeyWithSequenceSequence]"); });
CREATE TABLE PrimaryKeyWithSequence ( ID int PRIMARY KEY CLUSTERED DEFAULT (NEXT VALUE FOR [PrimaryKeyWithSequenceSequence]), Field1 nvarchar(300) NULL ) ;
اما برای حالت batch و مشخص بودن Id آنها، از همین روش با متد خاص ForSqlServerUseSequenceHiLo استفاده میشود:
modelbuilder.HasSequence<int>("DBSequenceHiLo") .StartsAt(1000).IncrementsBy(5); modelbuilder.ForSqlServerUseSequenceHiLo("DBSequenceHiLo");
CREATE SEQUENCE [dbo].[DBSequenceHiLo] AS [int] START WITH 1000 INCREMENT BY 5 MINVALUE -2147483648 MAXVALUE 2147483647 CACHE GO
using (var dataContext = new SampleDBContext()) { dataContext.Categories.Add(new Category() { CategoryName = "Clothing" }); dataContext.Categories.Add(new Category() { CategoryName = "Footwear" }); dataContext.Categories.Add(new Category() { CategoryName = "Accessories" }); dataContext.SaveChanges(); dataContext.Products.Add(new Product() { ProductName = "TShirts" }); dataContext.Products.Add(new Product() { ProductName = "Shirts" }); dataContext.Products.Add(new Product() { ProductName = "Causal Shoes" }); dataContext.SaveChanges(); }
و سپس کوئری insert اصلی، دارای idهای از پیش تعیین شدهای میشود که اینبار نیازی نیست تا یکی یکی رکوردها insert شوند و id بعدی محاسبه شود:
اشتراکها
نگاهی به جلسات کنفرانس React Europe
پس از معرفی اجمالی OpenAPI و Swagger در قسمت قبل و همچنین ارائهی یک برنامهی نمونه که آنرا به مرور تکمیل خواهیم کرد، در ادامه کتابخانهی Swashbuckle را نصب کرده و شروع به مستند سازی API ارائه شده خواهیم کرد.
نصب Swashbuckle (سوواَش باکِل)
اگر عبارت Swashbuckle.AspNetCore را در سایت NuGet جستجو کنیم، چندین بستهی مختلف مرتبط با آنرا خواهیم یافت. ما در این بین، بیشتر به این بستهها علاقمندیم:
- Swashbuckle.AspNetCore.Swagger: کار آن ارائهی خروجی OpenAPI تولیدی بر اساس ASP.NET Core API برنامهی ما، به صورت یک JSON Endpoint است.
- Swashbuckle.AspNetCore.SwaggerGen: کار آن ساخت Swagger document objects است؛ یا همان OpenAPI Specification.
عموما این دو بسته را با هم جهت ارائهی OpenAPI Specification استفاده میکنند.
- Swashbuckle.AspNetCore.SwaggerUI: این بسته، نگارش جایگذاری شدهی (embedded) ابزار swagger-UI را به همراه دارد. کار آن، ارائهی یک UI خودکار، بر اساس OpenAPI Specification است که از آن برای آزمایش API نیز میتوان استفاده کرد.
یک نکته: اگر صرفا بستهی Swashbuckle.AspNetCore را نصب کنیم، هر سه بستهی فوق را با هم دریافت خواهیم کرد و اگر از Visual Studio برای نصب آنها استفاده میکنید، انتخاب گزینهی Include prerelease را فراموش نکنید؛ از این جهت که قصد داریم از نگارش 5 آنها استفاده کنیم. چون این نگارش است که از OpenAPI 3x، پشتیبانی میکند. خلاصهی این موارد، افزودن PackageReference زیر به فایل پروژهی OpenAPISwaggerDoc.Web.csproj است و سپس اجرای دستور dotnet restore:
تنظیم میانافزار Swashbuckle
پس از افزودن ارجاعی به Swashbuckle.AspNetCore، اکنون نوبت انجام تنظیمات میانافزارهای آن است. برای این منظور ابتدا به کلاس Startup و متد ConfigureServices آن مراجعه میکنیم:
در اینجا نحوهی تنظیمات ابتدایی سرویسهای مرتبط با SwaggerGen را ملاحظه میکنید. ابتدا نیاز است یک SwaggerDoc به آن اضافه شود که یک name و info را دریافت میکند. این name، جزئی از آدرسی است که در نهایت، OpenAPI Specification تولیدی را میتوان در آنجا یافت. پارامتر Info آن نیز به همراه یک سری مشخصات عمومی درج شدهی در مستندات OpenAPI است.
اکنون در متد Configure، میانافزار آنرا خواهیم افزود:
بهتر است UseSwagger را پس از UseHttpsRedirection درج کرد تا هر نوع درخواست HTTP به آن، به صورت خودکار به HTTPS تبدیل و هدایت شود.
تا اینجا اگر برنامه را اجرا کنید، میتوان OpenAPI Specification تولیدی را در آدرس زیر یافت:
در این آدرس، LibraryOpenAPISpecification، همان نامی است که در قسمت setupAction.SwaggerDoc تنظیم کردیم.
نگاهی به OpenAPI Specification تولیدی
در ابتدای swagger.json تولیدی، همانطور که در تصویر فوق نیز مشخص است، همان مشخصات ذکر شدهی در قسمت info متد setupAction.SwaggerDoc، قابل مشاهدهاست. سپس لیست مسیرهای این API مشخص شدهاند:
اینها مسیرهایی هستند که توسط دو کنترلر کتابها و نویسندگان برنامهی Web API ما عمومی شدهاند. در اینجا مقابل هر مسیر، تعداد آیتمهای متناظری نیز ذکر شدهاند. این موارد مرتبط هستند با HTTP methods پشتیبانی شده:
که هر کدام به همراه نام متدها و پارامترهای متناظر با آنها نیز میشوند. به علاوه نوع responseهای پشتیبانی شدهی توسط این متدها نیز ذکر شدهاند. هر کدام از خروجیها نیز نوع مشخصی دارند که توسط قسمت components -> schemas تصاویر فوق، جزئیات دقیق آنها بر اساس نوع مدلهای متناظر، استخراج و ارائه شدهاند.
مشکل: نوع Response تولیدی در OpenAPI Specification صحیح نیست
اگر به جزئیات مسیر /api/authors/{authorId} دقت کنیم، نوع response آنرا صرفا 200 یا Ok ذکر کردهاست؛ در حالیکه GetAuthor تعریف شده، حالت NotFound را نیز دارد:
نمونهی دیگر آن اکشن متد public async Task<ActionResult<Book>> CreateBook است که میتواند NotFound یا 404 و یا CreatedAtRoute را که معادل 201 است، بازگشت دهد و در اینجا فقط 200 را ذکر کردهاست که اشتباه است. بنابراین برای نزدیک کردن این خروجی به اطلاعات واقعی اکشن متدها، نیاز است کار بیشتری انجام شود.
افزودن و راه اندازی Swagger UI
در ادامه میخواهیم یک رابط کاربری خودکار را بر اساس OpenAPI Specification تولیدی، ایجاد کنیم:
برای این منظور میانافزار SwaggerUI را پس از UseSwagger، در متد Configure کلاس Startup، تعریف میکنیم. در اینجا باید مشخص کنیم که OpenAPI Specification تولید شده، دقیقا در چه آدرسی قرار دارد که روش انجام آنرا در متد setupAction.SwaggerEndpoint ملاحظه میکنید. پارامتر دوم آن یک نام اختیاری است.
پس از این تنظیم اگر آدرس https://localhost:5001/swagger/index.html را در مرورگر باز کنیم، چنین خروجی قابل مشاهده خواهد بود:
و اگر بر روی هر کدام کلیک کنیم، ریز جزئیات آنها بر اساس OpenAPI Specification ای که بررسی کردیم، تولید شدهاست (از پارامترها تا نوع خروجی):
اکنون اگر بر روی دکمهی try it out آن نیز کلیک کنید، در همینجا میتوان این API را آزمایش کرد. برای مثال Controls Accept header را بر روی application/json قرار داده و سپس بر روی دکمهی execute که پس از کلیک بر روی دکمهی try it out ظاهر شدهاست، کلیک کنید تا بتوان خروجی Web API را مشاهده کرد.
در انتهای این صفحه، در قسمت schemas آن، مشخصات مدلهای بازگشت داده شدهی توسط Web API نیز ذکر شدهاند:
یک نکته: تغییر آدرس https://localhost:5001/swagger/index.html به ریشهی سایت
اگر علاقمند باشید تا زمانیکه برای اولین بار آدرس ریشهی سایت را در مسیر https://localhost:5001 باز میکنید، Swagger UI نمایان شود، میتوانید تنظیم RoutePrefix زیر را اضافه کنید:
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: OpenAPISwaggerDoc-02.zip
در قسمت بعد، به بهبود و غنی سازی جزئیات OpenAPI Specification تولیدی خواهیم پرداخت.
نصب Swashbuckle (سوواَش باکِل)
اگر عبارت Swashbuckle.AspNetCore را در سایت NuGet جستجو کنیم، چندین بستهی مختلف مرتبط با آنرا خواهیم یافت. ما در این بین، بیشتر به این بستهها علاقمندیم:
- Swashbuckle.AspNetCore.Swagger: کار آن ارائهی خروجی OpenAPI تولیدی بر اساس ASP.NET Core API برنامهی ما، به صورت یک JSON Endpoint است.
- Swashbuckle.AspNetCore.SwaggerGen: کار آن ساخت Swagger document objects است؛ یا همان OpenAPI Specification.
عموما این دو بسته را با هم جهت ارائهی OpenAPI Specification استفاده میکنند.
- Swashbuckle.AspNetCore.SwaggerUI: این بسته، نگارش جایگذاری شدهی (embedded) ابزار swagger-UI را به همراه دارد. کار آن، ارائهی یک UI خودکار، بر اساس OpenAPI Specification است که از آن برای آزمایش API نیز میتوان استفاده کرد.
یک نکته: اگر صرفا بستهی Swashbuckle.AspNetCore را نصب کنیم، هر سه بستهی فوق را با هم دریافت خواهیم کرد و اگر از Visual Studio برای نصب آنها استفاده میکنید، انتخاب گزینهی Include prerelease را فراموش نکنید؛ از این جهت که قصد داریم از نگارش 5 آنها استفاده کنیم. چون این نگارش است که از OpenAPI 3x، پشتیبانی میکند. خلاصهی این موارد، افزودن PackageReference زیر به فایل پروژهی OpenAPISwaggerDoc.Web.csproj است و سپس اجرای دستور dotnet restore:
<Project Sdk="Microsoft.NET.Sdk.Web"> <ItemGroup> <PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc2" /> </ItemGroup> </Project>
تنظیم میانافزار Swashbuckle
پس از افزودن ارجاعی به Swashbuckle.AspNetCore، اکنون نوبت انجام تنظیمات میانافزارهای آن است. برای این منظور ابتدا به کلاس Startup و متد ConfigureServices آن مراجعه میکنیم:
namespace OpenAPISwaggerDoc.Web { public class Startup { public void ConfigureServices(IServiceCollection services) { // ... services.AddSwaggerGen(setupAction => { setupAction.SwaggerDoc( name: "LibraryOpenAPISpecification", info: new Microsoft.OpenApi.Models.OpenApiInfo() { Title = "Library API", Version = "1", Description = "Through this API you can access authors and their books.", Contact = new Microsoft.OpenApi.Models.OpenApiContact() { Email = "name@site.com", Name = "DNT", Url = new Uri("https://www.dntips.ir") }, License = new Microsoft.OpenApi.Models.OpenApiLicense() { Name = "MIT License", Url = new Uri("https://opensource.org/licenses/MIT") } }); }); }
اکنون در متد Configure، میانافزار آنرا خواهیم افزود:
namespace OpenAPISwaggerDoc.Web { public class Startup { public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // ... app.UseHttpsRedirection(); app.UseSwagger(); // ... }
تا اینجا اگر برنامه را اجرا کنید، میتوان OpenAPI Specification تولیدی را در آدرس زیر یافت:
https://localhost:5001/swagger/LibraryOpenAPISpecification/swagger.json
در این آدرس، LibraryOpenAPISpecification، همان نامی است که در قسمت setupAction.SwaggerDoc تنظیم کردیم.
نگاهی به OpenAPI Specification تولیدی
در ابتدای swagger.json تولیدی، همانطور که در تصویر فوق نیز مشخص است، همان مشخصات ذکر شدهی در قسمت info متد setupAction.SwaggerDoc، قابل مشاهدهاست. سپس لیست مسیرهای این API مشخص شدهاند:
اینها مسیرهایی هستند که توسط دو کنترلر کتابها و نویسندگان برنامهی Web API ما عمومی شدهاند. در اینجا مقابل هر مسیر، تعداد آیتمهای متناظری نیز ذکر شدهاند. این موارد مرتبط هستند با HTTP methods پشتیبانی شده:
که هر کدام به همراه نام متدها و پارامترهای متناظر با آنها نیز میشوند. به علاوه نوع responseهای پشتیبانی شدهی توسط این متدها نیز ذکر شدهاند. هر کدام از خروجیها نیز نوع مشخصی دارند که توسط قسمت components -> schemas تصاویر فوق، جزئیات دقیق آنها بر اساس نوع مدلهای متناظر، استخراج و ارائه شدهاند.
مشکل: نوع Response تولیدی در OpenAPI Specification صحیح نیست
اگر به جزئیات مسیر /api/authors/{authorId} دقت کنیم، نوع response آنرا صرفا 200 یا Ok ذکر کردهاست؛ در حالیکه GetAuthor تعریف شده، حالت NotFound را نیز دارد:
[HttpGet("{authorId}")] public async Task<ActionResult<Author>> GetAuthor(Guid authorId) { var authorFromRepo = await _authorsService.GetAuthorAsync(authorId); if (authorFromRepo == null) { return NotFound(); } return Ok(_mapper.Map<Author>(authorFromRepo)); }
افزودن و راه اندازی Swagger UI
در ادامه میخواهیم یک رابط کاربری خودکار را بر اساس OpenAPI Specification تولیدی، ایجاد کنیم:
namespace OpenAPISwaggerDoc.Web { public class Startup { public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // ... app.UseHttpsRedirection(); app.UseSwagger(); app.UseSwaggerUI(setupAction => { setupAction.SwaggerEndpoint( "/swagger/LibraryOpenAPISpecification/swagger.json", "Library API"); }); // ... }
پس از این تنظیم اگر آدرس https://localhost:5001/swagger/index.html را در مرورگر باز کنیم، چنین خروجی قابل مشاهده خواهد بود:
و اگر بر روی هر کدام کلیک کنیم، ریز جزئیات آنها بر اساس OpenAPI Specification ای که بررسی کردیم، تولید شدهاست (از پارامترها تا نوع خروجی):
اکنون اگر بر روی دکمهی try it out آن نیز کلیک کنید، در همینجا میتوان این API را آزمایش کرد. برای مثال Controls Accept header را بر روی application/json قرار داده و سپس بر روی دکمهی execute که پس از کلیک بر روی دکمهی try it out ظاهر شدهاست، کلیک کنید تا بتوان خروجی Web API را مشاهده کرد.
در انتهای این صفحه، در قسمت schemas آن، مشخصات مدلهای بازگشت داده شدهی توسط Web API نیز ذکر شدهاند:
یک نکته: تغییر آدرس https://localhost:5001/swagger/index.html به ریشهی سایت
اگر علاقمند باشید تا زمانیکه برای اولین بار آدرس ریشهی سایت را در مسیر https://localhost:5001 باز میکنید، Swagger UI نمایان شود، میتوانید تنظیم RoutePrefix زیر را اضافه کنید:
app.UseSwaggerUI(setupAction => { setupAction.SwaggerEndpoint( "/swagger/LibraryOpenAPISpecification/swagger.json", "Library API"); setupAction.RoutePrefix = ""; });
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: OpenAPISwaggerDoc-02.zip
در قسمت بعد، به بهبود و غنی سازی جزئیات OpenAPI Specification تولیدی خواهیم پرداخت.
اگر با زبان C و مشتقات آن آشنایی داشته باشید، حتما با عملگرهای ترکیبی آنها که جهت خلاصه نویسی بکار میروند، نیز کار کردهاید. برای مثال:
int i =5;
i += 15; // i = i + 15;
اس کیوال سرور 2008 نیز از اینگونه عملگرها پشتیبانی به عمل میآورد. برای نمونه:
DECLARE @x1 int = 27;
SET @x1 += 2 ;
SELECT @x1 AS Added_2;
الف) امکان تعریف و مقدار دهی همزمان یک متغیر (مقدار دهی همزمان با تعریف، تا قبل از اس کیوال سرور 2008 پشتیبانی نمیشد)
ب) امکان استفاده از عملگرهای C مانند در عبارات T-SQL
لیست این عملگرهای جدید به شرح زیر است:
+= (Add EQUALS) (Transact-SQL)
-= (Subtract EQUALS) (Transact-SQL)
*= (Multiply EQUALS) (Transact-SQL)
/= (Divide EQUALS) (Transact-SQL)
%= (Modulo EQUALS) (Transact-SQL)
&= (Bitwise AND EQUALS) (Transact-SQL)
^= (Bitwise Exclusive OR EQUALS) (Transact-SQL)
|= (Bitwise OR EQUALS) (Transact-SQL)
به روز رسانی: ارتقاء به نگارش «2.0.0rc.0 »
برای ارتقاء به نگارش RC0، این مراحل را باید طی کنید:
1) پیش از هر کاری، پوشهی node_modules قدیمی خود را حذف کنید (با تمام محتوای آن).
2) به روز رسانی فایل package.json به صورت ذیل:
به روز شدهی محتوای فوق، همیشه در آدرس مستندات npm packages موجود است.
3) افزودن فایلی به نام typings.json در ریشهی پروژه؛ با این محتوا:
این فایل توسط قسمت «postinstall» اسکریپت package.json نصب میشود. اما چون مسیر https://raw.githubusercontent.com قابل دسترسی نیست (از این طرف البته!)، موفق به دریافت آن نخواهید شد. بنابراین یک پوشه را به نام typings به ریشهی سایت اضافه کنید و سپس فایل ذیل را به آن اضافه نمائید:
es6-shim.d.ts
بدون این فایل، کامپایلر TypeScript تعاریف ES 6 را مانند Map و Promise و امثال آن، نمیشناسد و پروژه را کامپایل نخواهد کرد.
اکنون یکبار فایل package.json را ذخیره کنید تا کار به روز رسانی بستهها انجام شود. البته اگر بر روی این فایل کلیک راست کنید، در منوی ظاهر شده، گزینهی restore packages هم موجود است.
4) پس از آن، چند تغییر جزئی ذیل باید در کدهای این سری، اعمال شوند:
هر جایی angular2 تعریف شده، اینبار میشود angular@. مثلا:
فایل مسیریابی آن قرار است تغییرات کلی داشته باشد. این مورد به صورت ذیل تغییر نام یافته است:
5) فایل main.ts (قسمت دوم) به صورت ذیل تغییر کردهاست:
6) تعاریف اسکریپتهای Index.html سایت، اینبار به نحو ذیل تغییر کردهاند:
یک نکته: اگر میخواهید این تعاریف را در یک فایل razor، وارد کنید، چون @ به ابتدای پوشهی angular2 اضافه شده (node_modules\@angular)، مشکل پردازشی razor را ایجاد خواهد کرد و باید escape شود. به همین جهت بجای @ بهتر است معادل آن را یعنی ("@")Html.Raw@ وارد کنید.
سپس ابتدا فایل systemjs.config.js را از اینجا دریافت کنید.
در ادامه مداخل جدید را هم در فایل index.html مثال رسمی آغازین آن بررسی کنید.
بنابراین، فایل systemjs.config.js را به ریشهی سایت اضافه کنید (از این جهت که مسیر بستههای node_modules را از ریشهی سایت میخواند). سپس فایل Views\Shared\_Layout.cshtml را به نحو ذیل تغییر دهید:
خلاصهی سریع این موارد
الف) تغییرات آخرین بستههای npm را از مستندات آن پیگیری و اعمال کنید. آخرین نگارش آن همیشه در اینجا قابل دسترسی است.
ب) تغییرات index.html، فایل main.ts و مداخل آغازین آنرا از مثال آغازین رسمی آن پیگیری و اعمال کنید.
برای ارتقاء به نگارش RC0، این مراحل را باید طی کنید:
1) پیش از هر کاری، پوشهی node_modules قدیمی خود را حذف کنید (با تمام محتوای آن).
2) به روز رسانی فایل package.json به صورت ذیل:
{ "name": "asp-net-mvc5x-angular2x", "version": "1.0.0", "author": "DNT", "description": "", "scripts": { "postinstall": "typings install" }, "license": "Apache-2.0", "dependencies": { "@angular/common": "^2.0.0-rc.0", "@angular/compiler": "^2.0.0-rc.0", "@angular/core": "^2.0.0-rc.0", "@angular/http": "2.0.0-rc.0", "@angular/router": "2.0.0-rc.0", "@angular/router-deprecated": "^2.0.0-rc.0", "@angular/platform-browser": "^2.0.0-rc.0", "@angular/platform-browser-dynamic": "^2.0.0-rc.0", "bootstrap": "^3.3.6", "es6-promise": "^3.1.2", "es6-shim": "^0.35.0", "jquery": "^2.2.3", "reflect-metadata": "^0.1.3", "rxjs": "^5.0.0-beta.6", "systemjs": "^0.19.27", "zone.js": "^0.6.12" }, "devDependencies": { "typescript": "^1.8.9", "typings": "^0.8.1" }, "repository": { } }
3) افزودن فایلی به نام typings.json در ریشهی پروژه؛ با این محتوا:
{ "ambientDependencies": { "es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#7de6c3dd94feaeb21f20054b9f30d5dabc5efabd" } }
es6-shim.d.ts
بدون این فایل، کامپایلر TypeScript تعاریف ES 6 را مانند Map و Promise و امثال آن، نمیشناسد و پروژه را کامپایل نخواهد کرد.
اکنون یکبار فایل package.json را ذخیره کنید تا کار به روز رسانی بستهها انجام شود. البته اگر بر روی این فایل کلیک راست کنید، در منوی ظاهر شده، گزینهی restore packages هم موجود است.
4) پس از آن، چند تغییر جزئی ذیل باید در کدهای این سری، اعمال شوند:
هر جایی angular2 تعریف شده، اینبار میشود angular@. مثلا:
import { PipeTransform, Pipe } from '@angular/core';
import { RouteParams, Router } from '@angular/router-deprecated';
/// <reference path="../typings/es6-shim.d.ts" /> import { bootstrap } from '@angular/platform-browser-dynamic'; // Our main component import { AppComponent } from "./app.component"; bootstrap(AppComponent);
یک نکته: اگر میخواهید این تعاریف را در یک فایل razor، وارد کنید، چون @ به ابتدای پوشهی angular2 اضافه شده (node_modules\@angular)، مشکل پردازشی razor را ایجاد خواهد کرد و باید escape شود. به همین جهت بجای @ بهتر است معادل آن را یعنی ("@")Html.Raw@ وارد کنید.
سپس ابتدا فایل systemjs.config.js را از اینجا دریافت کنید.
در ادامه مداخل جدید را هم در فایل index.html مثال رسمی آغازین آن بررسی کنید.
بنابراین، فایل systemjs.config.js را به ریشهی سایت اضافه کنید (از این جهت که مسیر بستههای node_modules را از ریشهی سایت میخواند). سپس فایل Views\Shared\_Layout.cshtml را به نحو ذیل تغییر دهید:
<!DOCTYPE html> <html> <head> <base href="/"> <meta charset="utf-8"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - My ASP.NET Application</title> <link href="~/node_modules/bootstrap/dist/css/bootstrap.css" rel="stylesheet"/> <link href="~/app/app.component.css" rel="stylesheet"/> <link href="~/Content/Site.css" rel="stylesheet" type="text/css"/> <!-- 1. Load libraries --> <!-- IE required polyfills, in this exact order --> <script src="~/node_modules/es6-shim/es6-shim.min.js"></script> <script src="~/node_modules/zone.js/dist/zone.js"></script> <script src="~/node_modules/reflect-metadata/Reflect.js"></script> <script src="~/node_modules/systemjs/dist/system.src.js"></script> <script src="~/systemjs.config.js"></script> <!-- 2. Configure SystemJS --> <script> System.import('app/main').then(null, console.error.bind(console)); </script> </head> <body> <div> @RenderBody() <pm-app>Loading App...</pm-app> </div> @RenderSection("Scripts", required: false) </body> </html>
خلاصهی سریع این موارد
الف) تغییرات آخرین بستههای npm را از مستندات آن پیگیری و اعمال کنید. آخرین نگارش آن همیشه در اینجا قابل دسترسی است.
ب) تغییرات index.html، فایل main.ts و مداخل آغازین آنرا از مثال آغازین رسمی آن پیگیری و اعمال کنید.