Code
using Gestalt.ASPNet.ExtensionMethods;
using Gestalt.ASPNet.MVC.BaseClasses;
using Gestalt.ASPNet.MVC.Interfaces;
using Gestalt.ASPNet.RazorPages.BaseClasses;
using Gestalt.ASPNet.RazorPages.Interfaces;
using Gestalt.ASPNet.SignalR.Interfaces;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Diagnostics.Metrics;
namespace Gestalt.Example
{
/// <summary>
/// In this example, we are creating a basic web application using Gestalt. We are using the
/// default configuration settings and showing examples of building your own modules.
/// </summary>
public static class Program
{
/// <summary>
/// The main entry point for the application. This is where the application is configured
/// and run.
/// </summary>
/// <param name="args">The command line arguments</param>
public static void Main(string[] args)
{
// Create a new web application builder as normal.
WebApplicationBuilder Builder = WebApplication.CreateBuilder(args);
// Call the UseGestalt extension method and the Gestalt library will find your modules,
// use them to configure your application, and build your WebApplication object. In this
// example, we have added the Gestalt.ASPNet.MVC, Gestalt.ASPNet.SignalR, and
// Gestalt.ASPNet.RazorPages libraries to the project. As such, the UseGestalt extesion
// will automatically add routing, call AddControllersWithViews, AddRazorPages, and
// AddSignalR for us. It will then allow the modules to configure the parts of the
// application that they are responsible for.
WebApplication? App = Builder.UseGestalt(args);
// If the application is null, then the Gestalt library was unable to build the
// application. Normally an exception would be thrown but if the WebApplicationBuilder
// is null, then a null WebApplication object is returned.
if (App is null)
return;
// Note that you can still configure the application as normal. Gestalt is meant to help
// you build your application in a modular way but you can still configure it as you see
// fit. This also applies above to the WebApplicationBuilder. You can always configure
// it as you see fit prior to calling UseGestalt.
_ = App.Map("/Custom", app =>
{
_ = app.UseRouting();
_ = app.UseEndpoints(endpoints =>
{
_ = endpoints.MapGet("/", async context => await context.Response.WriteAsync("Hello World!"));
});
});
// Run the application as normal.
App.Run();
}
}
/// <summary>
/// This is an example of a basic module that configures the application with the usual default
/// settings when creating a new web application. It implements the MvcModuleBaseClass which
/// simplifies the process of creating a module that needs to modify MVC settings. However, you
/// can implement the IMvcModule interface directly if you prefer.
/// </summary>
public class BasicModule : MvcModuleBaseClass<BasicModule>
{
/// <summary>
/// This is called to configure the IApplicationBuilder object. Since this is an MVC app,
/// that would be the WebApplication object.
/// </summary>
/// <param name="applicationBuilder">The application builder object.</param>
/// <param name="configuration">The configuration object.</param>
/// <param name="environment">The host environment object.</param>
/// <returns>The application builder object should be returned.</returns>
public override IApplicationBuilder? ConfigureApplication(IApplicationBuilder? applicationBuilder, IConfiguration? configuration, IHostEnvironment? environment)
{
if (applicationBuilder is null)
return applicationBuilder;
// Configure the HTTP request pipeline.
if (environment?.IsDevelopment() == false)
{
// This is the default exception handler for the application when in production.
_ = applicationBuilder.UseExceptionHandler("/Home/Error");
// We will add a strict transport security header to the response.
_ = applicationBuilder.UseHsts();
}
// This will redirect HTTP requests to HTTPS.
_ = applicationBuilder.UseHttpsRedirection();
// And let's serve static files.
_ = applicationBuilder.UseStaticFiles();
// We will also add authorization to the application.
_ = applicationBuilder.UseAuthorization();
// And lastly, we will return the application builder.
return applicationBuilder;
}
/// <summary>
/// This is called to configure the MVC options. We will just return the options object as is.
/// </summary>
/// <param name="mVCBuilder">The MVC builder object.</param>
/// <param name="configuration">The configuration object.</param>
/// <param name="environment">The host environment object.</param>
/// <returns>The MVC builder object.</returns>
public override IMvcBuilder? ConfigureMVC(IMvcBuilder? mVCBuilder, IConfiguration? configuration, IHostEnvironment? environment) => mVCBuilder;
/// <summary>
/// This is called to configure our endpoint routes. For our example, we will just use the
/// default route.
/// </summary>
/// <param name="endpoints">The endpoint route builder.</param>
/// <param name="configuration">The configuration object.</param>
/// <param name="environment">The host environment object.</param>
/// <returns>The endpoint route builder.</returns>
public override IEndpointRouteBuilder? ConfigureRoutes(IEndpointRouteBuilder? endpoints, IConfiguration? configuration, IHostEnvironment? environment)
{
if (endpoints is null)
return endpoints;
// Map the default route.
_ = endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
return endpoints;
}
}
/// <summary>
/// <para>
/// All modules implement the IApplicationModule interface. As such, they all have certain
/// methods that they must implement and can be used to configure the application. Module
/// interfaces then get more and more specific to the application type. For example,
/// IAspNetModule adds application, route, and web app configuration methods. IMvcModule is used
/// to configure MVC settings, like the BasicModule example.
/// </para>
/// <para>
/// This example though implements the IRazorPagesModule interface. This is used to configure
/// Razor Pages settings.
/// </para>
/// </summary>
public class BasicRazorPagesModule : RazorPagesModuleBaseClass<BasicRazorPagesModule>
{
/// <summary>
/// Sometimes modules need to be loaded in a specific order. By default, the order number is
/// 100. Lower numbers are loaded first, as such this module will be loaded prior to the BasicModule.
/// </summary>
public override int Order => 20;
/// <summary>
/// This method is called to configure Razor Pages settings.
/// </summary>
/// <param name="mVCBuilder">The MVC builder object.</param>
/// <param name="configuration">The configuration object.</param>
/// <param name="environment">The host environment object.</param>
/// <returns>The configured MVC builder object.</returns>
public override IMvcBuilder? ConfigureRazorPages(IMvcBuilder? mVCBuilder, IConfiguration? configuration, IHostEnvironment? environment) => mVCBuilder;
}
/// <summary>
/// The other examples use the *BaseClass classes to simplify the process of creating a module.
/// However, you can implement the interfaces directly if you prefer or need to due to the
/// module that you are trying to build. Note though, that I would recommend breaking down your
/// modules into smaller parts if you find yourself needing to implement multiple interfaces.
/// </summary>
public class MoreAdvancedModule : IMvcModule, ISignalRModule, IRazorPagesModule
{
/// <summary>
/// The category of the module. This is used to group modules together. When using the
/// *BaseClass classes, this is the last part of the namespace that the module is in by default.
/// </summary>
public string Category { get; } = "Example Category";
/// <summary>
/// The content path of the module. Gestalt does not directly use this, but it is available
/// for your use. For adding static web content, you would still configure the
/// StaticWebAssetBasePath in the csproj file. When using the *BaseClass classes, this
/// defaults to "wwwroot/Content/{Category}/{Name}".
/// </summary>
public string ContentPath { get; } = "MyContentPath";
/// <summary>
/// The ID of the module. This is used to identify the module and determine if there are any
/// conflicts. This defaults to the module's type name.
/// </summary>
public string ID { get; } = "ExampleID";
/// <summary>
/// The last modified date of the module. This is used to determine if the module has been
/// updated. When using the *BaseClass classes, this is the assembly last modified date.
/// </summary>
public DateTime LastModified { get; } = DateTime.Now;
/// <summary>
/// The display name of the module. By default this would be the name of the module class.
/// </summary>
public string Name { get; } = "Example";
/// <summary>
/// The order that the module is loaded in. Lower numbers are loaded first. By default, this
/// is 100.
/// </summary>
public int Order { get; } = 0;
/// <summary>
/// The tags of the module. This is used to group modules together but is not used by
/// Gestalt directly.
/// </summary>
public string?[] Tags { get; } = new string?[] { "Example" };
/// <summary>
/// The version of the module. By default, this is the assembly version number.
/// </summary>
public string Version { get; } = "1.0.0";
/// <summary>
/// This is called to configure the application.
/// </summary>
/// <param name="applicationBuilder">The application builder.</param>
/// <param name="configuration">The configuration.</param>
/// <param name="environment">The host environment.</param>
/// <returns>The application builder.</returns>
public IApplicationBuilder? ConfigureApplication(IApplicationBuilder? applicationBuilder, IConfiguration? configuration, IHostEnvironment? environment) => applicationBuilder;
/// <summary>
/// This is called to configure the configuration settings.
/// </summary>
/// <param name="configuration">The configuration builder.</param>
/// <param name="environment">The host environment.</param>
/// <param name="args">The arguments.</param>
/// <returns>The configuration builder.</returns>
public IConfigurationBuilder? ConfigureConfigurationSettings(IConfigurationBuilder? configuration, IHostEnvironment? environment, string?[]? args) => configuration;
/// <summary>
/// This is called to configure the host settings.
/// </summary>
/// <param name="host">The host builder.</param>
/// <param name="configuration">The configuration.</param>
/// <param name="environment">The host environment.</param>
/// <returns>The host builder.</returns>
public IHostBuilder? ConfigureHostSettings(IHostBuilder? host, IConfiguration? configuration, IHostEnvironment? environment) => host;
/// <summary>
/// This is called to configure the logging settings.
/// </summary>
/// <param name="logging">The logging builder.</param>
/// <param name="configuration">The configuration.</param>
/// <param name="environment">The host environment.</param>
/// <returns>The logging builder.</returns>
public ILoggingBuilder? ConfigureLoggingSettings(ILoggingBuilder? logging, IConfiguration? configuration, IHostEnvironment? environment) => logging;
/// <summary>
/// This is called to configure the metrics settings. Note that this is only called if the
/// metrics builder is available. In .Net 6, the metrics builder is not available by default
/// and thus is not called. However, in .Net 8, it is available. The module can still be
/// used in .Net 6 or 8, but the metrics builder will not be available in .Net 6.
/// </summary>
/// <param name="metrics">The metrics builder.</param>
/// <param name="configuration">The configuration.</param>
/// <param name="environment">The host environment.</param>
/// <returns>The metrics builder.</returns>
public IMetricsBuilder? ConfigureMetrics(IMetricsBuilder? metrics, IConfiguration? configuration, IHostEnvironment? environment) => metrics;
/// <summary>
/// This is called to configure the MVC settings.
/// </summary>
/// <param name="mVCBuilder">The MVC builder.</param>
/// <param name="configuration">The configuration.</param>
/// <param name="environment">The host environment.</param>
/// <returns>The MVC builder.</returns>
public IMvcBuilder? ConfigureMVC(IMvcBuilder? mVCBuilder, IConfiguration? configuration, IHostEnvironment? environment) => mVCBuilder;
/// <summary>
/// This is called to configure the Razor Pages settings.
/// </summary>
/// <param name="mVCBuilder">The MVC builder.</param>
/// <param name="configuration">The configuration.</param>
/// <param name="environment">The host environment.</param>
/// <returns>The MVC builder.</returns>
public IMvcBuilder? ConfigureRazorPages(IMvcBuilder? mVCBuilder, IConfiguration? configuration, IHostEnvironment? environment) => mVCBuilder;
/// <summary>
/// This is called to configure endpoint routes.
/// </summary>
/// <param name="endpoints">The endpoint route builder.</param>
/// <param name="configuration">The configuration.</param>
/// <param name="environment">The host environment.</param>
/// <returns>The endpoint route builder.</returns>
public IEndpointRouteBuilder? ConfigureRoutes(IEndpointRouteBuilder endpoints, IConfiguration? configuration, IHostEnvironment? environment) => endpoints;
/// <summary>
/// This is called to configure the services.
/// </summary>
/// <param name="services">The service collection.</param>
/// <param name="configuration">The configuration.</param>
/// <param name="environment">The host environment.</param>
/// <returns>The service collection.</returns>
public IServiceCollection? ConfigureServices(IServiceCollection? services, IConfiguration? configuration, IHostEnvironment? environment) => services;
/// <summary>
/// This is called to configure SignalR settings.
/// </summary>
/// <param name="builder">The SignalR server builder.</param>
/// <param name="configuration">The configuration.</param>
/// <param name="environment">The host environment.</param>
/// <returns>The SignalR server builder.</returns>
public ISignalRServerBuilder? ConfigureSignalR(ISignalRServerBuilder? builder, IConfiguration? configuration, IHostEnvironment? environment) => builder;
/// <summary>
/// This is called to configure the web host settings.
/// </summary>
/// <param name="webHost">The web host builder.</param>
/// <param name="configuration">The configuration.</param>
/// <param name="environment">The host environment.</param>
/// <returns>The web host builder.</returns>
public IWebHostBuilder? ConfigureWebHostSettings(IWebHostBuilder? webHost, IConfiguration? configuration, IHostEnvironment? environment) => webHost;
/// <summary>
/// This is called when the application is started. Any code that needs to be run when the
/// application starts can be placed here.
/// </summary>
public void OnStarted()
{ }
/// <summary>
/// This is called when the application is stopped. Any code that needs to be run when the
/// application stops can be placed here.
/// </summary>
public void OnStopped()
{ }
/// <summary>
/// This is called when the application is stopping. Any code that needs to be run when the
/// application is stopping can be placed here.
/// </summary>
public void OnStopping()
{ }
/// <summary>
/// This is called to configure the options for razor pages. Note that you can always skip
/// this method and instead configure the options in the ConfigureServices method. It's more
/// of a convenience method than necessary.
/// </summary>
/// <param name="options">The razor pages options object.</param>
/// <param name="configuration">The configuration</param>
/// <param name="environment">The host environment.</param>
/// <returns>The razor pages options object.</returns>
public RazorPagesOptions? Options(RazorPagesOptions? options, IConfiguration? configuration, IHostEnvironment? environment) => options;
/// <summary>
/// This is called to configure the options for SignalR Note that you can always skip this
/// method and instead configure the options in the ConfigureServices method. It's more of a
/// convenience method than necessary.
/// </summary>
/// <param name="options">The SignalR hub options object.</param>
/// <param name="configuration">The configuration</param>
/// <param name="environment">The host environment.</param>
/// <returns>The SignalR hub options object.</returns>
public HubOptions? Options(HubOptions? options, IConfiguration? configuration, IHostEnvironment? environment) => options;
/// <summary>
/// This is called to configure the options for MVC. Note that you can always skip this
/// method and instead configure the options in the ConfigureServices method. It's more of a
/// convenience method than necessary.
/// </summary>
/// <param name="options">The MVC options object.</param>
/// <param name="configuration">The configuration</param>
/// <param name="environment">The host environment.</param>
/// <returns>The MVC options object.</returns>
public MvcOptions? Options(MvcOptions? options, IConfiguration? configuration, IHostEnvironment? environment) => options;
}
}