Add client-side WebHttpBinding support (closes #1413, #46) - #5959
Add client-side WebHttpBinding support (closes #1413, #46)#5959afifi-ins wants to merge 1 commit into
Conversation
a5caed5 to
794f262
Compare
CI failure analysis on PR dotnet#5959: - All 12 'dotnet-wcf-ci' (non-corewcf) legs fail with HTML-500 responses from the shared bridge wcfcoresrv23.westus3.cloudapp.azure.com - an infra outage that affects every outerloop test (Binding.Http, Binding.WS, Client.*, Contract.*, Encoding.*, Extensibility.*, Security.*), NOT this PR. - 'dotnet-wcf-with-corewcf--ci' (which uses local self-hosted CoreWCF, no bridge) is much cleaner - only one workitem fails: Binding.WebHttp.IntegrationTests. 4 of 7 tests fail with: System.InvalidOperationException: Manual addressing is enabled on this factory, so all messages sent must be pre-addressed. Root cause: - The CoreWCF source we lifted for WebHttpBehavior.cs (Phase 5) had an empty ApplyClientBehavior - CoreWCF is server-only and never implemented the client-side wiring. As a result, no UriTemplateClientFormatter ever ran on outgoing messages, so the per-operation URI was never bound. The channel factory then tried to send each request to the endpoint base address (http://localhost:8081/WebHttp.svc/) with ManualAddressing = true on the HttpTransportBindingElement - failing fast in ApplyManualAddressing. - The stub CoreWCF UriTemplateClientFormatter also threw PlatformNotSupportedException on every call - same reason. Fix: port the real client-side wiring from the .NET Framework MIT-licensed Reference Source mirror in mono/mono. Specifically: 1. src/.../Dispatcher/UriTemplateClientFormatter.cs: Replace the CoreWCF stub (DeserializeReply / SerializeRequest throw PlatformNotSupportedException) with the real .NET FX implementation (~150 LOC): binds operation parameters into the UriTemplate, sets Message.Headers.To from the bound URI, and applies SuppressEntityBody + Method on HttpRequestMessageProperty. Server-side WebOperationContext branch dropped; the client-only port uses the HttpRequestMessageProperty path unconditionally because dotnet/wcf's WebOperationContext does not expose OutgoingRequest (only OutgoingResponse, which is server-perspective). 2. src/.../Description/WebHttpBehavior.cs: - ApplyClientBehavior body replaced with the real .NET FX implementation: for each operation in the contract, build the request + reply client formatters, wrap in CompositeClientFormatter, set ClientOperation.Formatter, and add WebFaultClientMessageInspector. - Added the supporting client-side helper methods: GetRequestClientFormatter (the big one - ~80 LOC of URI-template + body-style routing, mirrors .NET FX) GetReplyClientFormatter (~30 LOC) GetDefaultClientFormatter (~30 LOC - harvests the WCF default formatter from a throwaway ClientOperation via IOperationBehavior.ApplyClientBehavior) GetDefaultXmlAndJsonClientFormatter (~10 LOC) GetDefaultContentType (~10 LOC) AddClientErrorInspector (~5 LOC) 3. src/.../Dispatcher/SingleBodyParameterMessageFormatter.cs: - Add IClientMessageFormatter interface (was IDispatchMessageFormatter only). - Add SerializeRequest, DeserializeReply, SuppressRequestEntityBody. - Add static factories CreateClientFormatter, CreateXmlAndJsonClientFormatter (mirror existing CreateDispatchFormatter / CreateXmlAndJsonDispatchFormatter). - Make nested NullMessageFormatter implement IClientMessageFormatter as well. 4. src/.../Dispatcher/HttpStreamFormatter.cs: - Add IClientMessageFormatter interface. - Add SerializeRequest (mirror of SerializeReply) and DeserializeReply. 5. New small client-side helper classes (each ~30 LOC, ported from .NET FX): - Dispatcher/CompositeClientFormatter.cs - request+reply pair. - Dispatcher/ContentTypeSettingClientMessageFormatter.cs - stamps outgoing Content-Type via HttpRequestMessageProperty (the .NET FX WebOperationContext branch is dropped for the same client-port reason). - Dispatcher/WebFaultClientMessageInspector.cs - surfaces HTTP 500 as CommunicationException so callers don't see empty payloads silently. DemultiplexingClientMessageFormatter is deliberately NOT ported: the .NET FX implementation switches on the inbound Content-Type to pick the XML or JSON client formatter, but our client-side path returns the XML formatter directly because [WebGet]/[WebInvoke].ResponseFormat already determines the wire format at description time. Both modes (XML and JSON) round-trip through the same SingleBodyParameter* formatter chain - the format mapping on WebHttpBinding routing selects the encoder per-message via WebBodyFormatMessageProperty. Verification: - Full repo build (build.cmd -restore -build -configuration Release): 0 warnings, 0 errors. - 3 unit tests pass locally (102ms): WebHttpBinding_CanBeConstructed, WebHttpBinding_TransportMode_UsesHttps, WebChannelFactory_Endpoint_HasWebHttpBinding. - 4 outerloop tests will execute end-to-end in CI now that the formatter chain is wired (still requires SelfHostedCoreWcfService running locally; CI's 'dotnet-wcf-with-corewcf--ci' leg launches it automatically). Also rebased onto upstream/main (commit 36673ab - Skip SctRenewalRegressionTests on CoreWCF host); no conflicts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
a04e6f3 to
98ec5dd
Compare
CI failure analysis on PR dotnet#5959: - All 12 'dotnet-wcf-ci' (non-corewcf) legs fail with HTML-500 responses from the shared bridge wcfcoresrv23.westus3.cloudapp.azure.com - an infra outage that affects every outerloop test (Binding.Http, Binding.WS, Client.*, Contract.*, Encoding.*, Extensibility.*, Security.*), NOT this PR. - 'dotnet-wcf-with-corewcf--ci' (which uses local self-hosted CoreWCF, no bridge) is much cleaner - only one workitem fails: Binding.WebHttp.IntegrationTests. 4 of 7 tests fail with: System.InvalidOperationException: Manual addressing is enabled on this factory, so all messages sent must be pre-addressed. Root cause: - The CoreWCF source we lifted for WebHttpBehavior.cs (Phase 5) had an empty ApplyClientBehavior - CoreWCF is server-only and never implemented the client-side wiring. As a result, no UriTemplateClientFormatter ever ran on outgoing messages, so the per-operation URI was never bound. The channel factory then tried to send each request to the endpoint base address (http://localhost:8081/WebHttp.svc/) with ManualAddressing = true on the HttpTransportBindingElement - failing fast in ApplyManualAddressing. - The stub CoreWCF UriTemplateClientFormatter also threw PlatformNotSupportedException on every call - same reason. Fix: port the real client-side wiring from the .NET Framework MIT-licensed Reference Source mirror in mono/mono. Specifically: 1. src/.../Dispatcher/UriTemplateClientFormatter.cs: Replace the CoreWCF stub (DeserializeReply / SerializeRequest throw PlatformNotSupportedException) with the real .NET FX implementation (~150 LOC): binds operation parameters into the UriTemplate, sets Message.Headers.To from the bound URI, and applies SuppressEntityBody + Method on HttpRequestMessageProperty. Server-side WebOperationContext branch dropped; the client-only port uses the HttpRequestMessageProperty path unconditionally because dotnet/wcf's WebOperationContext does not expose OutgoingRequest (only OutgoingResponse, which is server-perspective). 2. src/.../Description/WebHttpBehavior.cs: - ApplyClientBehavior body replaced with the real .NET FX implementation: for each operation in the contract, build the request + reply client formatters, wrap in CompositeClientFormatter, set ClientOperation.Formatter, and add WebFaultClientMessageInspector. - Added the supporting client-side helper methods: GetRequestClientFormatter (the big one - ~80 LOC of URI-template + body-style routing, mirrors .NET FX) GetReplyClientFormatter (~30 LOC) GetDefaultClientFormatter (~30 LOC - harvests the WCF default formatter from a throwaway ClientOperation via IOperationBehavior.ApplyClientBehavior) GetDefaultXmlAndJsonClientFormatter (~10 LOC) GetDefaultContentType (~10 LOC) AddClientErrorInspector (~5 LOC) 3. src/.../Dispatcher/SingleBodyParameterMessageFormatter.cs: - Add IClientMessageFormatter interface (was IDispatchMessageFormatter only). - Add SerializeRequest, DeserializeReply, SuppressRequestEntityBody. - Add static factories CreateClientFormatter, CreateXmlAndJsonClientFormatter (mirror existing CreateDispatchFormatter / CreateXmlAndJsonDispatchFormatter). - Make nested NullMessageFormatter implement IClientMessageFormatter as well. 4. src/.../Dispatcher/HttpStreamFormatter.cs: - Add IClientMessageFormatter interface. - Add SerializeRequest (mirror of SerializeReply) and DeserializeReply. 5. New small client-side helper classes (each ~30 LOC, ported from .NET FX): - Dispatcher/CompositeClientFormatter.cs - request+reply pair. - Dispatcher/ContentTypeSettingClientMessageFormatter.cs - stamps outgoing Content-Type via HttpRequestMessageProperty (the .NET FX WebOperationContext branch is dropped for the same client-port reason). - Dispatcher/WebFaultClientMessageInspector.cs - surfaces HTTP 500 as CommunicationException so callers don't see empty payloads silently. DemultiplexingClientMessageFormatter is deliberately NOT ported: the .NET FX implementation switches on the inbound Content-Type to pick the XML or JSON client formatter, but our client-side path returns the XML formatter directly because [WebGet]/[WebInvoke].ResponseFormat already determines the wire format at description time. Both modes (XML and JSON) round-trip through the same SingleBodyParameter* formatter chain - the format mapping on WebHttpBinding routing selects the encoder per-message via WebBodyFormatMessageProperty. Verification: - Full repo build (build.cmd -restore -build -configuration Release): 0 warnings, 0 errors. - 3 unit tests pass locally (102ms): WebHttpBinding_CanBeConstructed, WebHttpBinding_TransportMode_UsesHttps, WebChannelFactory_Endpoint_HasWebHttpBinding. - 4 outerloop tests will execute end-to-end in CI now that the formatter chain is wired (still requires SelfHostedCoreWcfService running locally; CI's 'dotnet-wcf-with-corewcf--ci' leg launches it automatically). Also rebased onto upstream/main (commit 36673ab - Skip SctRenewalRegressionTests on CoreWCF host); no conflicts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). |
|
/azp run |
|
Azure Pipelines: Successfully started running 2 pipeline(s). |
… message The HttpClientCredentialTypeInvalid resource string used to list valid client credential values as 'None, Basic, Client, Digest, Ntlm, Windows'. There is no 'Client' member on HttpClientCredentialType; the intended value is 'Certificate' (see src/System.ServiceModel.Http/src/System/ ServiceModel/HttpClientCredentialType.cs). Every caller of SR.HttpClientCredentialTypeInvalid (WSHttpBinding, BasicHttpBinding, BasicHttpsBinding, NetHttpBinding, NetHttpsBinding, and the new WebHttpBinding guard added by this PR) was therefore telling users to use a value that does not exist. Fix the wording in all three shipping resx files: * System.ServiceModel.Http/src/Resources/Strings.resx * System.ServiceModel.Primitives/src/Resources/Strings.resx * System.ServiceModel.Web/src/Resources/Strings.resx Arcade's XliffTasks regenerated the 39 companion xlf files during the next build. The English <source> is now correct in every locale; the localized <target> strings that inlined the value verbatim are flagged state='needs-review-translation' so the localization team can refresh them in a follow-up localization sync. svcutil's SRServiceModel.resx keeps the pre-existing typo (out of scope per task direction). Flagged by Claude Sonnet 5 during multi-model review of PR dotnet#5959. No code-behind changes; SR key and format argument count are unchanged so all five call sites and the new WebHttp guard keep working. All 39 in-repo WebHttp tests still pass (0 failed). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
All three WebHttpBinding_*_RoundTripsAgainstLocalHttpListener tests used to hardcode a port (18091 / 18092 / 18093) and silently 'return' on HttpListenerException. If the hardcoded port was already in use on the test runner, the test would report as PASSED without running any assertion - masking a real regression in the client's URL binding, JSON reply deserialization, or cookie handling. Flagged by Gemini 3.1 Pro during multi-model code review of PR dotnet#5959. Add a StartLoopbackHttpListener helper that: * Picks a random port from the Windows dynamic / ephemeral range (49152-65535 per RFC 6335), minimizing collisions with configured services. * Retries up to MaxPortRetries (10) times to survive transient collisions or parallel-test races. * On exhaustion, calls Assert.Fail with a per-attempt diagnostic listing each attempted port and its HttpListener error code. Verified in a temp failure-mode run: 'Unable to find a random port number after 10 attempts. Errors: attempt 1 port 1: 5/Access is denied; ...' Refactor all three call sites to use the helper: one-line tuple deconstruction replaces the seven-line hardcoded-port + try/catch/return boilerplate in each test. Downstream logic is unchanged. Semantics change vs before: an HttpListener environment that truly blocks loopback binding after 10 tries now fails the test loudly instead of skipping silently. This is the intended trade-off - a real environmental block is worth surfacing, and 10 attempts across 16384 ports guarantees any transient collision is handled. Local validation: 39 passed / 0 failed / 4 skipped (outerloop). Full repo build clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
SR.Format is only needed when there string resource is parameterized. When it isn't parameterized, you can use the string resource directly without calling SR.Format. Refers to: src/System.ServiceModel.Web/src/System/UriTemplate.cs:337 in a0df75f. [](commit_id = a0df75f, deletion_comment = False) |
This can probably be removed as it was included to stop a false positive on a static analysis rule in the .NET Framework source code. Replace with an Fx.Assert that they are not null to ensure the stated assertion holds true. Refers to: src/System.ServiceModel.Web/src/System/UriTemplate.cs:429 in a0df75f. [](commit_id = a0df75f, deletion_comment = False) |
ByteStreamMessageEncodingBindingElement should be ported into the Primitives package as it has utility outside of WebHttpBinding. Add it to this PR. Refers to: src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebMessageEncoderFactory.cs:111 in a0df75f. [](commit_id = a0df75f, deletion_comment = False) |
It looks like this was ported over from the CoreWCF code base as it's referencing IServiceProvider. Have AI re-port this from the NetFx codebase as we don't need IServiceProvider for the client. Refers to: src/System.ServiceModel.Web/src/System/ServiceModel/Description/WebHttpBehavior.cs:38 in a0df75f. [](commit_id = a0df75f, deletion_comment = False) |
IDispatchMessageFormatter isn't needed for WebHttpBinding as it's only doing Request/Reply. IDispatchMessageFormatter is only used for duplex transports on the client. Refers to: src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/HttpStreamFormatter.cs:12 in a0df75f. [](commit_id = a0df75f, deletion_comment = False) |
Make sure this along with any other references is fixed once ByteStreamMessageEncodingBindingElement is ported. Refers to: src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/HttpStreamFormatter.cs:77 in a0df75f. [](commit_id = a0df75f, deletion_comment = False) |
A performance issue was found with this code in CoreWCF and was replace with something else. I can't remember whether the replacement is usable here as I think it might have used an asp.net core class which the WCF Client can't reference. Take a look and see if it is something in the main runtime that I switched to. If not, then ask Copilot for an alternative. There might be something in the newer HttpClient headers api's which provides this parsing capability. Either way, we need to strip this code out and replace its usage with something else. Refers to: src/System.ServiceModel.Web/src/System/ServiceModel/Web/HttpDateParse.cs:19 in a0df75f. [](commit_id = a0df75f, deletion_comment = False) |
This is a service side class to represent an incoming request. On the client side we should only have IncomingWebResponseContext and OutgoingWebResponseContext Refers to: src/System.ServiceModel.Web/src/System/ServiceModel/Web/IncomingWebRequestContext.cs:16 in a0df75f. [](commit_id = a0df75f, deletion_comment = False) |
This is missing: public IncomingWebResponseContext IncomingResponse { get; }
public OutgoingWebRequestContext OutgoingRequest { get; }Refers to: src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebOperationContext.cs:60 in a0df75f. [](commit_id = a0df75f, deletion_comment = False) |
f4b0821 to
829c3f4
Compare
CI failure analysis on PR dotnet#5959: - All 12 'dotnet-wcf-ci' (non-corewcf) legs fail with HTML-500 responses from the shared bridge wcfcoresrv23.westus3.cloudapp.azure.com - an infra outage that affects every outerloop test (Binding.Http, Binding.WS, Client.*, Contract.*, Encoding.*, Extensibility.*, Security.*), NOT this PR. - 'dotnet-wcf-with-corewcf--ci' (which uses local self-hosted CoreWCF, no bridge) is much cleaner - only one workitem fails: Binding.WebHttp.IntegrationTests. 4 of 7 tests fail with: System.InvalidOperationException: Manual addressing is enabled on this factory, so all messages sent must be pre-addressed. Root cause: - The CoreWCF source we lifted for WebHttpBehavior.cs (Phase 5) had an empty ApplyClientBehavior - CoreWCF is server-only and never implemented the client-side wiring. As a result, no UriTemplateClientFormatter ever ran on outgoing messages, so the per-operation URI was never bound. The channel factory then tried to send each request to the endpoint base address (http://localhost:8081/WebHttp.svc/) with ManualAddressing = true on the HttpTransportBindingElement - failing fast in ApplyManualAddressing. - The stub CoreWCF UriTemplateClientFormatter also threw PlatformNotSupportedException on every call - same reason. Fix: port the real client-side wiring from the .NET Framework MIT-licensed Reference Source mirror in mono/mono. Specifically: 1. src/.../Dispatcher/UriTemplateClientFormatter.cs: Replace the CoreWCF stub (DeserializeReply / SerializeRequest throw PlatformNotSupportedException) with the real .NET FX implementation (~150 LOC): binds operation parameters into the UriTemplate, sets Message.Headers.To from the bound URI, and applies SuppressEntityBody + Method on HttpRequestMessageProperty. Server-side WebOperationContext branch dropped; the client-only port uses the HttpRequestMessageProperty path unconditionally because dotnet/wcf's WebOperationContext does not expose OutgoingRequest (only OutgoingResponse, which is server-perspective). 2. src/.../Description/WebHttpBehavior.cs: - ApplyClientBehavior body replaced with the real .NET FX implementation: for each operation in the contract, build the request + reply client formatters, wrap in CompositeClientFormatter, set ClientOperation.Formatter, and add WebFaultClientMessageInspector. - Added the supporting client-side helper methods: GetRequestClientFormatter (the big one - ~80 LOC of URI-template + body-style routing, mirrors .NET FX) GetReplyClientFormatter (~30 LOC) GetDefaultClientFormatter (~30 LOC - harvests the WCF default formatter from a throwaway ClientOperation via IOperationBehavior.ApplyClientBehavior) GetDefaultXmlAndJsonClientFormatter (~10 LOC) GetDefaultContentType (~10 LOC) AddClientErrorInspector (~5 LOC) 3. src/.../Dispatcher/SingleBodyParameterMessageFormatter.cs: - Add IClientMessageFormatter interface (was IDispatchMessageFormatter only). - Add SerializeRequest, DeserializeReply, SuppressRequestEntityBody. - Add static factories CreateClientFormatter, CreateXmlAndJsonClientFormatter (mirror existing CreateDispatchFormatter / CreateXmlAndJsonDispatchFormatter). - Make nested NullMessageFormatter implement IClientMessageFormatter as well. 4. src/.../Dispatcher/HttpStreamFormatter.cs: - Add IClientMessageFormatter interface. - Add SerializeRequest (mirror of SerializeReply) and DeserializeReply. 5. New small client-side helper classes (each ~30 LOC, ported from .NET FX): - Dispatcher/CompositeClientFormatter.cs - request+reply pair. - Dispatcher/ContentTypeSettingClientMessageFormatter.cs - stamps outgoing Content-Type via HttpRequestMessageProperty (the .NET FX WebOperationContext branch is dropped for the same client-port reason). - Dispatcher/WebFaultClientMessageInspector.cs - surfaces HTTP 500 as CommunicationException so callers don't see empty payloads silently. DemultiplexingClientMessageFormatter is deliberately NOT ported: the .NET FX implementation switches on the inbound Content-Type to pick the XML or JSON client formatter, but our client-side path returns the XML formatter directly because [WebGet]/[WebInvoke].ResponseFormat already determines the wire format at description time. Both modes (XML and JSON) round-trip through the same SingleBodyParameter* formatter chain - the format mapping on WebHttpBinding routing selects the encoder per-message via WebBodyFormatMessageProperty. Verification: - Full repo build (build.cmd -restore -build -configuration Release): 0 warnings, 0 errors. - 3 unit tests pass locally (102ms): WebHttpBinding_CanBeConstructed, WebHttpBinding_TransportMode_UsesHttps, WebChannelFactory_Endpoint_HasWebHttpBinding. - 4 outerloop tests will execute end-to-end in CI now that the formatter chain is wired (still requires SelfHostedCoreWcfService running locally; CI's 'dotnet-wcf-with-corewcf--ci' leg launches it automatically). Also rebased onto upstream/main (commit 36673ab - Skip SctRenewalRegressionTests on CoreWCF host); no conflicts. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… message The HttpClientCredentialTypeInvalid resource string used to list valid client credential values as 'None, Basic, Client, Digest, Ntlm, Windows'. There is no 'Client' member on HttpClientCredentialType; the intended value is 'Certificate' (see src/System.ServiceModel.Http/src/System/ ServiceModel/HttpClientCredentialType.cs). Every caller of SR.HttpClientCredentialTypeInvalid (WSHttpBinding, BasicHttpBinding, BasicHttpsBinding, NetHttpBinding, NetHttpsBinding, and the new WebHttpBinding guard added by this PR) was therefore telling users to use a value that does not exist. Fix the wording in all three shipping resx files: * System.ServiceModel.Http/src/Resources/Strings.resx * System.ServiceModel.Primitives/src/Resources/Strings.resx * System.ServiceModel.Web/src/Resources/Strings.resx Arcade's XliffTasks regenerated the 39 companion xlf files during the next build. The English <source> is now correct in every locale; the localized <target> strings that inlined the value verbatim are flagged state='needs-review-translation' so the localization team can refresh them in a follow-up localization sync. svcutil's SRServiceModel.resx keeps the pre-existing typo (out of scope per task direction). Flagged by Claude Sonnet 5 during multi-model review of PR dotnet#5959. No code-behind changes; SR key and format argument count are unchanged so all five call sites and the new WebHttp guard keep working. All 39 in-repo WebHttp tests still pass (0 failed). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
All three WebHttpBinding_*_RoundTripsAgainstLocalHttpListener tests used to hardcode a port (18091 / 18092 / 18093) and silently 'return' on HttpListenerException. If the hardcoded port was already in use on the test runner, the test would report as PASSED without running any assertion - masking a real regression in the client's URL binding, JSON reply deserialization, or cookie handling. Flagged by Gemini 3.1 Pro during multi-model code review of PR dotnet#5959. Add a StartLoopbackHttpListener helper that: * Picks a random port from the Windows dynamic / ephemeral range (49152-65535 per RFC 6335), minimizing collisions with configured services. * Retries up to MaxPortRetries (10) times to survive transient collisions or parallel-test races. * On exhaustion, calls Assert.Fail with a per-attempt diagnostic listing each attempted port and its HttpListener error code. Verified in a temp failure-mode run: 'Unable to find a random port number after 10 attempts. Errors: attempt 1 port 1: 5/Access is denied; ...' Refactor all three call sites to use the helper: one-line tuple deconstruction replaces the seven-line hardcoded-port + try/catch/return boilerplate in each test. Downstream logic is unchanged. Semantics change vs before: an HttpListener environment that truly blocks loopback binding after 10 tries now fails the test loudly instead of skipping silently. This is the intended trade-off - a real environmental block is worth surfacing, and 10 attempts across 16384 ports guarantees any transient collision is handled. Local validation: 39 passed / 0 failed / 4 skipped (outerloop). Full repo build clean. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
I investigated the Findings:
The fix makes the new assembly a strict superset of the framework facade by preserving its exact 38 JSON/Syndication type forwards, adds the existing centrally-versioned |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 8849d097-7c27-4ccb-98a9-3fae1d876771
94fc0e6 to
928e6d6
Compare
|
All review feedback is resolved on squashed head
The five inline threads also have concise final replies and are marked resolved. CI is green. |
Closes #1413
Closes #46
Summary
Adds a new client-side
System.ServiceModel.Webpackage for REST-style WCF clients on .NET, including:WebHttpBinding,WebHttpSecurity, and HTTP/HTTPS transport settingsWebHttpBehavior,WebGetAttribute, andWebInvokeAttributeWebChannelFactory<TChannel>and client-sideWebOperationContextrequest/response contextsUriTemplate,UriTemplateTable, matching/binding helpers, andQueryStringConverterStreammessage encoding, including buffered and streamed pathsContent-TypeThe implementation is sourced from the MIT-licensed .NET Framework reference source and CoreWCF, then adapted to current dotnet/wcf patterns and its client-only architecture.
Scope
This PR implements the WCF client surface. Service hosting and dispatch remain CoreWCF responsibilities, so server-side dispatch selectors/formatters, help pages, service error handlers, JSONP, ASP.NET hosting integration, and
WebServiceHostare intentionally excluded.Raw octet-stream support is included. The reusable
ByteStreamMessageandByteStreamMessageEncodingBindingElementimplementation lives inSystem.ServiceModel.Primitives; its public surface is exposed only for the current .NET target, matching the implementation TFMs.Compatibility and packaging
System.ServiceModel.Webproject, reference assembly, unit-test project, package README, and solution wiring.System.ServiceModel.Webfacade by forwarding all 38 JSON and Syndication types exposed by that facade.InternalsVisibleTodependencies onSystem.ServiceModel.HttpandSystem.ServiceModel.Primitives.UriTemplateandQueryStringConvertercompatibility quirks.Tests
System.ServiceModel.Webunit tests covering bindings, security, URI templates, query conversion, attributes, operation context, behavior/formatters, XML/JSON/raw encoders, buffered/streamed paths, and facade compatibility.System.ServiceModel.PrimitivesByteStream tests cover buffering, offsets, ownership, repeated disposal, sync/async encoding, quotas, and validation.The self-hosted CoreWCF outerloop scenarios require elevated certificate installation locally and are expected to run in the CI/elevated test environment.
Source attribution
Ported files retain the .NET Foundation MIT header. Commit history records whether each implementation came from the .NET Framework reference source or CoreWCF and documents client-specific adaptations.