Skip to content

Attributes

Every attribute in the framework, by the package it comes from.

Modules and application

Hardened.Shared.Runtime.Attributes

AttributeTargetPurpose
[HardenedModule]ClassMarks a partial class as a module entry point. Generates the module and a companion attribute named after it
[ConfigurationModel]ClassMarks a partial class as a configuration model. Generates the interface, the properties and the registration
[FromEnvironmentVariable(name)]FieldPopulates a configuration field from an environment variable
[HideConfigurationField]FieldExcludes a field from the generated interface
[ConfigurationProvider]ClassMarks a configuration provider

Every [HardenedModule] class also produces <Name>Attribute, which is how one module imports another. [AspNetCoreRuntime], [HardenedWebModule], [DynamoDbClientModule] and the rest are all generated this way. See Modules.

Service registration

DependencyModules.Runtime.Attributes, from DependencyModules

AttributeTargetPurpose
[SingletonService]ClassOne instance for the application
[ScopedService]ClassOne instance per scope
[TransientService]ClassA new instance per resolution
[DependencyModule]ClassThe DependencyModules module attribute [HardenedModule] builds on
[Decorator]ClassWraps a registered service
[Decorate]ClassApplies a decorator to a service you do not control
[Intercept]ClassRoutes members through generated interceptors
[IfEnvironment] / [IfNotEnvironment]ClassRegisters only in (or outside) named environments
[IfEnvironmentValue] / [IfNotEnvironmentValue]ClassRegisters based on an environment variable
[CrossWireService]ClassCross-wires a registration between modules

All take As to narrow the service type, and Using to choose the registration semantics.

Requests

Hardened.Requests.Abstract.Attributes

AttributeTargetPurpose
[HardenedFunction(name?)]MethodA function handler, addressed by name
[Handler]ClassMarks an implementation of a generated OpenAPI service interface
[FromBody]ParameterBinds from the request body
[FromServices]ParameterBinds from the container
[Output<T>]MethodHands the response to a view or other output instead of serialising it. Takes the response out of negotiation: unsupported Accept is a 406
[RawResponse(contentType?)]MethodCommits the response to a content type and writes the value unstructured. Defaults to text/plain. Read from code-first handlers only; on a [Handler] implementation it does nothing

ICustomBindingAttribute is the interface an attribute implements to bind a parameter itself. See Parameter binding.

Hardened.Requests.Abstract.Responses

AttributeTargetPurpose
[Throws<T>(status?)]MethodDeclares a thrown response for the document. The status comes from T's [HttpStatus], or from the argument
[AnswersStatus(status, typeof(body))]Class, interfaceOn a filter attribute: every operation carrying it publishes that status. How [RateLimit] publishes its 429

Hardened.Requests.Runtime.Filters

AttributeTargetPurpose
[Retry]Class, methodRe-runs the handler after a failure. Attempts (3), SleepTime (500 ms), TotalBudget (10 s), AllowNonIdempotent. Declines client errors, and non-idempotent verbs unless told otherwise
[Timeout]Class, method, assemblyBounds how long the operation may take. Milliseconds (30 s), Status (504), RetryAfterSeconds. The nearest declaration wins, and nothing is bounded until one is written

Hardened.Requests.Runtime.RateLimiting

AttributeTargetPurpose
[RateLimit]Class, methodCaps how often the operation may be called. PermitLimit (100), WindowSeconds (60). Publishes the 429

Hardened.Requests.Runtime.Caching

AttributeTargetPurpose
[CacheResponse<T>(values, …)]Class, methodStores the response and serves it without running the handler. Duration, Scope, Tags. AllowMultiple, and the parts compose into one key

Hardened.Requests.Caching.Memory

AttributeTargetPurpose
[HardenedMemoryResponseCache]ClassRegisters the in-process IResponseCacheStore. Nothing stores a response without a store

Authorization

Hardened.Requests.Runtime.Authorization

AttributeTargetPurpose
[AuthorizeGrants(grants)]Class, methodRequires every grant named. What a generator emits from a specification
[AuthorizeGrants<T>]Class, methodRequires every grant in the IGrantProvider T names. The typed spelling
[Authorize<TAuth>]Class, methodRequires an authenticated caller and declares the authentication scheme TAuth in the document. Which scheme established the caller is not checked at runtime
[Authorize<TAuth, TPolicy>]Class, methodThe same, and the policy's requirement as well. The only form that can express or
[AllowAnonymous]Class, methodMakes an operation public on purpose. Beats every requirement on the same handler, including a convention
[RequireAuthorization]Class, assemblyOn the module: a handler declaring nothing is denied rather than public, and reported as HAUTH001 at build

