InstantAPIs
InstantAPIs copied to clipboard
Support for Startup.cs - ConfigureServices and Configure
I have a .NET 6 project, but I'm using Program.cs
and 'Startup.cs' approach.
There is a method to add InstantAPI using services.AddInstantAPIs();
, but no way to configure it inside Configure(IApplicationBuilder app)
https://github.com/csharpfritz/InstantAPIs/blob/main/Fritz.InstantAPIs/WebApplicationExtensions.cs#L18 supports IEndpointRouteBuilder
but a method that supports IApplicationBuilder
is missing.
Any plans to add support for it?
Don't you use the app.UseEndpoints? If you are, you can do.
app.UseEndpoints(x =>
{
x.MapInstantAPIs<MyContext>(config =>
{
config.IncludeTable(db => db.Contacts, ApiMethodsToGenerate.All, "addressBook");
});
x.MapControllers(); // example of what you are already mapping.
});
@verbedr thank you for the reply. Will try that ASAP
@verbedr this works well. It would be useful to add this example to the readme. What do you think?
@verbedr quick update: this works partially. When I create a new project using .NET 6 and add everything as shown in readme, I'm able to filter DBSets, using below snippet:
app.MapInstantAPIs<MyContext>(config =>
{
config.IncludeTable(db => db.Contacts, ApiMethodsToGenerate.All, "addressBook");
});
but when I do the same in Progam.cs and Startup.cs
approach (a .NET 3.1 project which is converted to .NET 6), nothing is filtered out - I get all the DBSets.
Here is my entire Startup.cs
file:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi.Models;
using Fritz.InstantAPIs;
namespace Test2
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Test2", Version = "v1" });
});
services.AddInstantAPIs();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Test2 v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapInstantAPIs<MyContext>(config =>
{
config.IncludeTable(db => db.Contacts, ApiMethodsToGenerate.Get, "addressBook");
});
});
}
}
}
MyContext.cs
using Microsoft.EntityFrameworkCore;
public class MyContext : DbContext
{
public MyContext(DbContextOptions<MyContext> options) : base(options) { }
public DbSet<Contact> Contacts => Set<Contact>();
public DbSet<Address> Addresses => Set<Address>();
}
public class Contact
{
public int Id { get; set; }
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address
{
public int Id { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
}
Quick way to reproduce:
- Create a .NET 5 ASP.NET Core Web API
- Change TargetFramework to
net6.0
- Update
Swashbuckle.AspNetCore
to6.3.1
- Add
Fritz.InstantAPIs
- Follow steps in readme
You will get this result:
Instead of:
when running from
Program.cs
approach:
using Fritz.InstantAPIs;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSqlite<MyContext>("Data Source=contacts.db");
builder.Services.AddInstantAPIs();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.MapInstantAPIs<MyContext>(config =>
{
config.IncludeTable(db => db.Contacts, ApiMethodsToGenerate.Get, "addressBook");
});
app.Run();
Yes, let’s get the documentation started and add samples like this
Jeff
On May 4, 2022, at 07:05, Tomasz @.***> wrote:
@verbedr quick update: this works partially. When I create a new project using .NET 6 and add everything as shown in readme, I'm able to filter DBSets, using below snippet:
app.MapInstantAPIs<MyContext>(config => { config.IncludeTable(db => db.Contacts, ApiMethodsToGenerate.All, "addressBook"); }); but when I do the same in Progam.cs and Startup.cs approach (a .NET 3.1 project which is converted to .NET 6), nothing is filtered out - I get all the DBSets.
Here is my entire Startup.cs file:
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.OpenApi.Models; using Fritz.InstantAPIs;
namespace Test2 { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; }
public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllers(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "Test2", Version = "v1" }); }); services.AddInstantAPIs(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "Test2 v1")); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); endpoints.MapInstantAPIs<MyContext>(config => { config.IncludeTable(db => db.Contacts, ApiMethodsToGenerate.Get, "addressBook"); }); }); } }
} MyContext.cs
using Microsoft.EntityFrameworkCore;
public class MyContext : DbContext { public MyContext(DbContextOptions<MyContext> options) : base(options) { }
public DbSet<Contact> Contacts => Set<Contact>(); public DbSet<Address> Addresses => Set<Address>();
}
public class Contact { public int Id { get; set; } public string Name { get; set; } public Address Address { get; set; } }
public class Address { public int Id { get; set; } public string Street { get; set; } public string City { get; set; } public string State { get; set; } public string Zip { get; set; } } Quick way to reproduce:
Create a .NET 5 ASP.NET Core Web API Change TargetFramework to net6.0 Update Swashbuckle.AspNetCore to 6.3.1 Add Fritz.InstantAPIs Follow steps in readme You will get this result:
Instead of:
when running from Program.cs approach:
using Fritz.InstantAPIs;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen();
builder.Services.AddSqlite<MyContext>("Data Source=contacts.db"); builder.Services.AddInstantAPIs();
var app = builder.Build();
// Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); }
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.MapInstantAPIs<MyContext>(config => { config.IncludeTable(db => db.Contacts, ApiMethodsToGenerate.Get, "addressBook"); });
app.Run(); — Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you are subscribed to this thread.
@csharpfritz I agree on that, but with Progam.cs and Startup.cs
approach the filtering (IncludeTable
and ExcludeTable
) isn't working.
In WebApplicationExtensions.cs
I've changed
public static IEndpointRouteBuilder MapInstantAPIs<D>(this IEndpointRouteBuilder app, Action<InstantAPIsConfigBuilder<D>> options = null) where D : DbContext
{
switch (app)
{
case IApplicationBuilder applicationBuilder:
AddOpenAPIConfiguration(app, options, applicationBuilder);
break;
case IEndpointRouteBuilder routeBuilder:
AddOpenAPIConfiguration(routeBuilder, options);
break;
}
// Get the tables on the DbContext
var dbTables = GetDbTablesForContext<D>();
var requestedTables = !Configuration.Tables.Any() ?
dbTables :
Configuration.Tables.Where(t => dbTables.Any(db => db.Name.Equals(t.Name, StringComparison.OrdinalIgnoreCase))).ToArray();
MapInstantAPIsUsingReflection<D>(app, requestedTables);
return app;
}
and added:
private static void AddOpenAPIConfiguration<D>(IEndpointRouteBuilder routeBuilder, Action<InstantAPIsConfigBuilder<D>> options) where D : DbContext
{
// Check if AddInstantAPIs was called by getting the service options and evaluate EnableSwagger property
var serviceOptions = routeBuilder.ServiceProvider.GetRequiredService<IOptions<InstantAPIsServiceOptions>>().Value;
if (serviceOptions == null || serviceOptions.EnableSwagger == null)
{
throw new ArgumentException("Call builder.Services.AddInstantAPIs(options) before MapInstantAPIs.");
}
//var webApp = (WebApplication)app;
if (serviceOptions.EnableSwagger == EnableSwagger.Always || (serviceOptions.EnableSwagger == EnableSwagger.DevelopmentOnly /*&& webApp.Environment.IsDevelopment()*/))
{
//routeBuilder.UseSwagger();
//routeBuilder.UseSwaggerUI();
}
var ctx = routeBuilder.ServiceProvider.CreateScope().ServiceProvider.GetService(typeof(D)) as D;
var builder = new InstantAPIsConfigBuilder<D>(ctx);
if (options != null)
{
options(builder);
Configuration = builder.Build();
}
}
Things that need to be added:
-checking if IsDevelopment()
-enabling SwaggerUI.
I'm not sure if InstantAPIs should enable and configure Swagger. It's up to the developer to setup it, besides that, it's enabled by default in new projects.
@verbedr @csharpfritz thoughts on this? I can create PR showing my changes. Not everyone (including me) can migrate Startup and Program to .NET 6 preferred approach.
As I mentioned before when creating new projects Swagger UI is enabled by default (unless we uncheck a checkbox during project creation in VS2022), so we should only detect if it is enabled and add the correct endpoints.
Ideally Swashbuckle dependency should be removed, because some may prefer and use NSwag (ref: https://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?view=aspnetcore-6.0) But this would require adding two more packages - one for Swagger and one for NSwag.