{"id":24402237,"url":"https://github.com/simcubeltd/simcube.spartan","last_synced_at":"2025-04-11T20:10:30.969Z","repository":{"id":61348273,"uuid":"522972494","full_name":"SimCubeLtd/SimCube.Spartan","owner":"SimCubeLtd","description":".Net 7 minimal apis with Mediatr, FluentValidation and usage of AsParametersAttribute for request handling","archived":false,"fork":false,"pushed_at":"2025-04-08T22:15:27.000Z","size":156,"stargazers_count":8,"open_issues_count":11,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-08T23:23:21.423Z","etag":null,"topics":["dotnet","minimal-api"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SimCubeLtd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-08-09T13:58:10.000Z","updated_at":"2024-03-25T00:10:15.000Z","dependencies_parsed_at":"2023-10-10T15:57:43.715Z","dependency_job_id":"4e40e1c8-0aed-45e1-89fb-0daba456781a","html_url":"https://github.com/SimCubeLtd/SimCube.Spartan","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimCubeLtd%2FSimCube.Spartan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimCubeLtd%2FSimCube.Spartan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimCubeLtd%2FSimCube.Spartan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SimCubeLtd%2FSimCube.Spartan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SimCubeLtd","download_url":"https://codeload.github.com/SimCubeLtd/SimCube.Spartan/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248473127,"owners_count":21109628,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dotnet","minimal-api"],"created_at":"2025-01-20T00:59:27.961Z","updated_at":"2025-04-11T20:10:30.948Z","avatar_url":"https://github.com/SimCubeLtd.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Spartan\n\nTestable Clean Minimal Apis, with Mediatr and Fluent Validation.\n\nIncluding Endpoint configuration, and IEndpointFilters! \n\nUtilising .Net 7's \u0026nbsp;[AsParametersAttribute](https://docs.microsoft.com/dotnet/api/microsoft.aspnetcore.http.asparametersattribute?view=aspnetcore-7.0)\n\n\u0026nbsp;\n\n[![codecov](https://codecov.io/gh/SimCubeLtd/SimCube.Spartan/branch/main/graph/badge.svg?token=YW1VVMY0UK)](https://codecov.io/gh/SimCubeLtd/SimCube.Spartan) [![main](https://github.com/SimCubeLtd/SimCube.Spartan/actions/workflows/main.yml/badge.svg)](https://github.com/SimCubeLtd/SimCube.Spartan/actions/workflows/main.yml) ![Nuget](https://img.shields.io/nuget/v/SimCube.Spartan?style=flat-square)\n\n## [Documentation](./docs/README.md)\n\n## Usage/Examples\n### See Examples of registration in the [DemoRegistrationMethods](./src/SimCube.Spartan.ExampleConsole/DemoRegistrationMethods.cs) class.\n\n### Using Attributes\n\n#### Application Startup\n\n```csharp\nbuilder.Services.AddSpartanInfrastructure(x =\u003e x.AsScoped());\n// Or pass through assemblies to scan for handlers\n// builder.Services.AddSpartanInfrastructure(x =\u003e x.AsScoped(), typeof(MyAssemblyOne), typeof(MyAssemblyTwo));\n```\n\n#### Request, Optional Validation and Handler\n\n```csharp\n[MediatedRequest(RequestType.MediatedGet, \"example/{name}/{age}\")]\npublic record GetExampleRequest(int Age, string Name) : IMediatedRequest;\n\npublic class GetExampleRequestValidator : AbstractValidator\u003cGetExampleRequest\u003e\n{\n    public GetExampleRequestValidator() =\u003e\n        RuleFor(x =\u003e x.Age)\n            .GreaterThan(18)\n            .WithMessage(\"You must be 18 to use this service.\");\n}\n\npublic class GetExampleRequestHandler : IRequestHandler\u003cGetExampleRequest, IResult\u003e\n{\n    public Task\u003cIResult\u003e Handle(GetExampleRequest request, CancellationToken cancellationToken) =\u003e\n        Task.FromResult(Results.Ok($\"The age was {request.Age} and the name was {request.Name}\"));\n}\n```\n\n### Directly Using Extensions\n\n#### Application Startup\n\nYou can enable or disable registration of FluentValidation on the AddSpartanInfrastructure extension method.\n\n```csharp\nvar builder = WebApplication.CreateBuilder(args);\nbuilder.Services.AddSpartanInfrastructure(x =\u003e x.AsScoped());\n// Or pass through assemblies to scan for handlers\n// builder.Services.AddSpartanInfrastructure(x =\u003e x.AsScoped(), typeof(MyAssemblyOne), typeof(MyAssemblyTwo));\n\n// You can also disable FluentValidation by registering with:\n//builder.Services.AddSpartanInfrastructure(x =\u003e x.AsScoped(), false);\n\nvar app = builder.Build();\n\napp.AddMediatedEndpointsFromAttributes();\napp.MediatedGet\u003cGetExampleRequest\u003e(\"example/{name}/{age}\", routeHandlerBuilder =\u003e routeHandlerBuilder.WithName(\"GetExample\"));\napp.MediatedPatch\u003cPatchExampleRequest\u003e(\"example/{name}/{age}\");\n\napp.Run();\n```\n\n#### Request, Optional Validation and Handler\n\n```csharp\npublic record GetExampleRequest(int Age, string Name) : IMediatedRequest;\n\npublic class GetExampleRequestValidator : AbstractValidator\u003cGetExampleRequest\u003e\n{\n    public GetExampleRequestValidator() =\u003e\n        RuleFor(x =\u003e x.Age)\n            .GreaterThan(18)\n            .WithMessage(\"You must be 18 to use this service.\");\n}\n\npublic class GetExampleRequestHandler : IRequestHandler\u003cGetExampleRequest, IResult\u003e\n{\n    public Task\u003cIResult\u003e Handle(GetExampleRequest request, CancellationToken cancellationToken) =\u003e\n        Task.FromResult(Results.Ok($\"The age was {request.Age} and the name was {request.Name}\"));\n}\n```\n\n#### Requests can also derive from the BaseMediatedRequest class, and override the ConfigureEndpoint method to chain route endpoint configuration such as Cache, WithName, Produces etc.\n#### You also have the ability to supply a collection of IEndpointFilters to chain to the endpoint, by overriding the 'EndpointFilters' property! \n\n```csharp\n[MediatedRequest(RequestType.MediatedDelete, \"example/{name}/{age}\")]\npublic class DeleteExampleRequest : BaseMediatedRequest\n{\n    public DeleteExampleRequest(int age, string name)\n    {\n        Age = age;\n        Name = name;\n    }\n\n    public int Age { get; }\n\n    public string Name { get; }\n    \n    // Here we override the EndpointFilters property, chaining the filter onto the request endpoint \n    // The are processed in the order that they appear in the list.\n    public override List\u003cIEndpointFilter\u003e EndpointFilters =\u003e new()\n    {\n        new ExampleNameIsPrometheusFilter()\n    };\n\n    // Here we override the invocation of the configuration of the route handler builder,\n    // Allowing you to add CacheOutput, manual filters, WithName, Produces etc.\n    public override Action\u003cRouteHandlerBuilder\u003e ConfigureEndpoint() =\u003e builder =\u003e\n        builder.AllowAnonymous()\n            .WithName(\"DeleteStuff\");\n}\n```\n\n### Stream Support\n\n#### Mediatr streams are also supported, which produce IAsyncEnumerables.\n\nWith attribute, also with endpoint route builder handler.\n\n```csharp\n[MediatedEndpoint(RequestType.MediatedGet, \"getstream\")]\npublic class GetStreamExampleRequest : BaseMediatedStream\u003cPerson\u003e\n{\n    /// \u003cinheritdoc /\u003e\n    public override Action\u003cRouteHandlerBuilder\u003e ConfigureEndpoint() =\u003e\n        builder =\u003e builder.AllowAnonymous();\n}\n```\n\nAs record\n```csharp\npublic record GetStreamExampleRequestTwo : IStreamRequest\u003cPerson\u003e;\n```\n\n#### Example Handler\n```csharp\nusing System.Runtime.CompilerServices;\nusing Bogus;\nusing Person = SimCube.Spartan.ExampleConsole.Models.Person;\n\nnamespace SimCube.Spartan.ExampleConsole.Handlers;\n\n/// \u003csummary\u003e\n/// Th example request handler.\n/// \u003c/summary\u003e\npublic class GetStreamExampleRequestHandler : IStreamRequestHandler\u003cGetStreamExampleRequest, Person\u003e\n{\n    private readonly Faker\u003cPerson\u003e _faker;\n\n    /// \u003csummary\u003e\n    /// Initializes a new instance of the \u003csee cref=\"GetStreamExampleRequestHandler\"/\u003e class.\n    /// \u003c/summary\u003e\n    public GetStreamExampleRequestHandler()\n    {\n        Randomizer.Seed = new(1701);\n\n        _faker = new Faker\u003cPerson\u003e()\n            .StrictMode(true)\n            .RuleFor(o =\u003e o.Name, f =\u003e f.Person.FullName)\n            .RuleFor(o =\u003e o.Age, f =\u003e f.Random.Number(18, 100))\n            .RuleFor(o =\u003e o.EmailAddress, f =\u003e f.Person.Email);\n    }\n\n    /// \u003cinheritdoc /\u003e\n    public async IAsyncEnumerable\u003cPerson\u003e Handle(\n        GetStreamExampleRequest request,\n        [EnumeratorCancellation] CancellationToken cancellationToken)\n    {\n        while (!cancellationToken.IsCancellationRequested)\n        {\n            await Task.Delay(200, cancellationToken);\n\n            yield return _faker.Generate();\n        }\n    }\n}\n\n```\n\n## Acknowledgements\n\n- [Mediatr](https://github.com/jbogard/MediatR)\n- [FluentValidation](https://docs.fluentvalidation.net/en/latest/)\n- [MIcrosoft](https://dotnet.microsoft.com/en-us/download/dotnet/7.0)\n- [Nick Chapsas](https://www.youtube.com/c/Elfocrash)\n\n\n## Authors\n\n- [@prom3theu5](https://www.github.com/prom3theu5)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimcubeltd%2Fsimcube.spartan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimcubeltd%2Fsimcube.spartan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimcubeltd%2Fsimcube.spartan/lists"}