Every one of these stacks as and. Attributes on a method, attributes on its controller, attributes inherited from a base attribute and requirements added by an IAuthorizationConvention are all conjoined into the single Requirement the pipeline reads. Alternatives are expressible only inside a single policy.

[AuthorizeGrants] is not sealed. Deriving from it is one of the two ways to require grants without writing strings. IAuthorizeAttribute is the interface anything the pipeline honours implements, including attributes of your own, and it is what the HAUTH001 diagnostic tests.

See Authorization.

Web

Hardened.Web.Runtime.Attributes

AttributeTargetPurpose
[Get(path)]MethodA GET route
[Post(path)]MethodA POST route
[Put(path)]MethodA PUT route
[Delete(path)]MethodA DELETE route
[Patch(path)]MethodA PATCH route
[BasePath(path)]Class, assemblyPrefixes every route beneath it
[FromQueryString(name?)]ParameterBinds from the query string
[FromHeader(name?)]ParameterBinds from a request header
[CacheControl]MethodSets cache headers. MaxAge, Type. The header half of caching; [CacheResponse<T>] is the store half
[ServerSentEvents]MethodFrames an IAsyncEnumerable<T> as text/event-stream rather than NDJSON
[WebLibrary]ClassMarks a web library entry point
[Tag(name)]ClassThe OpenAPI tag this controller's operations group under. Defaults to the class name minus Controller
[Operation(id)]MethodThe operationId the handler publishes, which a generated client names its method after. Defaults to the method name in camelCase. Two handlers declaring one id is HRDOA004
[Server(url, description?)]Class, assemblyA base URL the generated document lists under servers
[CaseInsensitiveRoutes]ClassMatches this module's routes without regard to case
[RouteConstraint(name)]MethodDeclares a route constraint. static bool(ReadOnlySpan<char>)

Hardened.Web.Runtime.Compression

AttributeTargetPurpose
[Compress]Class, methodCompresses this operation's responses under the configured media-type rule. Favor picks a coding
[Compress<TPredicate>(args)]Class, methodThe same, decided by a predicate over the value the handler returned

Hardened.Web.Runtime.Conditional

AttributeTargetPurpose
[ConditionalGet]Class, methodAnswers a caller holding the response with a 304. GET handlers only

Both features are off until the application asks for them, and both can be turned on for every handler from the module instead:

AttributeTargetPurpose
[Enable<ResponseCompression>]ClassCompresses every response the media-type rule admits, for every client that accepts it
[Enable<ConditionalGet>]ClassAnswers a conditional GET at every GET handler
[Enable<RequestTimeouts>]ClassBounds every operation that declares no budget of its own, at 30 seconds
[RequestTimeouts(ms)]ClassThe same, with the number written. [Enable<T>] takes no arguments, so this is where one goes

Each stands down for a handler carrying its own [Compress] or [ConditionalGet], so explicit beats convention. A budget resolves the same way, over four levels: the operation, its class, the handler's assembly, then the entry point.

The verb attributes also declare SuccessStatus, the status a successful response answers with and the document publishes; unset means 200. The NullReturnStatus, ValidationErrorStatus and ErrorStatus properties they once carried are gone. See Returning null for what decides those statuses.

Templates

Hardened.Templates.RazorBlade

AttributeTargetPurpose
[Enable<RazorTemplates>]ClassGenerates a RazorBlade template base for a module
[TemplateBase(typeof(T<>))]ClassOn an engine's marker: the class a generated base derives from
[TemplateContentType(type)]ClassOn an engine's marker: what views on that base produce

[Enable<T>] itself lives in Hardened.Shared.Runtime.Attributes and is the framework's one name for every optional generated feature. It requires new(), and a marker that is also a DependencyModules module has its registrations applied too. A view is named on a handler with [Output<T>].

Console

Hardened.Commands.Attributes

AttributeTargetPurpose
[Command(command)]ClassA command. ParentCommand, Description
[Option]PropertyRenames an option or gives it help text
[FileOption]PropertyAn option whose value is a path
[ExcludeOption]PropertyA property that is not an option

Testing

Hardened.Shared.Testing.Attributes

AttributeTargetPurpose
[HardenedTest]MethodBoots the application and injects the parameters. From Hardened.Shared.Testing.xUnit or Hardened.Shared.Testing.NUnit
[HardenedTestEntryPoint(type)]Assembly, class, methodNames the application module under test
[Mock]ParameterSubstitutes a mock from the library the test project names and hands it to the test. DependencyModules.Testing.Attributes, brought in by Hardened.Shared.Testing
[assembly: NSubstituteSupport], [MoqSupport], [FakeItEasySupport]AssemblyNames the library [Mock] builds with. From DependencyModules.NSubstitute, .Moq and .FakeItEasy; without one, [Mock] fails with Mock library not found
[EnvironmentName(name)]Assembly, class, methodThe environment name for the test. Defaults to test
[EnvironmentValue(variable, value)]Assembly, class, methodSets an environment value for the test

