Repository navigation
Add optional ISoapEndpointRegistry for SOAP endpoint discovery - #1198
Open
frankyjquintero wants to merge 1 commit into
Open
frankyjquintero wants to merge 1 commit into
frankyjquintero wants to merge 1 commit into
Conversation
Permite el listado programático de los servicios SOAP configurados con UseSoapEndpoint. Resuelve la limitación de que EndpointDataSource de ASP.NET Core no expone detalles suficientes para los servicios SoapCore. Esto facilita la creación de catálogos de servicios, gateways y herramientas de observabilidad. La funcionalidad es opt-in, thread-safe y registra un snapshot de la configuración del endpoint.
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.
Add optional
ISoapEndpointRegistryfor SOAP endpoint discoveryCloses #1190
Summary
SoapCore only records its endpoints as a side effect of
UseSoapEndpoint. In endpoint-routing modeEndpointDataSourceshows four routes per service (Path,/$metadata,/mex,/{methodName}), only one of them namedSoapCore, and none of them carries the service type, the serializer or the SOAP version. In middleware mode the endpoints do not appear inEndpointDataSourceat all. Anything that needs to list the SOAP services of a host (a catalog, a gateway, per-endpoint diagnostics) has to guess from the route table.This PR adds an opt-in, SOAP-aware registry of the endpoints configured with
UseSoapEndpoint, in both hosting modes. It follows the proposal in #1190 and the feedback from @andersjonsson ("a reasonable place to start"), and it includes the README section he asked for.When no registry is registered, SoapCore behaves exactly as before.
What changes
New public API:
Implementation notes:
UseSoapEndpointoverloads end in one of two methods, theIApplicationBuilderone and theIEndpointRouteBuilderone. Both call a small private helper that resolvesISoapEndpointRegistryfrom the root provider and, if present, registers one entry. In endpoint-routing mode the four mapped routes produce one entry.GetServiceperUseSoapEndpointcall at startup and no allocation (the snapshot is only built when a registry exists).AddSoapCore()is unchanged.SoapEndpointInfocopies values instead of holding the mutableSoapOptions, because the middleware mutatesEncoderOptionslater (EncoderOptions ??= ...). To keep the snapshot and the middleware aligned, the default encoder list now comes from one internal helper,SoapEncoderOptions.CreateDefaults(), used in both places (a one-line, behaviour-neutral change inSoapEndpointMiddleware).DefaultSoapEndpointRegistryisinternal, reachable throughAddSoapEndpointRegistry()(TryAddSingleton, so a registry the user already registered is never replaced). It is copy-on-write: registration takes a lock and publishes a new read-only array,GetAll()is a lock-free read, and a snapshot taken earlier never changes. Duplicates are kept on purpose: the same path can appear in mutually exclusiveUseWhenbranches.UseSoapEndpointruns, in call order. The recordedPathis the one as configured: prefixes added around the endpoint withapp.Map(...)orUsePathBase(...)are not included (documented in the README).Backward compatibility
AddSoapEndpointRegistry().DisplayName.netstandard2.0,netstandard2.1,netcoreapp3.1,net8.0) with no new warnings. The endpoint-routing hook sits inside the existing#if NETCOREAPP3_0_OR_GREATERblock.Tests
New tests in
src/SoapCore.Tests/EndpointRegistry(TestServer, same pattern as the existing integration tests):MiddlewareMode_RecordsSnapshotWithSoapCoreDefaultsEndpointRouting_RecordsOneEntryPerCallInCallOrderCaseInsensitivePath,GenerateSoapActionWithoutContractNameand distinctMessageVersionsSamePathInExclusiveBranches_RecordsBothEntriesInCallOrderUseWhenbranches is recorded twice, not deduplicatedUserRegisteredRegistry_TakesPrecedenceAndReceivesEntries(both modes)AddSoapEndpointRegistry()and receives the entriesMapBranch_RecordsPathRelativeToBranchapp.MaplimitationAddSoapCore_DoesNotEnableRegistryAddSoapEndpointRegistry()AddSoapEndpointRegistry_RegistersOneSingletonTryAddand singleton lifetimeDefaultRegistry_ValidatesAndReturnsReadOnlySnapshotsFull suite:
dotnet test src/SoapCore.Testspasses (302 existing tests plus the 9 new test cases).Documentation
New README section, "Discovering SOAP endpoints with ISoapEndpointRegistry": motivation, setup, a JSON catalog sample that works on every target framework, the
SoapEndpointInfofields, and the notes above (singleton requirement, call order, snapshot semantics, when to read the registry, theapp.Map/UsePathBaselimitation, what is not recorded).Not in this PR
Kept out on purpose to keep the change small and easy to review:
EndpointDataSource(the "future extension" of the issue).app.Map,UsePathBaseandMapGroup).<Version>bump, which I leave to the maintainers.Questions for the maintainers
DefaultSoapEndpointRegistrystayinternal(only reachable throughAddSoapEndpointRegistry()), or bepubliclikeDefaultOperationInvoker? I kept it internal because making it public later is not a breaking change, the opposite is.SoapEndpointInfohas public setters, likeSoapOptionsand the object initializer in the proposal. Would you prefer get-only properties with a constructor?EndpointDataSource: should the metadata always be attached to the routes, or be opt-in through aSoapCoreOptionsflag?Checklist