Replace IResultMapper with ResultMapper base class - #94
Merged
Conversation
- Replace IResultMapper interface with ResultMapper base class with virtual methods: MapException, GetStatusCode, MapValidationFailures, MapCancellation, MapSuccess<T> - Add ResultMapper.Create() factory for one-off lambda customizations - Change default validation status code from 400 to 422 - Change default exception handling from throw to ProblemDetails 500 - Add chainable IResult decorators: WithHeader, WithNoContent - Add DecoratedResult internal class for response customization - Rename selector parameter to contentSelector - Null success results now return 404 NotFound instead of Ok(null) - Update docs and tests Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- DecoratedResult now flattens decorator chains so WithHeader can be called any number of times without nesting - WithNoContent preserves all previously chained headers, not just the last one - GetPriorityStatusCode is now public virtual and respects custom status codes from overridden GetStatusCode (uses Min for unknown codes) - Non-generic ToResult now delegates to virtual MapSuccess() for consistency with generic overloads - Added 68 AspNetCore tests covering all code paths Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…erload Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bfarmer67
added a commit
that referenced
this pull request
Mar 19, 2026
* chore: format code with dotnet format * chore(nbgv): set version via CI: 2.7.0 * feat: add IResultMapper, IPipelineMiddlewareProvider, and PipelineFactory.Create Issue 1 - Smarter ToResult: - Add IResultMapper interface for DI-injectable cross-cutting result mapping - Add resultMapper lambda overloads to ToResult for inline error/success handling - Both generic CommandResult<T> and non-generic CommandResult variants supported Issue 2 - Injectable pipeline middleware: - Add IPipelineMiddlewareProvider interface with Hooks and Wraps properties - Add UseHooks/UseWraps builder extensions for explicit middleware application - Add PipelineFactory.Create convenience method that applies hooks after Start and wraps before Build automatically - Add WithMiddlewareProvider to PipelineContextFactoryFixture for test support - Add DefaultMiddlewareProvider static property for test-wide defaults * docs: add middleware provider and result mapper examples to README, index, and validation docs * chore: format code with dotnet format * feat: add PipelineFactory.Create overload and documentation - Add a convenience `Create` method for building pipelines using a configuration function. - Add XML documentation to `Start` and `Create` methods to clarify their usage and monadic nature. - Add null validation for the middleware provider in the existing `Create` overload. * fix: add null and empty guards for Hooks and Wraps in MiddlewareProviderBuilder * Inject pipeline middleware (#90) * feat: add IResultMapper, IPipelineMiddlewareProvider, and PipelineFactory.Create Issue 1 - Smarter ToResult: - Add IResultMapper interface for DI-injectable cross-cutting result mapping - Add resultMapper lambda overloads to ToResult for inline error/success handling - Both generic CommandResult<T> and non-generic CommandResult variants supported Issue 2 - Injectable pipeline middleware: - Add IPipelineMiddlewareProvider interface with Hooks and Wraps properties - Add UseHooks/UseWraps builder extensions for explicit middleware application - Add PipelineFactory.Create convenience method that applies hooks after Start and wraps before Build automatically - Add WithMiddlewareProvider to PipelineContextFactoryFixture for test support - Add DefaultMiddlewareProvider static property for test-wide defaults * docs: add middleware provider and result mapper examples to README, index, and validation docs * feat: add PipelineFactory.Create overload and documentation - Add a convenience `Create` method for building pipelines using a configuration function. - Add XML documentation to `Start` and `Create` methods to clarify their usage and monadic nature. - Add null validation for the middleware provider in the existing `Create` overload. * fix: add null and empty guards for Hooks and Wraps in MiddlewareProviderBuilder * chore(nbgv): set version via CI: 2.8.0 * test: update Create test to expect ArgumentNullException for null provider Update the PipelineFactory.Create test to reflect recent changes that added null validation for the middleware provider. * chore: format code with dotnet format * chore(nbgv): set version via CI: 2.8.1 * fix: allow null provider in PipelineFactory.Create for consistency with UseHooks/UseWraps Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore(nbgv): set version via CI: 2.8.2 * Replace IResultMapper with ResultMapper base class (#94) * feat: replace IResultMapper with ResultMapper base class - Replace IResultMapper interface with ResultMapper base class with virtual methods: MapException, GetStatusCode, MapValidationFailures, MapCancellation, MapSuccess<T> - Add ResultMapper.Create() factory for one-off lambda customizations - Change default validation status code from 400 to 422 - Change default exception handling from throw to ProblemDetails 500 - Add chainable IResult decorators: WithHeader, WithNoContent - Add DecoratedResult internal class for response customization - Rename selector parameter to contentSelector - Null success results now return 404 NotFound instead of Ok(null) - Update docs and tests * chore: format code with dotnet format * fix: production-grade quality improvements to ResultMapper - DecoratedResult now flattens decorator chains so WithHeader can be called any number of times without nesting - WithNoContent preserves all previously chained headers, not just the last one - GetPriorityStatusCode is now public virtual and respects custom status codes from overridden GetStatusCode (uses Min for unknown codes) - Non-generic ToResult now delegates to virtual MapSuccess() for consistency with generic overloads - Added 68 AspNetCore tests covering all code paths * chore: format code with dotnet format * refactor: remove unnecessary class constraint from contentSelector overload * chore(nbgv): set version via CI: 2.9.0
bfarmer67
added a commit
that referenced
this pull request
Mar 19, 2026
* chore: format code with dotnet format * chore(nbgv): set version via CI: 2.7.0 * feat: add IResultMapper, IPipelineMiddlewareProvider, and PipelineFactory.Create Issue 1 - Smarter ToResult: - Add IResultMapper interface for DI-injectable cross-cutting result mapping - Add resultMapper lambda overloads to ToResult for inline error/success handling - Both generic CommandResult<T> and non-generic CommandResult variants supported Issue 2 - Injectable pipeline middleware: - Add IPipelineMiddlewareProvider interface with Hooks and Wraps properties - Add UseHooks/UseWraps builder extensions for explicit middleware application - Add PipelineFactory.Create convenience method that applies hooks after Start and wraps before Build automatically - Add WithMiddlewareProvider to PipelineContextFactoryFixture for test support - Add DefaultMiddlewareProvider static property for test-wide defaults Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add middleware provider and result mapper examples to README, index, and validation docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: format code with dotnet format * feat: add PipelineFactory.Create overload and documentation - Add a convenience `Create` method for building pipelines using a configuration function. - Add XML documentation to `Start` and `Create` methods to clarify their usage and monadic nature. - Add null validation for the middleware provider in the existing `Create` overload. * fix: add null and empty guards for Hooks and Wraps in MiddlewareProviderBuilder Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Inject pipeline middleware (#90) * feat: add IResultMapper, IPipelineMiddlewareProvider, and PipelineFactory.Create Issue 1 - Smarter ToResult: - Add IResultMapper interface for DI-injectable cross-cutting result mapping - Add resultMapper lambda overloads to ToResult for inline error/success handling - Both generic CommandResult<T> and non-generic CommandResult variants supported Issue 2 - Injectable pipeline middleware: - Add IPipelineMiddlewareProvider interface with Hooks and Wraps properties - Add UseHooks/UseWraps builder extensions for explicit middleware application - Add PipelineFactory.Create convenience method that applies hooks after Start and wraps before Build automatically - Add WithMiddlewareProvider to PipelineContextFactoryFixture for test support - Add DefaultMiddlewareProvider static property for test-wide defaults Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add middleware provider and result mapper examples to README, index, and validation docs * feat: add PipelineFactory.Create overload and documentation - Add a convenience `Create` method for building pipelines using a configuration function. - Add XML documentation to `Start` and `Create` methods to clarify their usage and monadic nature. - Add null validation for the middleware provider in the existing `Create` overload. * fix: add null and empty guards for Hooks and Wraps in MiddlewareProviderBuilder * chore(nbgv): set version via CI: 2.8.0 * test: update Create test to expect ArgumentNullException for null provider Update the PipelineFactory.Create test to reflect recent changes that added null validation for the middleware provider. * chore: format code with dotnet format * chore(nbgv): set version via CI: 2.8.1 * fix: allow null provider in PipelineFactory.Create for consistency with UseHooks/UseWraps Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore(nbgv): set version via CI: 2.8.2 * Replace IResultMapper with ResultMapper base class (#94) * feat: replace IResultMapper with ResultMapper base class - Replace IResultMapper interface with ResultMapper base class with virtual methods: MapException, GetStatusCode, MapValidationFailures, MapCancellation, MapSuccess<T> - Add ResultMapper.Create() factory for one-off lambda customizations - Change default validation status code from 400 to 422 - Change default exception handling from throw to ProblemDetails 500 - Add chainable IResult decorators: WithHeader, WithNoContent - Add DecoratedResult internal class for response customization - Rename selector parameter to contentSelector - Null success results now return 404 NotFound instead of Ok(null) - Update docs and tests * chore: format code with dotnet format * fix: production-grade quality improvements to ResultMapper - DecoratedResult now flattens decorator chains so WithHeader can be called any number of times without nesting - WithNoContent preserves all previously chained headers, not just the last one - GetPriorityStatusCode is now public virtual and respects custom status codes from overridden GetStatusCode (uses Min for unknown codes) - Non-generic ToResult now delegates to virtual MapSuccess() for consistency with generic overloads - Added 68 AspNetCore tests covering all code paths * chore: format code with dotnet format * refactor: remove unnecessary class constraint from contentSelector overload * chore(nbgv): set version via CI: 2.9.0 * chore(nbgv): set version via CI: 2.9.1 --------- Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
bfarmer67
added a commit
that referenced
this pull request
Apr 12, 2026
* chore: format code with dotnet format * chore(nbgv): set version via CI: 2.7.0 * feat: add IResultMapper, IPipelineMiddlewareProvider, and PipelineFactory.Create Issue 1 - Smarter ToResult: - Add IResultMapper interface for DI-injectable cross-cutting result mapping - Add resultMapper lambda overloads to ToResult for inline error/success handling - Both generic CommandResult<T> and non-generic CommandResult variants supported Issue 2 - Injectable pipeline middleware: - Add IPipelineMiddlewareProvider interface with Hooks and Wraps properties - Add UseHooks/UseWraps builder extensions for explicit middleware application - Add PipelineFactory.Create convenience method that applies hooks after Start and wraps before Build automatically - Add WithMiddlewareProvider to PipelineContextFactoryFixture for test support - Add DefaultMiddlewareProvider static property for test-wide defaults Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add middleware provider and result mapper examples to README, index, and validation docs Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * chore: format code with dotnet format * feat: add PipelineFactory.Create overload and documentation - Add a convenience `Create` method for building pipelines using a configuration function. - Add XML documentation to `Start` and `Create` methods to clarify their usage and monadic nature. - Add null validation for the middleware provider in the existing `Create` overload. * fix: add null and empty guards for Hooks and Wraps in MiddlewareProviderBuilder Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Inject pipeline middleware (#90) * feat: add IResultMapper, IPipelineMiddlewareProvider, and PipelineFactory.Create Issue 1 - Smarter ToResult: - Add IResultMapper interface for DI-injectable cross-cutting result mapping - Add resultMapper lambda overloads to ToResult for inline error/success handling - Both generic CommandResult<T> and non-generic CommandResult variants supported Issue 2 - Injectable pipeline middleware: - Add IPipelineMiddlewareProvider interface with Hooks and Wraps properties - Add UseHooks/UseWraps builder extensions for explicit middleware application - Add PipelineFactory.Create convenience method that applies hooks after Start and wraps before Build automatically - Add WithMiddlewareProvider to PipelineContextFactoryFixture for test support - Add DefaultMiddlewareProvider static property for test-wide defaults Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add middleware provider and result mapper examples to README, index, and validation docs * feat: add PipelineFactory.Create overload and documentation - Add a convenience `Create` method for building pipelines using a configuration function. - Add XML documentation to `Start` and `Create` methods to clarify their usage and monadic nature. - Add null validation for the middleware provider in the existing `Create` overload. * fix: add null and empty guards for Hooks and Wraps in MiddlewareProviderBuilder * chore(nbgv): set version via CI: 2.8.0 * test: update Create test to expect ArgumentNullException for null provider Update the PipelineFactory.Create test to reflect recent changes that added null validation for the middleware provider. * chore: format code with dotnet format * chore(nbgv): set version via CI: 2.8.1 * fix: allow null provider in PipelineFactory.Create for consistency with UseHooks/UseWraps Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore(nbgv): set version via CI: 2.8.2 * Replace IResultMapper with ResultMapper base class (#94) * feat: replace IResultMapper with ResultMapper base class - Replace IResultMapper interface with ResultMapper base class with virtual methods: MapException, GetStatusCode, MapValidationFailures, MapCancellation, MapSuccess<T> - Add ResultMapper.Create() factory for one-off lambda customizations - Change default validation status code from 400 to 422 - Change default exception handling from throw to ProblemDetails 500 - Add chainable IResult decorators: WithHeader, WithNoContent - Add DecoratedResult internal class for response customization - Rename selector parameter to contentSelector - Null success results now return 404 NotFound instead of Ok(null) - Update docs and tests * chore: format code with dotnet format * fix: production-grade quality improvements to ResultMapper - DecoratedResult now flattens decorator chains so WithHeader can be called any number of times without nesting - WithNoContent preserves all previously chained headers, not just the last one - GetPriorityStatusCode is now public virtual and respects custom status codes from overridden GetStatusCode (uses Min for unknown codes) - Non-generic ToResult now delegates to virtual MapSuccess() for consistency with generic overloads - Added 68 AspNetCore tests covering all code paths * chore: format code with dotnet format * refactor: remove unnecessary class constraint from contentSelector overload * chore(nbgv): set version via CI: 2.9.0 * chore(nbgv): set version via CI: 2.9.1 * Fix WithNoContent to preserve error results instead of silently replacing them (#97) WithNoContent unconditionally replaced any IResult with 204 NoContent, including validation errors (422), unauthorized (401), not found (404), and server errors (500). Now only confirmed 2xx results are replaced; errors and unknown status codes pass through unchanged. * chore(nbgv): set version via CI: 2.10-alpha * Fix nullable reference type warnings in tests Use the null-forgiving operator when passing null to methods in CommandResultExtensionsTests and ResultMapperTests to satisfy compiler nullability checks. * chore(nbgv): set version via CI: 2.11.0 * Comments * chore(nbgv): set version via CI: 2.11.1 --------- Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Replace
IResultMapperinterface withResultMapperbase class with overridable virtual methods for each decision point:Add
ResultMapper.Create()factory for one-off lambda customizations without subclassingAdd chainable
IResultdecorators:.WithHeader()and.WithNoContent()Change default validation status code from 400 to 422 (RFC 9110)
Change default exception handling from throw to
ProblemDetails500Null success results now return 404
NotFoundinstead ofOk(null)Remove
where TResult : classconstraint fromcontentSelectoroverloadRename selector parameter to
contentSelectorMotivation
User code review identified three gaps in the result mapping API:
TryHandleInvalidCommandwith no extension pointIResultMappercould not compose with selector overloads - no overload accepted both a mapper and acontentSelectorThe user built 80 lines of custom extension methods as workarounds. With this PR, all three patterns reduce to:
Breaking changes
Tests