إشعار مهم إذا كنت ترقية بين الإصدارات الرئيسية! |
---|
* إذا كنت تقوم بالترقية من 4.x إلى 5.x ، فهناك العديد من التغييرات في الانهيار لتكون على دراية بها. انظر ملاحظات الإصدار للحصول على التفاصيل * إذا كنت تقوم بالقفز من 3.x إلى 4.x أولاً ، يكون هناك تنينات هناك أيضًا. انظر ملاحظات الإصدار هذه هنا |
أدوات Swagger لواجهة برمجة التطبيقات التي تم إنشاؤها باستخدام ASP.NET Core. قم بإنشاء وثائق API الجميلة ، بما في ذلك واجهة المستخدم لاستكشاف عمليات واختبارها ، مباشرة من طرقك ووحدات التحكم والموديلات.
بالإضافة إلى Swagger 2.0 ومولد OpenAPI 3.0 ، يوفر Swashbuckle أيضًا نسخة مضمنة من Swagger-Ui الرائعة التي يتم تشغيلها بواسطة Swagger Json. هذا يعني أنه يمكنك استكمال واجهة برمجة التطبيقات الخاصة بك مع وثائق المعيشة التي تتزامن دائمًا مع أحدث التعليمات البرمجية. والأفضل من ذلك كله ، أنه يتطلب الحد الأدنى من الترميز والصيانة ، مما يتيح لك التركيز على بناء واجهة برمجة تطبيقات رائعة.
وهذا ليس كل شيء ...
بمجرد حصولك على واجهة برمجة تطبيقات يمكن أن تصف نفسها في Swagger ، فقد فتحت صندوق الكنز للأدوات القائمة على Swagger بما في ذلك مولد العميل الذي يمكن استهدافه لمجموعة واسعة من المنصات الشائعة. انظر Swagger-Codegen لمزيد من التفاصيل.
نسخة swashbuckle | ASP.NET CORE | Swagger / Openapi Spec. | Swagger-Ui | redoc ui |
---|---|---|---|---|
CI | > = 2.0.0 | 2.0 ، 3.0 | 5.xx | 2.xx |
6.9.0 | > = 2.0.0 | 2.0 ، 3.0 | 5.17.14 | 2.1.5 |
5.6.3 | > = 2.0.0 | 2.0 ، 3.0 | 3.32.5 | 2.0.0-RC.40 |
4.0.0 | > = 2.0.0 ، <3.0.0 | 2.0 | 3.19.5 | 1.22.2 |
3.0.0 | > = 1.0.4 ، <3.0.0 | 2.0 | 3.17.1 | 1.20.0 |
2.5.0 | > = 1.0.4 ، <3.0.0 | 2.0 | 3.16.0 | 1.20.0 |
قم بتثبيت حزمة Nuget القياسية في تطبيق ASP.NET Core الخاص بك.
Package Manager : Install-Package Swashbuckle.AspNetCore CLI : dotnet add package Swashbuckle.AspNetCore
في طريقة ConfigureServices
الخاصة بـ Startup.cs
، قم بتسجيل مولد Swagger ، وتحديد مستندات Swagger واحدة أو أكثر.
باستخدام microsoft.openapi.models ؛
services.addmvc () ؛ services.addswaggergen (c => {c.swaggerDoc ("v1" ، new OpenAPiinfo {title = "my api" ، version = "v1"}) ؛}) ؛
تأكد من تزيين إجراءات API ومعلماتها بـ "HTTP" و "من" الارتباطات الصريحة.
[httppost] باطل باطل باطل ([من frombody] منتج المنتج) ...
[httpget] public ienumerable <Product> SearchProducts ([FromQuery] سلسلة الكلمات الرئيسية) ...
ملاحظة: إذا حذفت روابط المعلمة الصريحة ، فسوف يصفها المولد بأنها "استعلام" بشكل افتراضي.
في طريقة Configure
، يجب عليك فضح التباهي الذي تم إنشاؤه كنقطة نهاية (نقاط) JSON بواحدة من الطريقة التالية:
App.MapendPoints (endpoints => {// ... endpoints.mapswagger () ؛}) ؛
app.useswagger () ؛
في هذه المرحلة ، يمكنك تدوير تطبيقك وعرض Swagger الذي تم إنشاؤه في "/swagger/v1/swagger.json."
أدخل الوسيطة
أضف نقاط النهاية إذا كنت تستخدم التوجيه المستند إلى نقطة النهاية.
اختياريا ، أدخل البرامج الوسيطة Swagger-UI إذا كنت ترغب في فضح وثائق تفاعلية ، مع تحديد نقطة (نقاط) Swagger JSON لتشغيلها من.
app.useswaggerui (c => {c.swaggerendPoint ("v1/swagger.json" ، "my api v1") ؛}) ؛
يمكنك الآن إعادة تشغيل التطبيق الخاص بك والتحقق من المستندات التفاعلية التي تم إنشاؤها تلقائيًا على "/swagger".
في الإصدارات قبل 5.0.0
، ستقوم Swashbuckle بإنشاء مخطط (أوصاف لأنواع البيانات المكشوفة بواسطة API) استنادًا إلى سلوك Newtonsoft Serializer. هذا أمر منطقي لأن ذلك كان المسلسل الذي تم شحنه مع ASP.NET Core في ذلك الوقت. ومع ذلك ، نظرًا لأن الإصدار 3.0.0
، يقدم ASP.NET Core نظامًا مسلسلًا جديدًا الاشتراك. من Swashbuckle 5.0.0
وما وراء نمط مماثل يتم استخدامه. وهذا يعني أن Swashbuckle خارج الصندوق سوف تفترض أنك تستخدم STJ Serializer وتولد المخطط بناءً على سلوكه. إذا كنت تستخدم Newtonsoft ، فستحتاج إلى تثبيت حزمة Swashbuckle منفصلة واشتراك بشكل صريح. هذه خطوة مطلوبة ، بغض النظر عن إصدار ASP.NET Core الذي تستخدمه .
في ملخص ...
إذا كنت تستخدم System.text.json (STJ) ، فسيكون الإعداد الموضح أعلاه كافيًا ، وسيتم تكريم خيارات/سمات STJ تلقائيًا بواسطة مولد Swagger.
إذا كنت تستخدم Newtonsoft ، فستحتاج إلى تثبيت حزمة منفصلة واشتراكها بشكل صريح للتأكد من تكريم إعدادات/سمات Newtonsoft تلقائيًا بواسطة مولد Swagger:
Package Manager : Install-Package Swashbuckle.AspNetCore.Newtonsoft CLI : dotnet add package Swashbuckle.AspNetCore.Newtonsoft
services.addmvc () ؛ services.addswaggerGen (c => {c.swaggerDoc ("v1" ، new OpenAPiinfo {title = "my api" ، version = "v1"}) ؛}) ؛ services.addswaggergenwtonsoftsupport () ؛ // Orcless Opt -in - يجب وضعه بعد AddSwaggerGen ()
تعتمد Swashbuckle اعتمادًا كبيرًا على ApiExplorer
، طبقة بيانات الوصفية API التي تشحن مع ASP.NET Core. إذا كنت تستخدم مساعد AddMvc
للاضطلاع بمكدس MVC ، فسيتم تسجيل apiexplorer تلقائيًا وسيعمل SB بدون مشكلة. ومع ذلك ، إذا كنت تستخدم AddMvcCore
للحصول على مكدس MVC أكثر مقترنة ، فستحتاج إلى إضافة خدمة Apiexplorer بشكل صريح:
services.addmvccore (). addapiexplorer () ؛
بالإضافة إلى ذلك ، إذا كنت تستخدم التوجيه التقليدي (على عكس توجيه السمات) ، فلن يتم تمثيل أي وحدات تحكم وإجراءات على تلك وحدات التحكم التي تستخدم التوجيه التقليدي في apiexplorer ، مما يعني أن swashbuckle لن تتمكن العمليات منهم. على سبيل المثال:
app.usemvc (Roates => {// swaggergen لن تجد وحدات تحكم يتم توجيهها عبر هذه التقنية. routes.maproute ("افتراضي" ، "{controller = home}/{action = index}/{id؟}") ؛}) ؛
يجب عليك استخدام توجيه السمات لأي وحدات تحكم تريد تمثيلها في مستندات (مواقع) Swagger الخاصة بك:
[Route ("example)] examplecontroller الفئة العامة: وحدة التحكم {[httpget (" ")] public iActionResult dostuff () { / ** /}}
ارجع إلى وثائق التوجيه لمزيد من المعلومات.
يتكون Swashbuckle من مكونات متعددة يمكن استخدامها معًا أو بشكل فردي اعتمادًا على احتياجاتك. في جوهرها ، يوجد مولد Swagger ، ووسائط لفضحه كنقاط نهاية JSON ، ونسخة معبأة من Swagger-Ui. يمكن تثبيت هذه الحزم الثلاث باستخدام Swashbuckle.AspNetCore
"metapackage" وستعمل معًا بسلاسة (انظر البدء) لتوفير مستندات API الجميلة التي يتم إنشاؤها تلقائيًا من الكود الخاص بك.
بالإضافة إلى ذلك ، هناك حزم الوظيفة الإضافية (أدوات CLI ، واجهة مستخدم بديلة ، وما إلى ذلك) يمكنك تثبيتها وتكوينها اختياريًا حسب الحاجة.
طَرد | وصف |
---|---|
swashbuckle.aspnetcore.swagger | يعرض اخبال نقاط نهاية json. وتتوقع أن يتم تسجيل ISwaggerProvider في حاوية DI ، والتي يستفسر عن استرداد أو OpenAPIDocument(s) |
swashbuckle.aspnetcore.swaggergen | حقن تنفيذ ISwaggerProvider الذي يمكن استخدامه من قبل المكون أعلاه. ينشئ هذا التنفيذ بالذات OpenApiDocument(s) من طرقك ووحدات التحكم والموديلات |
swashbuckle.aspnetcore.swaggerui | يعرض نسخة مضمنة من Swagger-Ui. يمكنك تحديد نقاط نهاية API حيث يمكنها الحصول على Swagger JSON ، وتستخدمها لتشغيل مستندات تفاعلية لواجهة برمجة التطبيقات الخاصة بك |
طَرد | وصف |
---|---|
swashbuckle.aspnetcore.annotations | يتضمن مجموعة من السمات المخصصة التي يمكن تطبيقها على وحدات التحكم والإجراءات والنماذج لإثراء التباهي الذي تم إنشاؤه |
swashbuckle.aspnetcore.cli | يوفر واجهة سطر الأوامر لاسترداد Swagger مباشرة من مجموعة بدء التشغيل ، والكتابة إلى ملف |
swashbuckle.aspnetcore.redoc | يعرض نسخة مضمنة من واجهة المستخدم Redoc (بديل لـ Swagger-Ui) |
يتم توفير هذه الحزم من قبل المجتمع مفتوح المصدر.
طَرد | وصف |
---|---|
swashbuckle.aspnetcore.filters | بعض مرشحات Swashbuckle المفيدة التي تضيف وثائق إضافية ، مثل الطلب والاستجابة ، ومعلومات التفويض ، وما إلى ذلك ، راجع ReadMe لمزيد من التفاصيل |
unchase.swashbuckle.aspnetcore.Extensions | بعض الامتدادات المفيدة (المرشحات) ، والتي تضيف وثائق إضافية ، على سبيل المثال إخفاء الأدوار للأدوار غير المقبولة ، وإصلاح التعدادات لتوليد رمز العميل ، وما إلى ذلك ، راجع ReadMe لمزيد من التفاصيل |
microelements.swashbuckle.fluentvalidation | استخدم قواعد الفلنتيكية بدلاً من سمات العوامل المكونة لزيادة مخططات Swagger التي تم إنشاؤها |
mmlib.swaggerforocelot | مجمعة الوثائق على الخدمات الدقيقة مباشرة على بوابة Ocelot API |
ستجعلك الخطوات الموضحة أعلاه تعمل مع الحد الأدنى من الإعداد. ومع ذلك ، يوفر Swashbuckle الكثير من المرونة للتخصيص كما تراه مناسبًا. تحقق من الجدول أدناه للحصول على القائمة الكاملة للخيارات:
swashbuckle.aspnetcore.swagger
قم بتغيير مسار نقاط نهاية Swagger Json
تعديل Swagger مع سياق الطلب
Serialize Swagger JSON بتنسيق 2.0
العمل مع الدلائل الافتراضية والوكلاء العكسيين
تخصيص كيفية تسلسل مستند OpenAPI
swashbuckle.aspnetcore.swaggergen
تعيين العمليات الصريحة
قائمة ردود العمليات
العلم المطلوبة معلمات وخصائص المخطط
التعامل مع النماذج وتحميل الملفات
التعامل مع تنزيلات الملف
قم بتضمين أوصاف من تعليقات XML
توفير بيانات تعريف واجهة برمجة التطبيقات العالمية
توليد مستندات مبالغ متعددة
حذف العمليات القديمة و/أو خصائص المخطط
حذف العمليات التعسفية
تخصيص علامات التشغيل (على سبيل المثال لتجميع واجهة المستخدم)
تغيير ترتيب فرز التشغيل (على سبيل المثال لفرز واجهة المستخدم)
تخصيص معرف المخطط
تجاوز المخطط لأنواع محددة
تمديد المولد مع مرشحات التشغيل والمخطط والوثائق
إضافة تعريفات ومتطلبات الأمان
إضافة تعريفات ومتطلبات الأمان لمصادقة حامل
الميراث وتعدد الأشكال
swashbuckle.aspnetcore.swaggerui
تغيير المسار النسبي إلى واجهة المستخدم
تغيير عنوان المستند
تغيير مسارات CSS أو JS
سرد مستندات Swagger متعددة
تطبيق معلمات Swagger-UI
حقن JavaScript المخصص
حقن CSS المخصصة
تخصيص index.html
تمكين التدفقات OAuth2.0
استخدم طلب طلب من جانب العميل ومعترضات الاستجابة
swashbuckle.aspnetcore.annotations
تثبيت وتمكين التعليقات التوضيحية
إثراء البيانات الوصفية
إثراء البيانات الوصفية للاستجابة
إثراء بيانات التعريف
إثراء البيانات الوصفية للطلب
إثراء البيانات الوصفية
تطبيق مرشحات المخطط على أنواع محددة
أضف بيانات التعريف
swashbuckle.aspnetcore.cli
استرداد Swagger مباشرة من مجموعة بدء التشغيل
استخدم أداة CLI مع تكوين مضيف مخصص
swashbuckle.aspnetcore.redoc
تغيير المسار النسبي إلى واجهة المستخدم
تغيير عنوان المستند
تطبيق المعلمات redoc
حقن CSS المخصصة
تخصيص index.html
افتراضيًا ، سيتم كشف Swagger JSON في المسار التالي - "/swagger/ {documentname )/swagger.json". إذا لزم الأمر ، يمكنك تغيير هذا عند تمكين البرامج الوسيطة Swagger. يجب أن تتضمن الطرق المخصصة المعلمة {documentName}
.
app.useswagger (c => {c.RoutEmplate = "API-docs/{documentName} /swagger.json" ؛})
ملاحظة: إذا كنت تستخدم البرامج الوسيطة Swaggerui ، فستحتاج أيضًا إلى تحديث تكوينه لتعكس نقاط النهاية الجديدة:
app.useswaggerui (c => {c.swaggerendPoint ("/api-docs/v1/swagger.json" ، "my api v1") ؛})
ملاحظة: إذا كنت بحاجة أيضًا إلى تحديث المسار النسبي الذي يتوفره واجهة المستخدم نفسها ، فستحتاج إلى اتباع الإرشادات الموجودة في تغيير المسار النسبي إلى واجهة المستخدم.
إذا كنت بحاجة إلى تعيين بعض البيانات الوصفية Swagger بناءً على الطلب الحالي ، فيمكنك تكوين مرشح تم تنفيذه قبل تسلسل المستند.
app.useswagger (c => {c.preserializeFilters.add ((swagger ، httpreq) => {swagger.servers = new list <Poxapiserver> {new OpenAppiser {url = $ "{httpreq.scheme}: // {httpreq. Host.value} "}} ؛}) ؛}) ؛
يتم نقل كلاهما OpenApiDocument
و HttpRequest
الحالي إلى المرشح. هذا يوفر الكثير من المرونة. على سبيل المثال ، يمكنك إضافة خادم API صريح استنادًا إلى رأس "المضيف" (كما هو موضح) ، أو يمكنك فحص معلومات الجلسة أو رأس إذن وإزالة العمليات من المستند بناءً على أذونات المستخدم.
بشكل افتراضي ، ستقوم Swashbuckle بإنشاء وفضح Swagger JSON في الإصدار 3.0 من المواصفات ، والتي تسمى رسميًا مواصفات OpenAPI. ومع ذلك ، لدعم التوافق المتخلف ، يمكنك اختيار متابعة تعريضه بتنسيق 2.0 مع الخيار التالي:
app.useswagger (c => {c.SerializeAsv2 = true ؛}) ؛
يمكن أن تسبب الدلائل الافتراضية والوكلاء العكسيين مشكلات للتطبيقات التي تولد روابط وإعادة التوجيه ، خاصة إذا كان التطبيق يرجع عناوين URL المطلقة بناءً على رأس Host
والمعلومات الأخرى من الطلب الحالي. لتجنب هذه المشكلات ، يستخدم Swashbuckle عناوين URL النسبية حيثما أمكن ، ويشجع استخدامها عند تكوين الوسيطة Swaggerui و Redoc.
على سبيل المثال ، لتوصيل البرامج الوسيطة Swaggerui ، يمكنك توفير عنوان URL لوثائق OpenAPI/Swagger واحدة أو أكثر. هذا هو عنوان URL الذي سيتصل به Swagger-Ui ، وهو تطبيق من جانب العميل ، لاسترداد بيانات تعريف API الخاصة بك. لضمان هذا العمل وراء الدلائل الافتراضية والوكلاء العكسيين ، يجب أن تعبر عن هذا بالنسبة إلى RoutePrefix
من Swagger-Ui نفسه:
app.useswaggerui (c => {c.routeprefix = "swagger" ؛
ملاحظة: في الإصدارات السابقة من المستندات ، ربما تكون قد رأيت هذا معبرًا عن رابط ترشيح للجذر (على سبيل المثال /swagger/v1/swagger.json
). لن يعمل هذا إذا تم استضافة تطبيقك على دليل افتراضي IIS أو خلف وكيل يزيل مسار الطلب قبل إعادة التوجيه. إذا قمت بالتبديل إلى بناء الجملة المرتبط بالصفحة الموضح أعلاه ، فيجب أن يعمل في جميع الحالات.
افتراضيًا ، سيقوم Swashbuckle بتسلسل مستند OpenAPI باستخدام طرق التسلسل على كائن مستند OpenAPI. إذا كان التسلسل المخصص مطلوبًا ، فمن الممكن إنشاء جهاز تسلسل مستند مخصص يقوم بتنفيذ واجهة ISwaggerDocumentSerializer
. يمكن ضبط ذلك على SwaggerOptions
في مجموعة الخدمة باستخدام ConfigureSwagger()
:
ملحوظة
إذا كنت تخطط لاستخدام أداة سطر الأوامر لإنشاء ملفات مواصفات OpenAPI ، فيجب أن يتم ذلك على مجموعة الخدمة باستخدام ConfigureSwagger()
.
Services.ConfiguresWagger (خيارات => {Option.setCustomDocumentSerializer <CumentDocumentSerializer> () ؛})
عند عدم استخدام أداة سطر الأوامر ، يمكن أيضًا القيام بها على مضيف التطبيق:
app.UsesWagger (Options => {Options.setCustomDocumentSerializer <CumentDocumentSerializer> () ؛})
في Swagger ، يمكن تعيين العمليات operationId
. يجب أن يكون هذا المعرف فريدًا بين جميع العمليات الموضحة في API. قد تستخدم الأدوات والمكتبات (على سبيل المثال مولدات العميل) عملية التشغيل لتحديد العملية بشكل فريد ، لذلك ، يوصى باتباع اتفاقيات التسمية الشائعة للبرمجة.
إن توليد معرف تلقائيًا يطابق هذه المتطلبات ، مع توفير اسم سيكون ذا معنى في مكتبات العملاء هو مهمة غير تافهة ، وهكذا ، فإن swashbuckle يغفل operationId
بشكل افتراضي. ومع ذلك ، إذا لزم الأمر ، يمكنك تعيين operationIds
عن طريق تزيين الطرق الفردية أو عن طريق توفير استراتيجية مخصصة.
الخيار 1) تزيين الطرق باستخدام خاصية Name
[httpget ("{id}" ، name = "getProductById")] public iActionResult get (int id) // OperationId = "getProductByid"
الخيار 2) توفير استراتيجية مخصصة
// startup.csservices.addswaggergen (c => {... // استخدم اسم الطريقة كعملية c.customOperationIDs (apidesc => {return apidesc.trygetMethodinfo (Out methodInfo methodInfo)؟ methodInfo.name: null ؛}) ؛}) ؛ ) // productscontroller.cs [httpget ("{id}")] public iActionResult GetProductById (int id) // OperationId = "getProductByid"
ملاحظة: مع أي من النهجين ، يكون مؤلفو واجهة برمجة التطبيقات مسؤولة عن ضمان تفرد operationIds
في جميع العمليات
بشكل افتراضي ، سوف يولد Swashbuckle استجابة "200" لكل عملية. إذا أعاد الإجراء استجابة DTO ، فسيتم استخدام ذلك لإنشاء مخطط لجسم الاستجابة. على سبيل المثال ...
[httppost ("{{id}")] المنتج العام getByid (int id)
سوف تنتج بيانات تعريف الاستجابة التالية:
responses: { 200: { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/Product" } } } } }
إذا كنت بحاجة إلى تحديد رمز حالة مختلف و/أو ردود إضافية ، أو تُرجع أفعالك IActionResult
بدلاً من استجابة DTO ، فيمكنك وصف الاستجابات بشكل صريح باستخدام ProducesResponseTypeAttribute
الذي يشحن مع ASP.NET Core. على سبيل المثال ...
[httppost ("{id}")]
سوف تنتج بيانات تعريف الاستجابة التالية:
responses: { 200: { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/Product" } } } }, 400: { description: "Bad Request", content: { "application/json": { schema: { type: "object", additionalProperties: { type: "string" } } } } }, 500: { description: "Internal Server Error", content: {} } }
في مستند Swagger ، يمكنك الإبلاغ عن معلمات وخصائص المخطط المطلوبة لطلب. إذا تم تزيين معلمة (المستوى الأعلى أو المستندة إلى العقار) باستخدام BindRequiredAttribute
أو RequiredAttribute
، فإن Swashbuckle سوف يعلقها تلقائيًا كمعلمة "مطلوبة" في Swagger المولدة:
// productscontroller.cspublic iActionResult Search ([FromQuery ، BindRequired] كلمات رئيسية ، [FromQuery] pagingparams pagingparams) {if (! modelState.isvalid) ] Public Int Pageno {get ؛ تعيين؛ } pagesize {get ؛ تعيين؛ }}
بالإضافة إلى المعلمات ، سوف يكرم Swashbuckle أيضًا RequiredAttribute
عند استخدامه في نموذج مرتبط بجسم الطلب. في هذه الحالة ، سيتم وضع علامة على الخصائص المزينة كخصائص "مطلوبة" في وصف الجسم:
// productscontroller.cspublic iActionResult Create ([Frombody] Product) {if (! modelState.isvalid) إرجاع BadRequest (ModelState) ؛ ...} // product.cspublic class product {[مطلوب] اسم السلسلة العامة {get ؛ تعيين؛ } وصف السلسلة العامة {get ؛ تعيين؛ }}
ستقبل وحدة التحكم هذه قيمتين حقل النموذجين وتحميل ملف مسمى من نفس النموذج:
[httppost] public void uploadfile ([fromform] وصف السلسلة ، [fromform] dateTime ClientDate ، ملف iformfile)
ملاحظة مهمة: وفقًا لمستندات ASP.NET الأساسية ، ليس من المفترض أن تزين معلمات
IFormFile
مع سمة[FromForm]
حيث يتم استنتاج مصدر الربط تلقائيًا من النوع. في الواقع ، فإن القيمة المستنتجة هيBindingSource.FormFile
، وإذا قمت بتطبيق السمة ، فسيتم تعيينه علىBindingSource.Form
بدلاً من ذلك ، والذي يربطApiExplorer
، مكون البيانات الوصفية التي تشحن مع ASP.NET Core ويعتمد عليها بشدة بواسطة swashbuckle. إحدى المشكلات المحددة هنا هي أن Swaggerui لن يتعامل مع المعلمة كملف وبالتالي لن يعرض زر تحميل الملف ، إذا قمت بتضمين هذه السمة عن طريق الخطأ.
لا يظهر ApiExplorer
(مكون بيانات FileResult
ASP.NET Core الذي تم بناء Swashbuckle) بشكل افتراضي ، وبالتالي تحتاج إلى إخباره بشكل صريح باستخدام سمة ProducesResponseType
(أو Produces
على .NET 5 أو أكبر):
[httpget ("{fileName}")] [producesponsetype (typeof (filestreamresult) ، statuscodes.status200ok ، "Image/JPEG")]
لتعزيز المستندات التي تم إنشاؤها مع الأوصاف الصديقة للإنسان ، يمكنك التعليق على إجراءات وحدات التحكم مع تعليقات XML وتكوين swashbuckle لدمج تلك التعليقات في Swagger JSON المخرج:
افتح مربع حوار Properties لمشروعك ، انقر فوق علامة التبويب "Build" وتأكد من فحص "ملف وثائق XML" ، أو إضافة <GenerateDocumentationFile>true</GenerateDocumentationFile>
عنصر إلى قسم <PropertyGroup>
من ملف مشروع .csproj الخاص بك. سيؤدي ذلك إلى إنتاج ملف يحتوي على جميع تعليقات XML في وقت البناء.
في هذه المرحلة ، ستؤدي أي فئات أو طرق غير مشروح بتعليقات XML إلى تحذير بناء. لقمع هذا ، أدخل رمز التحذير "1591" في حقل "القمع التحذيرات" في مربع الحوار أو إضافة <NoWarn>1591</NoWarn>
إلى قسم <PropertyGroup>
من ملف مشروع .csproj الخاص بك.
قم بتكوين SwashBuckle لدمج تعليقات XML في الملف في Swagger Json الذي تم إنشاؤه:
services.addswaggerGen (c => {c.swaggerDoc ("v1" ، new OpenAPiInfo {title = "my api - v1" ، version = "v1"}) ؛ c.includexmlcomments (typeof (myController) .assembly)) ؛}
قم بتعليق أفعالك بملخص وملاحظات وعلامات param والاستجابة:
/// <summary> /// استرداد منتج معين بواسطة معرف فريد /// </summary> /// <mromarks> الذهول! </remarks> /// <param name = "id" example = "123" > معرف المنتج </param> /// <استجابة رمز = "200"> تم استرداد المنتج </response> /// <استجابة رمز = "404" "500"> عفوا! لا يمكن البحث عن منتجك الآن </stripte> [httpget ("{id}")] بطاقة تعريف)
يمكنك أيضًا التعليق على أنواع الملخص والمثال: العلامات:
Public Class Product {/// <summary> /// اسم المنتج /// </summary> /// <eample> أحذية كرة السلة للرجال </example> اسم السلسلة العامة {get ؛ تعيين؛ } /// <summary> /// Quantity in stock /// </summary> /// <example> 10 </efulle> public int invieblestock {get ؛ تعيين؛ } /// <summary> /// الأحجام المتوفرة للمنتج في /// </summary> /// <eample> ["small" ، "medium" ، "large"] </example> قائمة عامة < سلسلة> أحجام {get ؛ تعيين؛ }}
أعد بناء مشروعك لتحديث ملف تعليقات XML وانتقل إلى نقطة نهاية Swagger JSON. لاحظ كيف يتم تعيين الأوصاف على حقول Swagger المقابلة.
ملاحظة: يمكنك أيضًا توفير أوصاف مخطط Swagger من خلال التعليق على نماذج API الخاصة بك وخصائصها بعلامات موجزة. إذا كان لديك العديد من ملفات تعليقات XML (مثل مكتبات منفصلة لوحدات التحكم والموديلات) ، فيمكنك استدعاء طريقة includexmlcomments عدة مرات وسيتم دمجها جميعًا في Swagger JSON المخرج.
بالإضافة إلى "Pathitems" و "العمليات" و "الردود" ، التي يولدها Swashbuckle لك ، يدعم Swagger أيضًا بيانات التعريف العالمية (انظر https://swagger.io/specification/#oasobject). على سبيل المثال ، يمكنك تقديم وصف كامل لاتصالات API أو شروط الخدمة أو حتى معلومات الاتصال والترخيص:
C.SwaggerDoc ("V1" ، Openapiinfo جديد ) //www.apache.org/licenses/license-2.0.html ")}}) ؛
نصيحة: استخدم Intellisense لمعرفة الحقول الأخرى المتاحة.
مع الإعداد الموضح أعلاه ، سيتضمن المولد جميع عمليات API في وثيقة Swagger واحدة. ومع ذلك ، يمكنك إنشاء مستندات متعددة إذا لزم الأمر. على سبيل المثال ، قد ترغب في مستند منفصل لكل إصدار من واجهة برمجة التطبيقات الخاصة بك. للقيام بذلك ، ابدأ بتحديد مستندات Swagger متعددة في Startup.cs
:
Services.addswaggerGen (C => {c.swaggerDoc ("V1" ، OpenApiinfo new {title = "my api - v1" ، version = "v1"}) ؛ API - V2 "، الإصدار =" V2 "}) ؛})
نلاحظ الحجة الأولى إلى SwaggerDoc. يجب أن يكون اسمًا صديقًا لليوري يحدد المستند بشكل فريد. يتم استخدامه لاحقًا لتعويض المسار لطلب Swagger JSON المقابل. على سبيل المثال ، مع التوجيه الافتراضي ، ستكون المستندات المذكورة أعلاه متاحة على "/swagger/v1/swagger.json" و "/swagger/v2/swagger.json".
بعد ذلك ، ستحتاج إلى إبلاغ Swashbuckle ما هي الإجراءات التي يجب تضمينها في كل وثيقة. على الرغم من أنه يمكن تخصيص ذلك (انظر أدناه) ، بشكل افتراضي ، سيستخدم المولد الخاصية ApiDescription.GroupName
، جزءًا من طبقة البيانات الوصفية المدمجة التي تشحن مع ASP.NET Core ، لإجراء هذا التمييز. يمكنك تعيين هذا عن طريق تزيين الإجراءات الفردية أو عن طريق تطبيق اتفاقية واسعة التطبيق.
لتضمين إجراء في مستند Swagger معين ، قم بتزيينه باستخدام ApiExplorerSettingsAttribute
وتعيين GroupName
على اسم المستند المقابل (حساس الحالة):
[httppost] [apiexplorersettings (groupName = "V2")]
للتجميع عن طريق الاتفاقية بدلاً من تزيين كل إجراء ، يمكنك تطبيق وحدة تحكم مخصصة أو اتفاقية عمل. على سبيل المثال ، يمكنك توصيل الاتفاقية التالية لتعيين إجراءات للمستندات بناءً على مساحة اسم وحدة التحكم.
. // eg "controllers.v1" var apiversion = controlnamespace.split ('.'). last (). services.addmvc (c => c.conventions.add (apiexplorergroupperversionconvention ())) ؛ ...}
عند اختيار إجراءات لوثيقة Swagger معينة ، يستدعي المولد DocInclusionPredicate
ضد كل ApiDescription
الذي ظهر بالإطار. يفحص التطبيق الافتراضي ApiDescription.GroupName
ويُرجع صحيحًا إذا كانت القيمة إما فارغة أو تساوي اسم المستند المطلوب. ومع ذلك ، يمكنك أيضًا توفير مسند إدراج مخصص. على سبيل المثال ، إذا كنت تستخدم نهجًا قائمًا على السمات لتنفيذ إصدار API (على سبيل المثال microsoft.aspnetcore.mvc.versioning) ، فيمكنك تكوين مسند أساسي يعزز سمات الإصدار بدلاً من ذلك:
c.docinclusionpredpredicate ((docname ، apidesc) => {if (! apidesc.trygetMethodinfo (Out MethodInfo methodInfo)) > attr.versions) ؛
إذا كنت تستخدم البرامج الوسيطة SwaggerUI
، فستحتاج إلى تحديد أي نقاط نهاية مبتكرة إضافية تريد فضحها. انظر قائمة مستندات Swagger متعددة للمزيد.
تتضمن مواصفات Swagger علامة deprecated
للإشارة إلى أن العملية قد تم إهمالها ويجب امتناعها عن الاستخدام. سيقوم مولد Swagger بتعيين هذه العلامة تلقائيًا إذا تم تزيين الإجراء المقابل باستخدام ObsoleteAttribute
. ومع ذلك ، بدلاً من إعداد علامة ، يمكنك تكوين المولد لتجاهل الإجراءات القديمة تمامًا:
services.addswaggerGen (c => {... c.ignoreobsoleteaations () ؛} ؛
يمكن أيضًا استخدام نهج مماثل لحذف الخصائص القديمة من المخططات في إخراج Swagger. بمعنى أنه يمكنك تزيين خصائص النموذج باستخدام ObsoleteAttribute
وتكوين swashbuckle لحذف هذه الخصائص عند إنشاء مخططات JSON:
Services.addswaggerGen (C => {...
يمكنك حذف العمليات من الإخراج Swagger عن طريق تزيين الإجراءات الفردية أو عن طريق تطبيق اتفاقية واسعة التطبيق.
لحذف إجراء معين ، تزيينه باستخدام ApiExplorerSettingsAttribute
وتعيين علامة IgnoreApi
:
[httpget ("{id}")]
لحذف الإجراءات حسب الاتفاقية بدلاً من تزيينها بشكل فردي ، يمكنك تطبيق اتفاقية عمل مخصصة. على سبيل المثال ، يمكنك توصيل الاتفاقية التالية إلى المستند فقط للحصول على العمليات:
. الخدمات) {services.addmvc (c => c.conventions.add (ApiexplorergetsonlyConvention ()) ؛ ...}
تتيح مواصفات Swagger تعيين "علامات" واحدًا أو أكثر لعملية ما. سيقوم مولد Swagger بتعيين اسم وحدة التحكم كعلامة افتراضية. من المهم ملاحظة ما إذا كنت تستخدم برامج SwaggerUI
الوسيطة لأنها تستخدم هذه القيمة لعمليات المجموعة.
يمكنك تجاوز العلامة الافتراضية من خلال توفير وظيفة تطبق العلامات حسب الاتفاقية. على سبيل المثال ، سوف يوضح التكوين التالي ، وبالتالي عمليات المجموعة في واجهة المستخدم ، بواسطة طريقة HTTP:
services.addswaggerGen (c => {... c.tagactionsby (api => api.httpmethod) ؛} ؛
بشكل افتراضي ، يتم طلب الإجراءات بواسطة علامة مخصصة (انظر أعلاه) قبل تجميعها في الهيكل المتداخل للمسار المتداخل للمواصفات Swagger. ولكن ، يمكنك تغيير الطلب الافتراضي للإجراءات باستخدام استراتيجية فرز مخصصة:
services.addswaggerGen (c => {... c.orderactionsby ((apidesc) => $ "{apidesc.ActionDescriptor.Routevalues [" Controller "]} _ {apidesc.httpmethod}") ؛} ؛
ملاحظة: هذا يملي ترتيب الفرز قبل تجميع الإجراءات وتحويلها إلى تنسيق Swagger. لذلك ، فإنه يؤثر على ترتيب المجموعات (أي Swagger "pathitems") ، وترتيب العمليات داخل مجموعة ، في إخراج Swagger.
إذا كان المولد يواجه معلمة أو أنواع استجابة معقدة ، فسيقوم بإنشاء مخطط JSON المقابل ، وإضافته إلى قاموس components/schemas
العالمية ، ويشير إليه من وصف العملية حسب المعرف الفريد. على سبيل المثال ، إذا كان لديك إجراء يرجع نوع Product
، فسيتم الرجوع إلى المخطط الذي تم إنشاؤه على النحو التالي:
responses: { 200: { description: "OK", content: { "application/json": { schema: { $ref: "#/components/schemas/Product" } } } } }
ومع ذلك ، إذا واجهت أنواعًا متعددة بنفس الاسم ولكن مساحات أسماء مختلفة (على سبيل المثال RequestModels.Product
& ResponseModels.Product
) ، فإن Swashbuckle سترفع استثناء بسبب "Schemaids المتضاربة". في هذه الحالة ، ستحتاج إلى توفير استراتيجية معرف مخصصة تؤهل الاسم بشكل أكبر:
services.addswaggerGen (c => {... c.customschemaids ((type) => type.fullname) ؛} ؛
انظر #2703 للحصول على دعم لأنواع متداخلة.
خارج الصندوق ، يقوم Swashbuckle بعمل لائق في إنشاء مخططات JSON التي تصف بدقة طلبك وضربات الاستجابة. ومع ذلك ، إذا كنت تقوم بتخصيص سلوك التسلسل لأنواع معينة في واجهة برمجة التطبيقات الخاصة بك ، فقد تحتاج إلى مساعدته.
على سبيل المثال ، قد يكون لديك فئة ذات خصائص متعددة تريد تمثيلها في JSON كسلسلة مفصولة فاصلة. للقيام بذلك ، من المحتمل أن تنفذ JsonConverter
مخصص. في هذه الحالة ، لا يعرف Swashbuckle كيف يتم تنفيذ المحول ، وبالتالي ستحتاج إلى تزويد مخططه بدقة: النوع:
// phonenumber.cspublic class phonenumber {public String CountryCode {get ؛ تعيين؛ } areaCode {get ؛ تعيين؛ } سلسلة عامة مشتركة {get ؛ تعيين؛ }} // startup.csservices.addswaggerGen (c => {...
يكشف Swashbuckle خط أنابيب مرشح يربط في عملية التوليد. بمجرد إنشائها ، يتم تمرير كائنات البيانات الوصفية الفردية إلى خط الأنابيب حيث يمكن تعديلها بشكل أكبر. يمكنك توصيل المرشحات المخصصة لإثراء "العمليات" التي تم إنشاؤها و "Schemas" و "Documents".
يسترجع Swashbuckle ApiDescription
، جزء من ASP.NET Core ، لكل إجراء ويستخدمه لإنشاء OpenApiOperation
المقابلة. Once generated, it passes the OpenApiOperation
and the ApiDescription
through the list of configured Operation Filters.
In a typical filter implementation, you would inspect the ApiDescription
for relevant information (eg route info, action attributes etc.) and then update the OpenApiOperation
accordingly. For example, the following filter lists an additional "401" response for all actions that are decorated with the AuthorizeAttribute
:
// AuthResponsesOperationFilter.cspublic class AuthResponsesOperationFilter : IOperationFilter{public void Apply(OpenApiOperation operation, OperationFilterContext context){var authAttributes = context.MethodInfo.DeclaringType.GetCustomAttributes(true).Union(context.MethodInfo.GetCustomAttributes(true)).OfType<AuthorizeAttribute>();if (authAttributes.Any())operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });}}// Startup.csservices.AddSwaggerGen(c =>{...c.OperationFilter<AuthResponsesOperationFilter>();};
NOTE: Filter pipelines are DI-aware. That is, you can create filters with constructor parameters and if the parameter types are registered with the DI framework, they'll be automatically injected when the filters are instantiated
Swashbuckle generates a Swagger-flavored JSONSchema for every parameter, response and property type that's exposed by your controller actions. Once generated, it passes the schema and type through the list of configured Schema Filters.
The example below adds an AutoRest vendor extension (see https://github.com/Azure/autorest/blob/master/docs/extensions/readme.md#x-ms-enum) to inform the AutoRest tool how enums should be modelled when it generates the API client.
// AutoRestSchemaFilter.cspublic class AutoRestSchemaFilter : ISchemaFilter{public void Apply(OpenApiSchema schema, SchemaFilterContext context){var type = context.Type;if (type.IsEnum){schema.Extensions.Add("x-ms-enum",new OpenApiObject{["name"] = new OpenApiString(type.Name),["modelAsString"] = new OpenApiBoolean(true)});};}}// Startup.csservices.AddSwaggerGen(c =>{...c.SchemaFilter<AutoRestSchemaFilter>();};
The example below allows for automatic schema generation of generic Dictionary<Enum, TValue>
objects. Note that this only generates the swagger; System.Text.Json
is not able to parse dictionary enums by default, so you will need a special JsonConverter, like in the .NET docs
// DictionaryTKeyEnumTValueSchemaFilter.cspublic class DictionaryTKeyEnumTValueSchemaFilter : ISchemaFilter{ public void Apply(OpenApiSchema schema, SchemaFilterContext context) {// Only run for fields that are a Dictionary<Enum, TValue>if (!context.Type.IsGenericType || !context.Type.GetGenericTypeDefinition().IsAssignableFrom(typeof(Dictionary<,>))){return;}var keyType = context.Type.GetGenericArguments()[0];var valueType = context.Type.GetGenericArguments()[1];if (!keyType.IsEnum){return;}schema.Type = "object";schema.Properties = keyType.GetEnumNames().ToDictionary(name => name,name => context.SchemaGenerator.GenerateSchema(valueType, context.SchemaRepository)); }}// Startup.csservices.AddSwaggerGen(c =>{...// These will be replaced by DictionaryTKeyEnumTValueSchemaFilter, but are needed to avoid an error.// You will need one for every kind of Dictionary<,> you have.c.MapType<Dictionary<MyEnum, List<string>>>(() => new OpenApiSchema());c.SchemaFilter<DictionaryTKeyEnumTValueSchemaFilter>();};
Once an OpenApiDocument
has been generated, it too can be passed through a set of pre-configured Document Filters. This gives full control to modify the document however you see fit. To ensure you're still returning valid Swagger JSON, you should have a read through the specification before using this filter type.
The example below provides a description for any tags that are assigned to operations in the document:
public class TagDescriptionsDocumentFilter : IDocumentFilter{public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context){swaggerDoc.Tags = new List<OpenApiTag> {new OpenApiTag { Name = "Products", Description = "Browse/manage the product catalog" },new OpenApiTag { Name = "Orders", Description = "Submit orders" }};}}
NOTE: If you're using the SwaggerUI
middleware, the TagDescriptionsDocumentFilter
demonstrated above could be used to display additional descriptions beside each group of Operations.
In Swagger, you can describe how your API is secured by defining one or more security schemes (eg basic, api key, oauth2 etc.) and declaring which of those schemes are applicable globally OR for specific operations. For more details, take a look at the Security Requirement Object in the Swagger spec..
In Swashbuckle, you can define schemes by invoking the AddSecurityDefinition
method, providing a name and an instance of OpenApiSecurityScheme
. For example you can define an OAuth 2.0 - implicit flow as follows:
// Startup.csservices.AddSwaggerGen(c =>{ ... // Define the OAuth2.0 scheme that's in use (ie Implicit Flow) c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { Type = SecuritySchemeType.OAuth2, Flows = new OpenApiOAuthFlows { Implicit = new OpenApiOAuthFlow { AuthorizationUrl = new Uri("/auth-server/connect/authorize", UriKind.Relative), Scopes = new Dictionary<string, string> { { "readAccess", "Access read operations" }, { "writeAccess", "Access write operations" } } } } });};
NOTE: In addition to defining a scheme, you also need to indicate which operations that scheme is applicable to. You can apply schemes globally (ie to ALL operations) through the AddSecurityRequirement
method. The example below indicates that the scheme called "oauth2" should be applied to all operations, and that the "readAccess" and "writeAccess" scopes are required. When applying schemes of type other than "oauth2", the array of scopes MUST be empty.
c.AddSwaggerGen(c =>{ ... c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" } }, new[] { "readAccess", "writeAccess" } } });})
If you have schemes that are only applicable for certain operations, you can apply them through an Operation filter. For example, the following filter adds OAuth2 requirements based on the presence of the AuthorizeAttribute
:
// SecurityRequirementsOperationFilter.cspublic class SecurityRequirementsOperationFilter : IOperationFilter{public void Apply(OpenApiOperation operation, OperationFilterContext context){// Policy names map to scopesvar requiredScopes = context.MethodInfo.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Select(attr => attr.Policy).Distinct();if (requiredScopes.Any()){operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });var oAuthScheme = new OpenApiSecurityScheme{Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" }};operation.Security = new List<OpenApiSecurityRequirement>{new OpenApiSecurityRequirement{[ oAuthScheme ] = requiredScopes.ToList()}};}}}
NOTE: If you're using the SwaggerUI
middleware, you can enable interactive OAuth2.0 flows that are powered by the emitted security metadata. See Enabling OAuth2.0 Flows for more details.
services.AddSwaggerGen(c =>{ c.AddSecurityDefinition("bearerAuth", new OpenApiSecurityScheme { Type = SecuritySchemeType.Http, Scheme = "bearer", BearerFormat = "JWT", Description = "JWT Authorization header using the Bearer scheme." }); c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearerAuth" } }, new string[] {} } });});
Swagger / OpenAPI defines the allOf
and oneOf
keywords for describing inheritance and polymorphism relationships in schema definitions. For example, if you're using a base class for models that share common properties you can use the allOf
keyword to describe the inheritance hierarchy. Or, if your serializer supports polymorphic serialization/deserialization, you can use the oneOf
keyword to document all the "possible" schemas for requests/responses that vary by subtype.
By default, Swashbuckle flattens inheritance hierarchies. That is, for derived models, the inherited properties are combined and listed alongside the declared properties. This can cause a lot of duplication in the generated Swagger, particularly when there's multiple subtypes. It's also problematic if you're using a client generator (eg NSwag) and would like to maintain the inheritance hierarchy in the generated client models. To work around this, you can apply the UseAllOfForInheritance
setting, and this will leverage the allOf
keyword to incorporate inherited properties by reference in the generated Swagger:
Circle: { type: "object", allOf: [ { $ref: "#/components/schemas/Shape" } ], properties: { radius: { type: "integer", format: "int32", } }, }, Shape: { type: "object", properties: { name: { type: "string", nullable: true, } }, }
If your serializer supports polymorphic serialization/deserialization and you would like to list the possible subtypes for an action that accepts/returns abstract base types, you can apply the UseOneOfForPolymorphism
setting. As a result, the generated request/response schemas will reference a collection of "possible" schemas instead of just the base class schema:
requestBody: { content: { application/json: { schema: { oneOf: [ { $ref: "#/components/schemas/Rectangle" }, { $ref: "#/components/schemas/Circle" }, ], } } }
As inheritance and polymorphism relationships can often become quite complex, not just in your own models but also within the .NET class library, Swashbuckle is selective about which hierarchies it does and doesn't expose in the generated Swagger. By default, it will pick up any subtypes that are defined in the same assembly as a given base type. If you'd like to override this behavior, you can provide a custom selector function:
services.AddSwaggerGen(c =>{ ... c.UseAllOfForInheritance(); c.SelectSubTypesUsing(baseType => { return typeof(Startup).Assembly.GetTypes().Where(type => type.IsSubclassOf(baseType)); })});
NOTE: If you're using the Swashbuckle Annotations library, it contains a custom selector that's based on the presence of SwaggerSubType
attributes on base class definitions. This way, you can use simple attributes to explicitly list the inheritance and/or polymorphism relationships you want to expose. To enable this behavior, check out the Annotations docs.
In conjunction with the oneOf
and/or allOf
keywords, Swagger / OpenAPI supports a discriminator
field on base schema definitions. This keyword points to the property that identifies the specific type being represented by a given payload. In addition to the property name, the discriminator description MAY also include a mapping
which maps discriminator values to specific schema definitions.
For example, the Newtonsoft serializer supports polymorphic serialization/deserialization by emitting/accepting a "$type" property on JSON instances. The value of this property will be the assembly qualified type name of the type represented by a given JSON instance. So, to explicitly describe this behavior in Swagger, the corresponding request/response schema could be defined as follows:
components: { schemas: { Shape: { required: [ "$type" ], type: "object", properties: { $type: { type": "string" }, discriminator: { propertyName: "$type", mapping: { Rectangle: "#/components/schemas/Rectangle", Circle: "#/components/schemas/Circle" } } }, Rectangle: { type: "object", allOf: [ { "$ref": "#/components/schemas/Shape" } ], ... }, Circle: { type: "object", allOf: [ { "$ref": "#/components/schemas/Shape" } ], ... } } }
If UseAllOfForInheritance
or UseOneOfForPolymorphism
is enabled, and your serializer supports (and has enabled) emitting/accepting a discriminator property, then Swashbuckle will automatically generate the corresponding discriminator
metadata on base schema definitions.
Alternatively, if you've customized your serializer to support polymorphic serialization/deserialization, you can provide some custom selector functions to determine the discriminator name and corresponding mapping:
services.AddSwaggerGen(c =>{ ... c.UseOneOfForInheritance(); c.SelectDiscriminatorNameUsing((baseType) => "TypeName"); c.SelectDiscriminatorValueUsing((subType) => subType.Name);});
NOTE: If you're using the Swashbuckle Annotations library, it contains custom selector functions that are based on the presence of SwaggerDiscriminator
and SwaggerSubType
attributes on base class definitions. This way, you can use simple attributes to explicitly provide discriminator metadata. To enable this behavior, check out the Annotations docs.
By default, the Swagger UI will be exposed at "/swagger". If necessary, you can alter this when enabling the SwaggerUI middleware:
app.UseSwaggerUI(c =>{ c.RoutePrefix = "api-docs"}
By default, the Swagger UI will have a generic document title. When you have multiple Swagger pages open, it can be difficult to tell them apart. You can alter this when enabling the SwaggerUI middleware:
app.UseSwaggerUI(c =>{ c.DocumentTitle = "My Swagger UI";}
By default, the Swagger UI include default CSS and JS, but if you wish to change the path or URL (for example to use a CDN):
app.UseSwaggerUI(c =>{ c.StylesPath = "https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.10/swagger-ui.min.css"; c.ScriptBundlePath = "https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.10/swagger-ui-bundle.min.js"; c.ScriptPresetsPath = "https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.10/swagger-ui-standalone-preset.min.js";}
When enabling the middleware, you're required to specify one or more Swagger endpoints (fully qualified or relative to the UI page) to power the UI. If you provide multiple endpoints, they'll be listed in the top right corner of the page, allowing users to toggle between the different documents. For example, the following configuration could be used to document different versions of an API.
app.UseSwaggerUI(c =>{ c.SwaggerEndpoint("/swagger/v1/swagger.json", "V1 Docs"); c.SwaggerEndpoint("/swagger/v2/swagger.json", "V2 Docs"); }
The swagger-ui ships with its own set of configuration parameters, all described here. In Swashbuckle, most of these are surfaced through the SwaggerUI middleware options:
app.UseSwaggerUI(c =>{ c.DefaultModelExpandDepth(2); c.DefaultModelRendering(ModelRendering.Model); c.DefaultModelsExpandDepth(-1); c.DisplayOperationId(); c.DisplayRequestDuration(); c.DocExpansion(DocExpansion.None); c.EnableDeepLinking(); c.EnableFilter(); c.EnablePersistAuthorization(); c.EnableTryItOutByDefault(); c.MaxDisplayedTags(5); c.ShowExtensions(); c.ShowCommonExtensions(); c.Plugins = ["myCustomPlugin"]; c.EnableValidator(); c.SupportedSubmitMethods(SubmitMethod.Get, SubmitMethod.Head); c.UseRequestInterceptor("(request) => { return request; }"); c.UseResponseInterceptor("(response) => { return response; }");});
ملحوظة
When adding custom plugins, make sure you add any custom js
files that define the plugin function(s).
To tweak the behavior, you can inject additional JavaScript files by adding them to your wwwroot
folder and specifying the relative paths in the middleware options:
app.UseSwaggerUI(c =>{ c.InjectJavascript("/swagger-ui/custom.js");}
NOTE: The InjectOnCompleteJavaScript
and InjectOnFailureJavaScript
options have been removed because the latest version of swagger-ui doesn't expose the necessary hooks. Instead, it provides a flexible customization system based on concepts and patterns from React and Redux. To leverage this, you'll need to provide a custom version of index.html as described below.
The custom index sample app demonstrates this approach, using the swagger-ui plugin system provide a custom topbar, and to hide the info component.
To tweak the look and feel, you can inject additional CSS stylesheets by adding them to your wwwroot
folder and specifying the relative paths in the middleware options:
app.UseSwaggerUI(c =>{ c.InjectStylesheet("/swagger-ui/custom.css");}
To customize the UI beyond the basic options listed above, you can provide your own version of the swagger-ui index.html page:
app.UseSwaggerUI(c =>{ c.IndexStream = () => GetType().Assembly .GetManifestResourceStream("CustomUIIndex.Swagger.index.html"); // requires file to be added as an embedded resource});
To get started, you should base your custom index.html on the default version
The swagger-ui has built-in support to participate in OAuth2.0 authorization flows. It interacts with authorization and/or token endpoints, as specified in the Swagger JSON, to obtain access tokens for subsequent API calls. See Adding Security Definitions and Requirements for an example of adding OAuth2.0 metadata to the generated Swagger.
If your Swagger endpoint includes the appropriate security metadata, the UI interaction should be automatically enabled. However, you can further customize OAuth support in the UI with the following settings below. See Swagger-UI documentation for more info:
app.UseSwaggerUI(c =>{ c.OAuthClientId("test-id"); c.OAuthClientSecret("test-secret"); c.OAuthUsername("test-user"); c.OAuthRealm("test-realm"); c.OAuthAppName("test-app"); c.OAuth2RedirectUrl("url"); c.OAuthScopeSeparator(" "); c.OAuthScopes("scope1", "scope2"); c.OAuthAdditionalQueryStringParams(new Dictionary<string, string> { { "foo", "bar" }}); c.OAuthUseBasicAuthenticationWithAccessCodeGrant(); c.OAuthUsePkce();});
To use custom interceptors on requests and responses going through swagger-ui you can define them as javascript functions in the configuration:
app.UseSwaggerUI(c =>{ c.UseRequestInterceptor("(req) => { req.headers['x-my-custom-header'] = 'MyCustomValue'; return req; }"); c.UseResponseInterceptor("(res) => { console.log('Custom interceptor intercepted response from:', res.url); return res; }");});
This can be useful in a range of scenarios where you might want to append local xsrf tokens to all requests for example:
app.UseSwaggerUI(c =>{ c.UseRequestInterceptor("(req) => { req.headers['X-XSRF-Token'] = localStorage.getItem('xsrf-token'); return req; }"); }) ؛
Install the following Nuget package into your ASP.NET Core application.
Package Manager : Install-Package Swashbuckle.AspNetCore.Annotations CLI : dotnet add package Swashbuckle.AspNetCore.Annotations
In the ConfigureServices
method of Startup.cs
, enable annotations within in the Swagger config block:
services.AddSwaggerGen(c =>{ ... c.EnableAnnotations();});
Once annotations have been enabled, you can enrich the generated Operation metadata by decorating actions with a SwaggerOperationAttribute
.
[HttpPost][SwaggerOperation( Summary = "Creates a new product", Description = "Requires admin privileges", OperationId = "CreateProduct", Tags = new[] { "Purchase", "Products" })]public IActionResult Create([FromBody]Product product)
ASP.NET Core provides the ProducesResponseTypeAttribute
for listing the different responses that can be returned by an action. These attributes can be combined with XML comments, as described above, to include human friendly descriptions with each response in the generated Swagger. If you'd prefer to do all of this with a single attribute, and avoid the use of XML comments, you can use SwaggerResponseAttribute
s instead:
[HttpPost][SwaggerResponse(201, "The product was created", typeof(Product))][SwaggerResponse(400, "The product data is invalid")]public IActionResult Create([FromBody]Product product)
You can annotate "path", "query" or "header" bound parameters or properties (ie decorated with [FromRoute]
, [FromQuery]
or [FromHeader]
) with a SwaggerParameterAttribute
to enrich the corresponding Parameter
metadata that's generated by Swashbuckle:
[HttpGet]public IActionResult GetProducts([FromQuery, SwaggerParameter("Search keywords", Required = true)]string keywords)
You can annotate "body" bound parameters or properties (ie decorated with [FromBody]
) with a SwaggerRequestBodyAttribute
to enrich the corresponding RequestBody
metadata that's generated by Swashbuckle:
[HttpPost]public IActionResult CreateProduct([FromBody, SwaggerRequestBody("The product payload", Required = true)]Product product)
You can annotate classes or properties with a SwaggerSchemaAttribute
to enrich the corresponding Schema
metadata that's generated by Swashbuckle:
[SwaggerSchema(Required = new[] { "Description" })]public class Product{[SwaggerSchema("The product identifier", ReadOnly = true)]public int Id { get; تعيين؛ }[SwaggerSchema("The product description")]public string Description { get; تعيين؛ }[SwaggerSchema("The date it was created", Format = "date")]public DateTime DateCreated { get; تعيين؛ }}
NOTE: In Swagger / OpenAPI, serialized objects AND contained properties are represented as Schema
instances, hence why this annotation can be applied to both classes and properties. Also worth noting, "required" properties are specified as an array of property names on the top-level schema as opposed to a flag on each individual property.
The SwaggerGen
package provides several extension points, including Schema Filters (described here) for customizing ALL generated Schemas. However, there may be cases where it's preferable to apply a filter to a specific Schema. For example, if you'd like to include an example for a specific type in your API. This can be done by decorating the type with a SwaggerSchemaFilterAttribute
:
// Product.cs[SwaggerSchemaFilter(typeof(ProductSchemaFilter))]public class Product{...}// ProductSchemaFilter.cspublic class ProductSchemaFilter : ISchemaFilter{public void Apply(OpenApiSchema schema, SchemaFilterContext context){schema.Example = new OpenApiObject{[ "Id" ] = new OpenApiInteger(1),[ "Description" ] = new OpenApiString("An awesome product")};}}
By default, the Swagger generator will tag all operations with the controller name. This tag is then used to drive the operation groupings in the swagger-ui. If you'd like to provide a description for each of these groups, you can do so by adding metadata for each controller name tag via the SwaggerTagAttribute
:
[SwaggerTag("Create, read, update and delete Products")]public class ProductsController{...}
NOTE: This will add the above description specifically to the tag named "Products". Therefore, you should avoid using this attribute if you're tagging Operations with something other than controller name - eg if you're customizing the tagging behavior with TagActionsBy
.
If you want to use Swashbuckle's inheritance and/or polymorphism behavior, you can use annotations to explicitly indicate the "known" subtypes for a given base type. This will override the default selector function, which selects all subtypes in the same assembly as the base type, and therefore needs to be explicitly enabled when you enable Annotations:
// Startup.csservices.AddSwaggerGen(c =>{ c.EnableAnnotations(enableAnnotationsForInheritance: true, enableAnnotationsForPolymorphism: true);});// Shape.cs[SwaggerSubType(typeof(Rectangle))][SwaggerSubType(typeof(Circle))]public abstract class Shape{}
If you're using annotations to explicitly indicate the "known" subtypes for a polymorphic base type, you can combine the SwaggerDiscriminatorAttribute
with the SwaggerSubTypeAttribute
to provide additional metadata about the "discriminator" property, which will then be incorporated into the generated schema definition:
// Startup.csservices.AddSwaggerGen(c =>{ c.EnableAnnotations(enableAnnotationsForInheritance: true, enableAnnotationsForPolymorphism: true);});// Shape.cs[SwaggerDiscriminator("shapeType")][SwaggerSubType(typeof(Rectangle), DiscriminatorValue = "rectangle")][SwaggerSubType(typeof(Circle), DiscriminatorValue = "circle")]public abstract class Shape{public ShapeType { get; تعيين؛ }}
This indicates that the corresponding payload will have a "shapeType" property to discriminate between subtypes, and that property will have a value of "rectangle" if the payload represents a Rectangle
type and a value of "circle" if it represents a Circle
type. This detail will be described in the generated schema definition as follows:
schema: { oneOf: [ { $ref: "#/components/schemas/Rectangle" }, { $ref: "#/components/schemas/Circle" }, ], discriminator: { propertyName: shapeType, mapping: { rectangle: "#/components/schemas/Rectangle", circle: "#/components/schemas/Circle", } } }
Once your application has been setup with Swashbuckle (see Getting Started), you can use the Swashbuckle CLI tool to retrieve Swagger / OpenAPI JSON directly from your application's startup assembly, and write it to file. This can be useful if you want to incorporate Swagger generation into a CI/CD process, or if you want to serve it from static file at run-time.
It's packaged as a .NET Tool that can be installed and used via the dotnet SDK.
️ The tool needs to load your Startup DLL and its dependencies at runtime. Therefore, you should use a version of thedotnet
SDK that is compatible with your application. For example, if your app targetsnet6.0
, then you should use version 6.0.xxx of the SDK to run the CLI tool. If it targetsnet8.0
, then you should use version 8.0.xxx of the SDK and so on.
Install as a global tool
dotnet tool install -g Swashbuckle.AspNetCore.Cli
Verify that the tool was installed correctly
swagger tofile --help
Generate a Swagger/ OpenAPI document from your application's startup assembly
swagger tofile --output [output] [startupassembly] [swaggerdoc]
أين ...
[output] is the relative path where the Swagger JSON will be output to
[startupassembly] is the relative path to your application's startup assembly
[swaggerdoc] is the name of the swagger document you want to retrieve, as configured in your startup class
In your project root, create a tool manifest file:
dotnet new tool-manifest
Install as a local tool
dotnet tool install Swashbuckle.AspNetCore.Cli
Verify that the tool was installed correctly
dotnet swagger tofile --help
Generate a Swagger / OpenAPI document from your application's startup assembly
dotnet swagger tofile --output [output] [startupassembly] [swaggerdoc]
أين ...
[output] is the relative path where the Swagger JSON will be output to
[startupassembly] is the relative path to your application's startup assembly
[swaggerdoc] is the name of the swagger document you want to retrieve, as configured in your startup class
Out-of-the-box, the tool will execute in the context of a "default" web host. However, in some cases you may want to bring your own host environment, for example if you've configured a custom DI container such as Autofac. For this scenario, the Swashbuckle CLI tool exposes a convention-based hook for your application.
That is, if your application contains a class that meets either of the following naming conventions, then that class will be used to provide a host for the CLI tool to run in.
public class SwaggerHostFactory
, containing a public static method called CreateHost
with return type IHost
public class SwaggerWebHostFactory
, containing a public static method called CreateWebHost
with return type IWebHost
For example, the following class could be used to leverage the same host configuration as your application:
public class SwaggerHostFactory{public static IHost CreateHost(){return Program.CreateHostBuilder(new string[0]).Build();}}
By default, the Redoc UI will be exposed at "/api-docs". If necessary, you can alter this when enabling the Redoc middleware:
app.UseReDoc(c =>{ c.RoutePrefix = "docs" ...}
By default, the Redoc UI will have a generic document title. You can alter this when enabling the Redoc middleware:
app.UseReDoc(c =>{c.DocumentTitle = "My API Docs";...}
Redoc ships with its own set of configuration parameters, all described here https://github.com/Rebilly/redoc/blob/main/README.md#redoc-options-object. In Swashbuckle, most of these are surfaced through the Redoc middleware options:
app.UseReDoc(c =>{ c.SpecUrl("/v1/swagger.json"); c.EnableUntrustedSpec(); c.ScrollYOffset(10); c.HideHostname(); c.HideDownloadButton(); c.ExpandResponses("200,201"); c.RequiredPropsFirst(); c.NoAutoAuth(); c.PathInMiddlePanel(); c.HideLoading(); c.NativeScrollbars(); c.DisableSearch(); c.OnlyRequiredInSamples(); c.SortPropsAlphabetically();});
Using c.SpecUrl("/v1/swagger.json")
multiple times within the same UseReDoc(...)
will not add multiple urls.
To tweak the look and feel, you can inject additional CSS stylesheets by adding them to your wwwroot
folder and specifying the relative paths in the middleware options:
app.UseReDoc(c =>{ ... c.InjectStylesheet("/redoc/custom.css");}
It is also possible to modify the theme by using the AdditionalItems
property, see https://github.com/Rebilly/redoc/blob/main/README.md#redoc-options-object for more information.
app.UseReDoc(c =>{ ... c.ConfigObject.AdditionalItems = ...}
To customize the UI beyond the basic options listed above, you can provide your own version of the Redoc index.html page:
app.UseReDoc(c =>{ c.IndexStream = () => GetType().Assembly .GetManifestResourceStream("CustomIndex.ReDoc.index.html"); // requires file to be added as an embedded resource});
To get started, you should base your custom index.html on the default version