So verwenden Sie das ASP.NET Core-Back-End-Server-SDK
Anmerkung
Dieses Produkt wird eingestellt. Eine Ersetzung für Projekte mit .NET 8 oder höher finden Sie in der Community Toolkit Datasync-Bibliothek.
In diesem Artikel erfahren Sie, wie Sie das ASP.NET Core-Back-End-Server-SDK konfigurieren und verwenden müssen, um einen Datensynchronisierungsserver zu erstellen.
Unterstützte Plattformen
Der ASP.NET Core-Back-End-Server unterstützt ASP.NET 6.0 oder höher.
Datenbankserver müssen die folgenden Kriterien erfüllen, die über ein DateTime
- oder Timestamp
Typfeld verfügen, das mit Millisekundengenauigkeit gespeichert ist. Repositoryimplementierungen werden für Entity Framework Core und LiteDbbereitgestellt.
Spezifische Datenbankunterstützung finden Sie in den folgenden Abschnitten:
Erstellen eines neuen Datensynchronisierungsservers
Ein Datensynchronisierungsserver verwendet die normalen ASP.NET Core-Mechanismen zum Erstellen des Servers. Sie besteht aus drei Schritten:
- Erstellen Sie ein ASP.NET 6.0 -Serverprojekt (oder höher).
- Hinzufügen von Entity Framework Core
- Hinzufügen von Datensynchronisierungsdiensten
Informationen zum Erstellen eines ASP.NET Core-Diensts mit Entity Framework Core finden Sie in lernprogramm.
Um Datensynchronisierungsdienste zu aktivieren, müssen Sie die folgenden NuGet-Bibliotheken hinzufügen:
- Microsoft.AspNetCore.Datasync-
- Microsoft.AspNetCore.Datasync.EFCore für Entity Framework Core-basierte Tabellen.
- Microsoft.AspNetCore.Datasync.InMemory für In-Memory-Tabellen.
Ändern Sie die Program.cs
Datei. Fügen Sie die folgende Zeile unter allen anderen Dienstdefinitionen hinzu:
builder.Services.AddDatasyncControllers();
Sie können auch die Vorlage ASP.NET Core datasync-server
verwenden:
# This only needs to be done once
dotnet new -i Microsoft.AspNetCore.Datasync.Template.CSharp
mkdir My.Datasync.Server
cd My.Datasync.Server
dotnet new datasync-server
Die Vorlage enthält ein Beispielmodell und einen Controller.
Erstellen eines Tabellencontrollers für eine SQL-Tabelle
Das Standard-Repository verwendet Entity Framework Core. Das Erstellen eines Tabellencontrollers ist ein dreistufiger Prozess:
- Erstellen Sie eine Modellklasse für das Datenmodell.
- Fügen Sie die Modellklasse der
DbContext
für Ihre Anwendung hinzu. - Erstellen Sie eine neue
TableController<T>
Klasse, um Ihr Modell verfügbar zu machen.
Erstellen einer Modellklasse
Alle Modellklassen müssen ITableData
implementieren. Jeder Repositorytyp verfügt über eine abstrakte Klasse, die ITableData
implementiert. Das Entity Framework Core-Repository verwendet EntityTableData
:
public class TodoItem : EntityTableData
{
/// <summary>
/// Text of the Todo Item
/// </summary>
public string Text { get; set; }
/// <summary>
/// Is the item complete?
/// </summary>
public bool Complete { get; set; }
}
Die schnittstelle ITableData
stellt die ID des Datensatzes zusammen mit zusätzlichen Eigenschaften für die Verarbeitung von Datensynchronisierungsdiensten bereit:
-
UpdatedAt
(DateTimeOffset?
) gibt das Datum an, an dem der Datensatz zuletzt aktualisiert wurde. -
Version
(byte[]
) stellt einen undurchsichtigen Wert bereit, der sich bei jedem Schreibvorgang ändert. -
Deleted
(bool
) ist "true", wenn der Datensatz zum Löschen markiert, aber noch nicht gelöscht wurde.
Die Datensynchronisierungsbibliothek verwaltet diese Eigenschaften. Ändern Sie diese Eigenschaften nicht in Ihrem eigenen Code.
Aktualisieren der DbContext
Jedes Modell in der Datenbank muss im DbContext
registriert werden. Zum Beispiel:
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
public DbSet<TodoItem> TodoItems { get; set; }
}
Erstellen eines Tabellencontrollers
Ein Tabellencontroller ist eine spezielle ApiController
. Hier ist ein minimaler Tabellencontroller:
[Route("tables/[controller]")]
public class TodoItemController : TableController<TodoItem>
{
public TodoItemController(AppDbContext context) : base()
{
Repository = new EntityTableRepository<TodoItem>(context);
}
}
Anmerkung
- Der Controller muss über eine Route verfügen. Standardmäßig werden Tabellen auf einem Unterpfad von
/tables
verfügbar gemacht, können aber überall platziert werden. Wenn Sie Clientbibliotheken vor v5.0.0 verwenden, muss die Tabelle ein Unterpfad von/tables
sein. - Der Controller muss von
TableController<T>
erben, wobei<T>
eine Implementierung derITableData
Implementierung für Ihren Repositorytyp ist. - Weisen Sie ein Repository basierend auf demselben Typ wie Ihr Modell zu.
Implementieren eines Speicher-Repositorys
Sie können auch ein speicherinternes Repository ohne beständigen Speicher verwenden. Fügen Sie einen Singletondienst für das Repository in Ihrem Program.cs
hinzu:
IEnumerable<Model> seedData = GenerateSeedData();
builder.Services.AddSingleton<IRepository<Model>>(new InMemoryRepository<Model>(seedData));
Richten Sie den Tabellencontroller wie folgt ein:
[Route("tables/[controller]")]
public class ModelController : TableController<Model>
{
public MovieController(IRepository<Model> repository) : base(repository)
{
}
}
Konfigurieren von Tabellencontrolleroptionen
Sie können bestimmte Aspekte des Controllers mithilfe von TableControllerOptions
konfigurieren:
[Route("tables/[controller]")]
public class MoodelController : TableController<Model>
{
public ModelController(IRepository<Model> repository) : base(repository)
{
Options = new TableControllerOptions { PageSize = 25 };
}
}
Zu den Optionen, die Sie festlegen können, gehören:
-
PageSize
(int
, Standard: 100) ist die maximale Anzahl von Elementen, die ein Abfragevorgang auf einer einzelnen Seite zurückgegeben hat. -
MaxTop
(int
, Standard: 512000) ist die maximale Anzahl von Elementen, die in einem Abfragevorgang ohne Paging zurückgegeben werden. -
EnableSoftDelete
(bool
, Standard: false) ermöglicht das Vorläufige Löschen, wodurch Elemente als gelöscht gekennzeichnet werden, anstatt sie aus der Datenbank zu löschen. Das vorläufige Löschen ermöglicht Clients das Aktualisieren des Offlinecaches, erfordert jedoch, dass gelöschte Elemente separat aus der Datenbank gelöscht werden. -
UnauthorizedStatusCode
(int
, Standard: 401 Nicht autorisiert) ist der Statuscode, der zurückgegeben wird, wenn der Benutzer keine Aktion ausführen darf.
Konfigurieren von Zugriffsberechtigungen
Standardmäßig kann ein Benutzer alles tun, was er für Entitäten innerhalb einer Tabelle verwenden möchte – einen beliebigen Datensatz erstellen, lesen, aktualisieren und löschen. Um eine differenzierte Kontrolle über die Autorisierung zu erhalten, erstellen Sie eine Klasse, die IAccessControlProvider
implementiert. Die IAccessControlProvider
verwendet drei Methoden zum Implementieren der Autorisierung:
-
GetDataView()
gibt eine Lambda-Funktion zurück, die angibt, was der verbundene Benutzer sehen kann. -
IsAuthorizedAsync()
bestimmt, ob der verbundene Benutzer die Aktion für die gewünschte Entität ausführen kann. -
PreCommitHookAsync()
passt jede Entität unmittelbar vor dem Schreiben in das Repository an.
Zwischen den drei Methoden können Sie die meisten Zugriffssteuerungsfälle effektiv behandeln. Wenn Sie Zugriff auf die HttpContext
benötigen, einen HttpContextAccessor-konfigurieren.
Im Folgenden wird beispielsweise eine persönliche Tabelle implementiert, in der ein Benutzer nur seine eigenen Datensätze sehen kann.
public class PrivateAccessControlProvider<T>: IAccessControlProvider<T>
where T : ITableData
where T : IUserId
{
private readonly IHttpContextAccessor _accessor;
public PrivateAccessControlProvider(IHttpContextAccessor accessor)
{
_accessor = accessor;
}
private string UserId { get => _accessor.HttpContext.User?.Identity?.Name; }
public Expression<Func<T,bool>> GetDataView()
{
return (UserId == null)
? _ => false
: model => model.UserId == UserId;
}
public Task<bool> IsAuthorizedAsync(TableOperation op, T entity, CancellationToken token = default)
{
if (op == TableOperation.Create || op == TableOperation.Query)
{
return Task.FromResult(true);
}
else
{
return Task.FromResult(entity?.UserId != null && entity?.UserId == UserId);
}
}
public virtual Task PreCommitHookAsync(TableOperation operation, T entity, CancellationToken token = default)
{
entity.UserId == UserId;
return Task.CompletedTask;
}
}
Die Methoden sind asynchron, falls Sie eine zusätzliche Datenbanksuche durchführen müssen, um die richtige Antwort zu erhalten. Sie können die IAccessControlProvider<T>
Schnittstelle auf dem Controller implementieren, müssen aber dennoch die IHttpContextAccessor
übergeben, um auf die HttpContext
sicher zuzugreifen.
Um diesen Zugriffssteuerungsanbieter zu verwenden, aktualisieren Sie Ihre TableController
wie folgt:
[Authorize]
[Route("tables/[controller]")]
public class ModelController : TableController<Model>
{
public ModelsController(AppDbContext context, IHttpContextAccessor accessor) : base()
{
AccessControlProvider = new PrivateAccessControlProvider<Model>(accessor);
Repository = new EntityTableRepository<Model>(context);
}
}
Wenn Sie sowohl nicht authentifizierten als auch authentifizierten Zugriff auf eine Tabelle zulassen möchten, versehen Sie sie mit [AllowAnonymous]
anstelle von [Authorize]
.
Konfigurieren der Protokollierung
Die Protokollierung wird über normalen Protokollierungsmechanismus für ASP.NET Core behandelt. Weisen Sie das ILogger
-Objekt der eigenschaft Logger
zu:
[Authorize]
[Route("tables/[controller]")]
public class ModelController : TableController<Model>
{
public ModelController(AppDbContext context, Ilogger<ModelController> logger) : base()
{
Repository = new EntityTableRepository<Model>(context);
Logger = logger;
}
}
Überwachen von Repositoryänderungen
Wenn das Repository geändert wird, können Sie Workflows auslösen, die Antwort auf den Client protokollieren oder andere Arbeiten in einer von zwei Methoden ausführen:
Option 1: Implementieren eines PostCommitHookAsync
Die IAccessControlProvider<T>
-Schnittstelle stellt eine PostCommitHookAsync()
Methode bereit. Die Th PostCommitHookAsync()
-Methode wird aufgerufen, nachdem die Daten in das Repository geschrieben wurden, aber bevor die Daten an den Client zurückgegeben werden. Es muss darauf geachtet werden, dass die an den Client zurückgegebenen Daten in dieser Methode nicht geändert werden.
public class MyAccessControlProvider<T> : AccessControlProvider<T> where T : ITableData
{
public override async Task PostCommitHookAsync(TableOperation op, T entity, CancellationToken cancellationToken = default)
{
// Do any work you need to here.
// Make sure you await any asynchronous operations.
}
}
Verwenden Sie diese Option, wenn Sie asynchrone Aufgaben als Teil des Hooks ausführen.
Option 2: Verwenden des RepositoryUpdated-Ereignishandlers
Die TableController<T>
Basisklasse enthält einen Ereignishandler, der gleichzeitig mit der PostCommitHookAsync()
-Methode aufgerufen wird.
[Authorize]
[Route(tables/[controller])]
public class ModelController : TableController<Model>
{
public ModelController(AppDbContext context) : base()
{
Repository = new EntityTableRepository<Model>(context);
RepositoryUpdated += OnRepositoryUpdated;
}
internal void OnRepositoryUpdated(object sender, RepositoryUpdatedEventArgs e)
{
// The RepositoryUpdatedEventArgs contains Operation, Entity, EntityName
}
}
Aktivieren der Azure App Service Identity
Der ASP.NET Core Data Sync Server unterstützt ASP.NET Core Identityoder ein anderes Authentifizierungs- und Autorisierungsschema, das Sie unterstützen möchten. Um Upgrades von früheren Versionen von Azure Mobile Apps zu unterstützen, stellen wir auch einen Identitätsanbieter bereit, der Azure App Service Identityimplementiert. Um Azure App Service Identity in Ihrer Anwendung zu konfigurieren, bearbeiten Sie Ihre Program.cs
:
builder.Services.AddAuthentication(AzureAppServiceAuthentication.AuthenticationScheme)
.AddAzureAppServiceAuthentication(options => options.ForceEnable = true);
// Then later, after you have created the app
app.UseAuthentication();
app.UseAuthorization();
Datenbankunterstützung
Entity Framework Core richtet keine Wertgenerierung für Datums-/Uhrzeitspalten ein. (Siehe Datum/Uhrzeit-Wertgenerierung). Das Azure Mobile Apps-Repository für Entity Framework Core aktualisiert automatisch das feld UpdatedAt
für Sie. Wenn Ihre Datenbank jedoch außerhalb des Repositorys aktualisiert wird, müssen Sie die felder UpdatedAt
und Version
aktualisieren.
Azure SQL
Erstellen Sie einen Trigger für jede Entität:
CREATE OR ALTER TRIGGER [dbo].[TodoItems_UpdatedAt] ON [dbo].[TodoItems]
AFTER INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE
[dbo].[TodoItems]
SET
[UpdatedAt] = GETUTCDATE()
WHERE
[Id] IN (SELECT [Id] FROM INSERTED);
END
Sie können diesen Trigger entweder mithilfe einer Migration oder unmittelbar nach EnsureCreated()
installieren, um die Datenbank zu erstellen.
Azure Cosmos DB
Azure Cosmos DB ist eine vollständig verwaltete NoSQL-Datenbank für leistungsstarke Anwendungen mit beliebiger Größe oder Skalierung. Informationen zur Verwendung von Azure Cosmos DB mit Entity Framework Core finden Sie unter Azure Cosmos DB Provider. Bei Verwendung von Azure Cosmos DB mit Azure Mobile Apps:
Richten Sie den Cosmos-Container mit einem zusammengesetzten Index ein, der die Felder
UpdatedAt
undId
angibt. Zusammengesetzte Indizes können einem Container über das Azure-Portal, ARM, Bicep, Terraform oder im Code hinzugefügt werden. Hier ist ein Beispiel bicep- Ressourcendefinition:resource cosmosContainer 'Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers@2023-04-15' = { name: 'TodoItems' parent: cosmosDatabase properties: { resource: { id: 'TodoItems' partitionKey: { paths: [ '/Id' ] kind: 'Hash' } indexingPolicy: { indexingMode: 'consistent' automatic: true includedPaths: [ { path: '/*' } ] excludedPaths: [ { path: '/"_etag"/?' } ] compositeIndexes: [ [ { path: '/UpdatedAt' order: 'ascending' } { path: '/Id' order: 'ascending' } ] ] } } } }
Wenn Sie eine Teilmenge von Elementen in der Tabelle abrufen, stellen Sie sicher, dass Sie alle Eigenschaften angeben, die an der Abfrage beteiligt sind.
Abgeleitete Modelle aus der
ETagEntityTableData
Klasse:public class TodoItem : ETagEntityTableData { public string Title { get; set; } public bool Completed { get; set; } }
Fügen Sie der
DbContext
eineOnModelCreating(ModelBuilder)
Methode hinzu. Der Cosmos DB-Treiber für Entity Framework platziert standardmäßig alle Entitäten in denselben Container. Sie müssen mindestens einen geeigneten Partitionsschlüssel auswählen und sicherstellen, dass dieEntityTag
Eigenschaft als Parallelitätstag gekennzeichnet ist. Der folgende Codeausschnitt speichert beispielsweise dieTodoItem
Entitäten in ihrem eigenen Container mit den entsprechenden Einstellungen für Azure Mobile Apps:protected override void OnModelCreating(ModelBuilder builder) { builder.Entity<TodoItem>(builder => { // Store this model in a specific container. builder.ToContainer("TodoItems"); // Do not include a discriminator for the model in the partition key. builder.HasNoDiscriminator(); // Set the partition key to the Id of the record. builder.HasPartitionKey(model => model.Id); // Set the concurrency tag to the EntityTag property. builder.Property(model => model.EntityTag).IsETagConcurrency(); }); base.OnModelCreating(builder); }
Azure Cosmos DB wird seit v5.0.11 im Microsoft.AspNetCore.Datasync.EFCore
NuGet-Paket unterstützt. Weitere Informationen können Sie über die folgenden Links erfahren:
- Cosmos DB Sample.
- EF Core Azure Cosmos DB Provider Dokumentation.
- Cosmos DB-Indexrichtlinie Dokumentation.
PostgreSQL
Erstellen Sie einen Trigger für jede Entität:
CREATE OR REPLACE FUNCTION todoitems_datasync() RETURNS trigger AS $$
BEGIN
NEW."UpdatedAt" = NOW() AT TIME ZONE 'UTC';
NEW."Version" = convert_to(gen_random_uuid()::text, 'UTF8');
RETURN NEW
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE TRIGGER
todoitems_datasync
BEFORE INSERT OR UPDATE ON
"TodoItems"
FOR EACH ROW EXECUTE PROCEDURE
todoitems_datasync();
Sie können diesen Trigger entweder mithilfe einer Migration oder unmittelbar nach EnsureCreated()
installieren, um die Datenbank zu erstellen.
SqLite
Warnung
Verwenden Sie SqLite nicht für Produktionsdienste. SqLite eignet sich nur für die clientseitige Verwendung in der Produktion.
SqLite verfügt nicht über ein Datums-/Uhrzeitfeld, das die Genauigkeit von Millisekunden unterstützt. Daher eignet es sich nicht für alles, außer für Tests. Wenn Sie SqLite verwenden möchten, stellen Sie sicher, dass Sie einen Wertkonverter und einen Wertvergleich für jedes Modell für Datums-/Uhrzeiteigenschaften implementieren. Die einfachste Methode zum Implementieren von Wertkonvertern und Vergleichern ist die OnModelCreating(ModelBuilder)
Methode Ihrer DbContext
:
protected override void OnModelCreating(ModelBuilder builder)
{
var timestampProps = builder.Model.GetEntityTypes().SelectMany(t => t.GetProperties())
.Where(p => p.ClrType == typeof(byte[]) && p.ValueGenerated == ValueGenerated.OnAddOrUpdate);
var converter = new ValueConverter<byte[], string>(
v => Encoding.UTF8.GetString(v),
v => Encoding.UTF8.GetBytes(v)
);
foreach (var property in timestampProps)
{
property.SetValueConverter(converter);
property.SetDefaultValueSql("STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')");
}
base.OnModelCreating(builder);
}
Installieren Sie einen Updatetrigger, wenn Sie die Datenbank initialisieren:
internal static void InstallUpdateTriggers(DbContext context)
{
foreach (var table in context.Model.GetEntityTypes())
{
var props = table.GetProperties().Where(prop => prop.ClrType == typeof(byte[]) && prop.ValueGenerated == ValueGenerated.OnAddOrUpdate);
foreach (var property in props)
{
var sql = $@"
CREATE TRIGGER s_{table.GetTableName()}_{prop.Name}_UPDATE AFTER UPDATE ON {table.GetTableName()}
BEGIN
UPDATE {table.GetTableName()}
SET {prop.Name} = STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')
WHERE rowid = NEW.rowid;
END
";
context.Database.ExecuteSqlRaw(sql);
}
}
}
Stellen Sie sicher, dass die InstallUpdateTriggers
-Methode nur einmal während der Datenbankinitialisierung aufgerufen wird:
public void InitializeDatabase(DbContext context)
{
bool created = context.Database.EnsureCreated();
if (created && context.Database.IsSqlite())
{
InstallUpdateTriggers(context);
}
context.Database.SaveChanges();
}
LiteDB
LiteDB ist eine serverlose Datenbank, die in einer einzigen kleinen DLL bereitgestellt wird, die in verwaltetem .NET C#-Code geschrieben wurde. Es ist eine einfache und schnelle NoSQL-Datenbanklösung für eigenständige Anwendungen. So verwenden Sie LiteDb mit beständigem Datenträgerspeicher:
Installieren Sie das
Microsoft.AspNetCore.Datasync.LiteDb
-Paket von NuGet.Fügen Sie dem
Program.cs
ein Singleton für dieLiteDatabase
hinzu:const connectionString = builder.Configuration.GetValue<string>("LiteDb:ConnectionString"); builder.Services.AddSingleton<LiteDatabase>(new LiteDatabase(connectionString));
Leiten Sie Modelle von der
LiteDbTableData
ab:public class TodoItem : LiteDbTableData { public string Title { get; set; } public bool Completed { get; set; } }
Sie können jedes der
BsonMapper
Attribute verwenden, die mit dem LiteDb NuGet-Paket bereitgestellt werden.Erstellen Sie einen Controller mit dem
LiteDbRepository
:[Route("tables/[controller]")] public class TodoItemController : TableController<TodoItem> { public TodoItemController(LiteDatabase db) : base() { Repository = new LiteDbRepository<TodoItem>(db, "todoitems"); } }
OpenAPI-Unterstützung
Sie können die von Datensynchronisierungscontrollern definierte API mit NSwag- oder Swashbuckle-veröffentlichen. Beginnen Sie in beiden Fällen, indem Sie den Dienst wie gewohnt für die ausgewählte Bibliothek einrichten.
NSwag
Befolgen Sie die grundlegenden Anweisungen für die NSwag-Integration, und ändern Sie dann wie folgt:
Fügen Sie Ihrem Projekt Pakete hinzu, um NSwag zu unterstützen. Die folgenden Pakete sind erforderlich:
Fügen Sie folgendes am Anfang ihrer
Program.cs
Datei hinzu:using Microsoft.AspNetCore.Datasync.NSwag;
Fügen Sie einen Dienst hinzu, um eine OpenAPI-Definition zu Ihrer
Program.cs
Datei zu generieren:builder.Services.AddOpenApiDocument(options => { options.AddDatasyncProcessors(); });
Aktivieren Sie die Middleware für die Bereitstellung des generierten JSON-Dokuments und der Swagger-UI, auch in
Program.cs
:if (app.Environment.IsDevelopment()) { app.UseOpenApi(); app.UseSwaggerUI3(); }
Wenn Sie zum /swagger
Endpunkt des Webdiensts navigieren, können Sie die API durchsuchen. Die OpenAPI-Definition kann dann in andere Dienste importiert werden (z. B. Azure API Management). Weitere Informationen zum Konfigurieren von NSwag finden Sie unter Erste Schritte mit NSwag und ASP.NET Core.
Swashbuckle
Befolgen Sie die grundlegenden Anweisungen für die Swashbuckle-Integration, und ändern Sie dann wie folgt:
Fügen Sie Ihrem Projekt Pakete hinzu, um Swashbuckle zu unterstützen. Die folgenden Pakete sind erforderlich:
Fügen Sie einen Dienst hinzu, um eine OpenAPI-Definition zu Ihrer
Program.cs
Datei zu generieren:builder.Services.AddSwaggerGen(options => { options.AddDatasyncControllers(); }); builder.Services.AddSwaggerGenNewtonsoftSupport();
Anmerkung
Die
AddDatasyncControllers()
-Methode verwendet eine optionaleAssembly
, die der Assembly entspricht, die Die Tabellencontroller enthält. DerAssembly
Parameter ist nur erforderlich, wenn sich die Tabellencontroller in einem anderen Projekt als der Dienst befinden.Aktivieren Sie die Middleware für die Bereitstellung des generierten JSON-Dokuments und der Swagger-UI, auch in
Program.cs
:if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(options => { options.SwaggerEndpoint("/swagger/v1/swagger.json", "v1"); options.RoutePrefix = string.Empty; }); }
Mit dieser Konfiguration können Sie im Stammverzeichnis des Webdiensts die API durchsuchen. Die OpenAPI-Definition kann dann in andere Dienste importiert werden (z. B. Azure API Management). Weitere Informationen zum Konfigurieren von Swashbuckle finden Sie unter Erste Schritte mit Swashbuckle und ASP.NET Core.
Begrenzungen
Die ASP.NET Core Edition der Dienstbibliotheken implementiert OData v4 für den Listenvorgang. Wenn der Server im Abwärtskompatibilitätsmodus ausgeführt wird, wird das Filtern nach einer Teilzeichenfolge nicht unterstützt.