Hardened.Web.Testing

AttributeTargetPurpose
[WebTesting]AssemblyInstalls ITestWebApp, the test credential source, and a typed client for every test parameter that names one
[Grants(params string[])]Parameter, method, class, assemblyThe grants a request is sent with, as X-Test-Grants. The narrowest wins
[Subject(name)]Parameter, method, class, assemblyWhich caller, as X-Test-Subject
[Anonymous]Parameter, method, class, assemblyNo credential, cancelling whatever a wider level declared
[PipelineHost]Assembly, class, methodRuns the test on the in-process pipeline where a wider level named a host

Hardened.Web.Kestrel.Testing and Hardened.Web.AspNetCore.Testing

AttributeTargetPurpose
[KestrelTesting]AssemblyRuns a test carrying [KestrelRuntime] on Kestrel, on a loopback port. See Test hosts
[AspNetCoreTesting(composition?)]AssemblyRuns a test carrying [AspNetCoreRuntime] inside a real WebApplication. The composition names an IAspNetCoreTestComposition that arranges the middleware

Hardened.Kiota.Testing and Hardened.Refit.Testing

AttributeTargetPurpose
[KiotaTesting]AssemblyMakes every Kiota client a test parameter built over the pipeline. See Typed clients
[RefitTesting]AssemblyThe same for a Refit interface

Triggers

Hardened.Functions.Runtime.Attributes. Provider-neutral: the handler names a source and the adapter package decides what serves it. See Triggers.

AttributeTargetPurpose
[Queue(name)]MethodMessages from a queue, one call per message. Routes as QUEUE /name
[Topic(name)]MethodMessages published to a topic, one call per notification
[Timer(name)]MethodA schedule firing. Usually takes no payload parameter
[Event(source, detailType)]MethodAn event from a message bus, bound from the event's detail
[Change(table)]MethodA row before and after an edit. Ordered and replayable
[Stream(name)]MethodRecords from a sharded stream, bound from the publisher's bytes. Ordered and replayable
[Blob(bucket)]MethodAn object in a store changing. Binds the notification's metadata, not the object

[HardenedFunction] is in the Requests table above and binds an adapter the same way: it is a direct invocation, the one shape that answers.

AWS

Hardened.Aws.Lambda.*. An application does not normally write an adapter module out — the trigger on a handler binds it. The exceptions are noted below.

AttributeNamespacePurpose
[ApiGatewayModule]Hardened.Aws.Lambda.ApiGatewayAPI Gateway payload format 2.0 onto the web pipeline. Written out by a web host, whose routes live in a library the generator cannot see
[InvokeModule]Hardened.Aws.Lambda.InvokeDirect invocation, for [HardenedFunction]
[SqsModule(ReportBatchItemFailures?)]Hardened.Aws.Lambda.SqsSQS, for [Queue]. Written out to turn on failure reporting, which has to match the event source mapping
[SnsModule]Hardened.Aws.Lambda.SnsSNS, for [Topic]
[EventBridgeModule]Hardened.Aws.Lambda.EventBridgeEventBridge, for [Timer] and [Event]
[DynamoDbStreamsModule(ReportBatchItemFailures?)]Hardened.Aws.Lambda.DynamoDbDynamoDB Streams, for [Change]
[KinesisModule(ReportBatchItemFailures?)]Hardened.Aws.Lambda.KinesisKinesis, for [Stream]
[S3Module]Hardened.Aws.Lambda.S3S3, for [Blob]
[NewImage] / [OldImage]Hardened.Aws.Lambda.DynamoDbBinds a change record's images as they arrived, type tags and all
[LambdaTesting]Hardened.Aws.Lambda.TestingAssembly. Delivers through the real AWS envelope and the invocation loop rather than straight into the pipeline
[LambdaWebTesting]Hardened.Aws.Lambda.TestingAssembly. API Gateway as a test host: a proxy event in, a proxy response out
[DynamoDbClientModule]Hardened.Aws.DynamoDbClientRegisters IDynamoDbClientProvider. A client, not an adapter — usable on any host
[LocalDynamoDb(Image?)]Hardened.Aws.DynamoDbClient.TestingPoints the client provider at DynamoDB Local in a container

Both were [DynamoDbModule] until 0.31.0, in two packages, so an application that read a table and handled its stream could not name either without qualifying it.

A Lambda response is always buffered. There is no streaming mode and no environment variable that selects one; see API Gateway.

Released under the MIT License.