{"id":17081476,"url":"https://github.com/benfoster/o9d-aspnet","last_synced_at":"2025-04-12T21:10:27.583Z","repository":{"id":65506004,"uuid":"580353130","full_name":"benfoster/o9d-aspnet","owner":"benfoster","description":"Extensions for ASP.NET Core","archived":false,"fork":false,"pushed_at":"2023-10-23T12:36:02.000Z","size":72,"stargazers_count":34,"open_issues_count":3,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-10T10:13:46.803Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/benfoster.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null}},"created_at":"2022-12-20T10:57:36.000Z","updated_at":"2024-10-01T14:45:32.000Z","dependencies_parsed_at":"2023-02-19T01:16:06.130Z","dependency_job_id":null,"html_url":"https://github.com/benfoster/o9d-aspnet","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benfoster%2Fo9d-aspnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benfoster%2Fo9d-aspnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benfoster%2Fo9d-aspnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/benfoster%2Fo9d-aspnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/benfoster","download_url":"https://codeload.github.com/benfoster/o9d-aspnet/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248631676,"owners_count":21136562,"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":[],"created_at":"2024-10-14T12:53:06.647Z","updated_at":"2025-04-12T21:10:27.557Z","avatar_url":"https://github.com/benfoster.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ASP.NET Extensions\n\nOpinionated extensions for ASP.NET Core.\n\n## O9d.AspNet.FluentValidation\n\nThis package includes a validation filter that can be used with ASP.NET Minimal APIs to automatically validate incoming requests using [FluentValidation](https://github.com/FluentValidation/FluentValidation).\n\nFor more information on the motivation behind this filter, see [this blog post](https://benfoster.io/blog/minimal-api-validation-endpoint-filters/).\n\n### Installation\n\nInstall from [Nuget](https://www.nuget.org/packages/O9d.AspNet.FluentValidation).\n\n```\ndotnet add package O9d.AspNet.FluentValidation\n```\n\n### Usage\n\nRather than attaching the filter to every endpoint, create a group under which your endpoints are created and add the validation filter:\n\n```c#\nvar group = app.MapGroup(\"/\")\n    .WithValidationFilter();\n```\n\nAutomatic validation is opt-in and defaults to a strategy that uses the provided `[Validate]` attribute:\n\n```c#\ngroup.MapPost(\"/things\", ([Validate] DoSomething _) =\u003e Results.Ok());\n\npublic class DoSomething\n{\n    public string? Name { get; set; }\n\n    public class Validator : AbstractValidator\u003cDoSomething\u003e\n    {\n        public Validator()\n        {\n            RuleFor(x =\u003e x.Name).NotEmpty();\n        }\n    }\n}\n```\n\nIf the request parameter is not valid, by default, a `ValidationProblem` is returned with the HTTP status code `422 - Unprocessable Entity` \n\n```json\n{\n  \"type\": \"https://tools.ietf.org/html/rfc4918#section-11.2\",\n  \"title\": \"One or more validation errors occurred.\",\n  \"status\": 422,\n  \"errors\": {\n    \"Name\": [\"'Name' must not be empty.\"]\n  }\n}\n```\n\n### Validation Strategies\n\nA validation strategy determines how whether a parameter type is validateable. The default behaviour is to use the `[Validate]` attribute which can be applied to the parameter (as above) or directly to the class. The library also includes support for the following:\n\n#### Metadata-based strategy\n\nYou can choose to decorate the endpoints you wish to validate explicitly using metadata:\n\n```c#\nvar group = app.MapGroup(\"/\")\n    .WithValidationFilter(options =\u003e options.ShouldValidate = ValidationStrategies.HasValidationMetadata)\n    .RequireValidation(typeof(DoSomething));\n\ngroup.MapPost(\"/things\", (DoSomething _) =\u003e Results.Ok());\n```\n\nYou need to specify the types that should be enlisted for validation so it generally only makes sense to do this at a group level.\n\n#### Type convention driven strategy\n\nMy preferred approach is to define a marker interface e.g. `IValidateable` and then decorate my input parameters with this:\n\n```c#\nvar group = app.MapGroup(\"/\")\n    .WithValidationFilter(options =\u003e options.ShouldValidate = ValidationStrategies.TypeImplements\u003cIValidateable\u003e());\n\ngroup.MapPost(\"/things\", (DoSomething _) =\u003e Results.Ok());\n```\n\n#### Custom strategy\n\nIf none of the built-in strategies work for you, you can create your own implementation of the `ValidationStrategy` delegate:\n\n```c#\npublic delegate bool ValidationStrategy(ParameterInfo parameterInfo, IList\u003cobject\u003e endpointMetadata);\n```\n\n### Overriding the validation result\n\nYou can override the default validation result by providing your own factory, which takes the FluentValidation `ValidationResult` as an input:\n\n```c#\nvar group = app.MapGroup(\"/\")\n    .WithValidationFilter(options =\u003e options.InvalidResultFactory = validationResult =\u003e Results.BadRequest());\n\ngroup.MapPost(\"/things\", ([Validate] DoSomething _) =\u003e Results.Ok());\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenfoster%2Fo9d-aspnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbenfoster%2Fo9d-aspnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbenfoster%2Fo9d-aspnet/lists"}