diff --git a/System.ServiceModel.sln b/System.ServiceModel.sln index 16c21a1eee1..5db2b14baa3 100644 --- a/System.ServiceModel.sln +++ b/System.ServiceModel.sln @@ -23,6 +23,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Binding.Custom.IntegrationT EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Binding.Http.IntegrationTests", "src\System.Private.ServiceModel\tests\Scenarios\Binding\Http\Binding.Http.IntegrationTests.csproj", "{2789D52D-9C17-4FCE-B81C-41B65C3FAFF9}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Binding.WebHttp.IntegrationTests", "src\System.Private.ServiceModel\tests\Scenarios\Binding\WebHttp\Binding.WebHttp.IntegrationTests.csproj", "{F0F5C0C0-AB1D-4A86-A0A9-3D13ACB9B249}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Binding.Tcp.IntegrationTests", "src\System.Private.ServiceModel\tests\Scenarios\Binding\Tcp\Binding.Tcp.IntegrationTests.csproj", "{B38A2272-F260-4303-964C-ACDC9BADEB79}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Client.ChannelLayer.IntegrationTests", "src\System.Private.ServiceModel\tests\Scenarios\Client\ChannelLayer\Client.ChannelLayer.IntegrationTests.csproj", "{CB612ECB-A863-46D2-90E2-61CC2C22C7D0}" @@ -89,6 +91,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Binding.UDS.IntegrationTest EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.ServiceModel.NetNamedPipe.Tests", "src\System.ServiceModel.NetNamedPipe\tests\System.ServiceModel.NetNamedPipe.Tests.csproj", "{FD188537-21AF-48C5-84FF-F8758F4C42A8}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.ServiceModel.Web", "src\System.ServiceModel.Web\src\System.ServiceModel.Web.csproj", "{B9669945-F041-4088-9949-20DC0AE9753D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.ServiceModel.Web.Tests", "src\System.ServiceModel.Web\tests\System.ServiceModel.Web.Tests.csproj", "{76E6B222-8CC8-44F4-A1C6-862706CCE788}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.ServiceModel.Http.Ref", "src\System.ServiceModel.Http\ref\System.ServiceModel.Http.Ref.csproj", "{34CCEAC9-43B1-4654-BF2F-0B40EC7AD016}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.ServiceModel.NetTcp.Ref", "src\System.ServiceModel.NetTcp\ref\System.ServiceModel.NetTcp.Ref.csproj", "{81843CB2-E128-427B-9920-EEDBBBD4CB0B}" @@ -243,6 +249,18 @@ Global {2789D52D-9C17-4FCE-B81C-41B65C3FAFF9}.Release|x64.Build.0 = Release|Any CPU {2789D52D-9C17-4FCE-B81C-41B65C3FAFF9}.Release|x86.ActiveCfg = Release|Any CPU {2789D52D-9C17-4FCE-B81C-41B65C3FAFF9}.Release|x86.Build.0 = Release|Any CPU + {F0F5C0C0-AB1D-4A86-A0A9-3D13ACB9B249}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F0F5C0C0-AB1D-4A86-A0A9-3D13ACB9B249}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F0F5C0C0-AB1D-4A86-A0A9-3D13ACB9B249}.Debug|x64.ActiveCfg = Debug|Any CPU + {F0F5C0C0-AB1D-4A86-A0A9-3D13ACB9B249}.Debug|x64.Build.0 = Debug|Any CPU + {F0F5C0C0-AB1D-4A86-A0A9-3D13ACB9B249}.Debug|x86.ActiveCfg = Debug|Any CPU + {F0F5C0C0-AB1D-4A86-A0A9-3D13ACB9B249}.Debug|x86.Build.0 = Debug|Any CPU + {F0F5C0C0-AB1D-4A86-A0A9-3D13ACB9B249}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F0F5C0C0-AB1D-4A86-A0A9-3D13ACB9B249}.Release|Any CPU.Build.0 = Release|Any CPU + {F0F5C0C0-AB1D-4A86-A0A9-3D13ACB9B249}.Release|x64.ActiveCfg = Release|Any CPU + {F0F5C0C0-AB1D-4A86-A0A9-3D13ACB9B249}.Release|x64.Build.0 = Release|Any CPU + {F0F5C0C0-AB1D-4A86-A0A9-3D13ACB9B249}.Release|x86.ActiveCfg = Release|Any CPU + {F0F5C0C0-AB1D-4A86-A0A9-3D13ACB9B249}.Release|x86.Build.0 = Release|Any CPU {B38A2272-F260-4303-964C-ACDC9BADEB79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B38A2272-F260-4303-964C-ACDC9BADEB79}.Debug|Any CPU.Build.0 = Debug|Any CPU {B38A2272-F260-4303-964C-ACDC9BADEB79}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -615,6 +633,30 @@ Global {FD188537-21AF-48C5-84FF-F8758F4C42A8}.Release|x64.Build.0 = Release|Any CPU {FD188537-21AF-48C5-84FF-F8758F4C42A8}.Release|x86.ActiveCfg = Release|Any CPU {FD188537-21AF-48C5-84FF-F8758F4C42A8}.Release|x86.Build.0 = Release|Any CPU + {B9669945-F041-4088-9949-20DC0AE9753D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9669945-F041-4088-9949-20DC0AE9753D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9669945-F041-4088-9949-20DC0AE9753D}.Debug|x64.ActiveCfg = Debug|Any CPU + {B9669945-F041-4088-9949-20DC0AE9753D}.Debug|x64.Build.0 = Debug|Any CPU + {B9669945-F041-4088-9949-20DC0AE9753D}.Debug|x86.ActiveCfg = Debug|Any CPU + {B9669945-F041-4088-9949-20DC0AE9753D}.Debug|x86.Build.0 = Debug|Any CPU + {B9669945-F041-4088-9949-20DC0AE9753D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9669945-F041-4088-9949-20DC0AE9753D}.Release|Any CPU.Build.0 = Release|Any CPU + {B9669945-F041-4088-9949-20DC0AE9753D}.Release|x64.ActiveCfg = Release|Any CPU + {B9669945-F041-4088-9949-20DC0AE9753D}.Release|x64.Build.0 = Release|Any CPU + {B9669945-F041-4088-9949-20DC0AE9753D}.Release|x86.ActiveCfg = Release|Any CPU + {B9669945-F041-4088-9949-20DC0AE9753D}.Release|x86.Build.0 = Release|Any CPU + {76E6B222-8CC8-44F4-A1C6-862706CCE788}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {76E6B222-8CC8-44F4-A1C6-862706CCE788}.Debug|Any CPU.Build.0 = Debug|Any CPU + {76E6B222-8CC8-44F4-A1C6-862706CCE788}.Debug|x64.ActiveCfg = Debug|Any CPU + {76E6B222-8CC8-44F4-A1C6-862706CCE788}.Debug|x64.Build.0 = Debug|Any CPU + {76E6B222-8CC8-44F4-A1C6-862706CCE788}.Debug|x86.ActiveCfg = Debug|Any CPU + {76E6B222-8CC8-44F4-A1C6-862706CCE788}.Debug|x86.Build.0 = Debug|Any CPU + {76E6B222-8CC8-44F4-A1C6-862706CCE788}.Release|Any CPU.ActiveCfg = Release|Any CPU + {76E6B222-8CC8-44F4-A1C6-862706CCE788}.Release|Any CPU.Build.0 = Release|Any CPU + {76E6B222-8CC8-44F4-A1C6-862706CCE788}.Release|x64.ActiveCfg = Release|Any CPU + {76E6B222-8CC8-44F4-A1C6-862706CCE788}.Release|x64.Build.0 = Release|Any CPU + {76E6B222-8CC8-44F4-A1C6-862706CCE788}.Release|x86.ActiveCfg = Release|Any CPU + {76E6B222-8CC8-44F4-A1C6-862706CCE788}.Release|x86.Build.0 = Release|Any CPU {34CCEAC9-43B1-4654-BF2F-0B40EC7AD016}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {34CCEAC9-43B1-4654-BF2F-0B40EC7AD016}.Debug|Any CPU.Build.0 = Debug|Any CPU {34CCEAC9-43B1-4654-BF2F-0B40EC7AD016}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -734,6 +776,7 @@ Global {58918456-A2B2-431F-BB95-BAAD2818BFC7} = {DFDC71CF-6E65-481D-99D7-C35ED7EF6D4E} {D878F354-E120-476A-A90A-9E601A7E7580} = {D6302510-AB10-4775-BCE9-98FA96FDEB76} {2789D52D-9C17-4FCE-B81C-41B65C3FAFF9} = {D6302510-AB10-4775-BCE9-98FA96FDEB76} + {F0F5C0C0-AB1D-4A86-A0A9-3D13ACB9B249} = {D6302510-AB10-4775-BCE9-98FA96FDEB76} {B38A2272-F260-4303-964C-ACDC9BADEB79} = {D6302510-AB10-4775-BCE9-98FA96FDEB76} {CB612ECB-A863-46D2-90E2-61CC2C22C7D0} = {D6302510-AB10-4775-BCE9-98FA96FDEB76} {76A75B01-C666-4953-924E-DCAC9C7AADF3} = {D6302510-AB10-4775-BCE9-98FA96FDEB76} @@ -760,6 +803,8 @@ Global {88918456-A2B2-431F-BB95-BAAD2818BFC7} = {DFDC71CF-6E65-481D-99D7-C35ED7EF6D4E} {B7C7D4F1-DE4D-421B-9CE9-C7320A503D58} = {D6302510-AB10-4775-BCE9-98FA96FDEB76} {FD188537-21AF-48C5-84FF-F8758F4C42A8} = {DFDC71CF-6E65-481D-99D7-C35ED7EF6D4E} + {B9669945-F041-4088-9949-20DC0AE9753D} = {D6302510-AB10-4775-BCE9-98FA96FDEB76} + {76E6B222-8CC8-44F4-A1C6-862706CCE788} = {DFDC71CF-6E65-481D-99D7-C35ED7EF6D4E} {0CB62138-1E7D-4D9D-B7BF-4FCB79BC8EAA} = {D6302510-AB10-4775-BCE9-98FA96FDEB76} {7D7DACFC-D1DA-48C0-9BA1-C3A414780658} = {D6302510-AB10-4775-BCE9-98FA96FDEB76} EndGlobalSection diff --git a/release-notes/SupportedFeatures-v2.1.0.md b/release-notes/SupportedFeatures-v2.1.0.md index a4a4dc419e8..433f1bed7f4 100644 --- a/release-notes/SupportedFeatures-v2.1.0.md +++ b/release-notes/SupportedFeatures-v2.1.0.md @@ -14,7 +14,7 @@ Supported features | |CustomBinding |:white_check_mark: |:white_check_mark: | :white_check_mark: | | |NetHttpBinding |:white_check_mark: |:white_check_mark: | :white_check_mark: | | |NetTcpBinding |:white_check_mark: |:white_check_mark: | :white_check_mark: | -| |WebHttpBinding |:no_entry_sign: |:no_entry_sign: | :no_entry_sign: | +| |WebHttpBinding |:warning: |:warning: | :warning: | |Transports |Http |:white_check_mark: |:white_check_mark: | :white_check_mark: | | |Https |:white_check_mark: |:white_check_mark: | :white_check_mark: | | |Tcp |:white_check_mark: |:white_check_mark: | :white_check_mark: | diff --git a/src/System.Private.ServiceModel/tests/Common/Infrastructure/ConditionalWcfTest.cs b/src/System.Private.ServiceModel/tests/Common/Infrastructure/ConditionalWcfTest.cs index f5f1f035095..20cf1cadeb7 100644 --- a/src/System.Private.ServiceModel/tests/Common/Infrastructure/ConditionalWcfTest.cs +++ b/src/System.Private.ServiceModel/tests/Common/Infrastructure/ConditionalWcfTest.cs @@ -390,5 +390,15 @@ public static bool Skip_CoreWCFService_FailedTest() return !GetConditionValue(nameof(Skip_CoreWCFService_FailedTest), ConditionalTestDetectors.IsRunWithCoreWCFService); } + + // Returns 'true' only when the test infrastructure is hosting services via + // CoreWCF (self-hosted). Used to gate outer-loop scenario tests whose + // service endpoint is only registered by the CoreWCF self-host project + // and is not yet deployed to the shared IIS bridge. + public static bool Run_With_CoreWCFService() + { + return GetConditionValue(nameof(Run_With_CoreWCFService), + ConditionalTestDetectors.IsRunWithCoreWCFService); + } } } diff --git a/src/System.Private.ServiceModel/tests/Common/Scenarios/Endpoints.WebHttp.cs b/src/System.Private.ServiceModel/tests/Common/Scenarios/Endpoints.WebHttp.cs new file mode 100644 index 00000000000..b6131efc9e5 --- /dev/null +++ b/src/System.Private.ServiceModel/tests/Common/Scenarios/Endpoints.WebHttp.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// Endpoints addresses for WebHttp (REST) test services. Partial extension to +// Endpoints (declared partial in tests/Common/Scenarios/Endpoints.cs). +public static partial class Endpoints +{ + #region WebHttp Addresses + public static string HttpBaseAddress_WebHttp + => GetEndpointAddress("WebHttp.svc/"); + + public static string HttpBaseAddress_WebHttp_EchoGet + => GetEndpointAddress("WebHttp.svc/EchoWithGet"); + + public static string HttpBaseAddress_WebHttp_EchoGetJson + => GetEndpointAddress("WebHttp.svc/EchoWithGetJson"); + + public static string HttpBaseAddress_WebHttp_EchoPost + => GetEndpointAddress("WebHttp.svc/EchoWithPost"); + + public static string HttpBaseAddress_WebHttp_EchoPostJson + => GetEndpointAddress("WebHttp.svc/EchoWithPostJson"); + + public static string HttpBaseAddress_WebHttp_EchoGetPath + => GetEndpointAddress("WebHttp.svc/EchoWithGetPath"); + #endregion +} diff --git a/src/System.Private.ServiceModel/tests/Scenarios/Binding/WebHttp/Binding.WebHttp.IntegrationTests.csproj b/src/System.Private.ServiceModel/tests/Scenarios/Binding/WebHttp/Binding.WebHttp.IntegrationTests.csproj new file mode 100644 index 00000000000..69dec139133 --- /dev/null +++ b/src/System.Private.ServiceModel/tests/Scenarios/Binding/WebHttp/Binding.WebHttp.IntegrationTests.csproj @@ -0,0 +1,25 @@ + + + + $(ScenarioTestTargetFrameworks) + false + true + false + 9.0 + + $(NoWarn);CS0105;CS0108;CS0436;MSB3243 + + + + + + + + + + + + + diff --git a/src/System.Private.ServiceModel/tests/Scenarios/Binding/WebHttp/WebHttpBindingTests.cs b/src/System.Private.ServiceModel/tests/Scenarios/Binding/WebHttp/WebHttpBindingTests.cs new file mode 100644 index 00000000000..2918d1005ef --- /dev/null +++ b/src/System.Private.ServiceModel/tests/Scenarios/Binding/WebHttp/WebHttpBindingTests.cs @@ -0,0 +1,552 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.ServiceModel; +using System.ServiceModel.Channels; +using System.ServiceModel.Description; +using System.ServiceModel.Dispatcher; +using System.ServiceModel.Web; +using Infrastructure.Common; +using Xunit; + +// Mirror of the contract defined in +// tools/IISHostedWcfService/App_code/testhosts/WebHttpTestServiceHost.cs +// Declared here so the test project does not need a project reference +// to IISHostedWcfService (which is folded into the SelfHostedCoreWcfService +// host via wildcard and is therefore not consumable as a +// library). The two declarations must stay in wire-format sync (same +// [ServiceContract], same UriTemplate paths). +[ServiceContract] +public interface IWcfWebHttpService +{ + [OperationContract] + [WebGet(UriTemplate = "EchoWithGet?message={message}", + BodyStyle = WebMessageBodyStyle.Bare, + ResponseFormat = WebMessageFormat.Xml)] + string EchoWithGet(string message); + + [OperationContract] + [WebGet(UriTemplate = "EchoWithGetJson?message={message}", + BodyStyle = WebMessageBodyStyle.Bare, + ResponseFormat = WebMessageFormat.Json)] + string EchoWithGetJson(string message); + + [OperationContract] + [WebInvoke(Method = "POST", UriTemplate = "EchoWithPost", + BodyStyle = WebMessageBodyStyle.Bare, + ResponseFormat = WebMessageFormat.Xml, + RequestFormat = WebMessageFormat.Xml)] + string EchoWithPost(string message); + + [OperationContract] + [WebInvoke(Method = "POST", UriTemplate = "EchoWithPostJson", + BodyStyle = WebMessageBodyStyle.Bare, + ResponseFormat = WebMessageFormat.Json, + RequestFormat = WebMessageFormat.Json)] + string EchoWithPostJson(string message); + + [OperationContract] + [WebGet(UriTemplate = "EchoWithGetPath/{message}", + BodyStyle = WebMessageBodyStyle.Bare, + ResponseFormat = WebMessageFormat.Xml)] + string EchoWithGetPath(string message); +} + +public partial class Binding_WebHttp_WebHttpBindingTests : ConditionalWcfTest +{ + [WcfFact] + [OuterLoop] + [Condition(nameof(Run_With_CoreWCFService))] + public static void DefaultSettings_EchoWithGet_Xml_RoundTrips_String() + { + WebChannelFactory factory = null; + IWcfWebHttpService serviceProxy = null; + const string testString = "Hello"; + try + { + // *** SETUP *** \\ + WebHttpBinding binding = new WebHttpBinding(); + factory = new WebChannelFactory( + binding, + new Uri(Endpoints.HttpBaseAddress_WebHttp)); + serviceProxy = factory.CreateChannel(); + + // *** EXECUTE *** \\ + string result = serviceProxy.EchoWithGet(testString); + + // *** VALIDATE *** \\ + Assert.Equal(testString, result); + + // *** CLEANUP *** \\ + ((ICommunicationObject)serviceProxy).Close(); + factory.Close(); + } + finally + { + ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory); + } + } + + [WcfFact] + [OuterLoop] + [Condition(nameof(Run_With_CoreWCFService))] + public static void DefaultSettings_EchoWithGetJson_Json_RoundTrips_String() + { + WebChannelFactory factory = null; + IWcfWebHttpService serviceProxy = null; + const string testString = "Hello-JSON"; + try + { + WebHttpBinding binding = new WebHttpBinding(); + factory = new WebChannelFactory( + binding, + new Uri(Endpoints.HttpBaseAddress_WebHttp)); + serviceProxy = factory.CreateChannel(); + + string result = serviceProxy.EchoWithGetJson(testString); + + Assert.Equal(testString, result); + + ((ICommunicationObject)serviceProxy).Close(); + factory.Close(); + } + finally + { + ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory); + } + } + + [WcfFact] + [OuterLoop] + [Condition(nameof(Run_With_CoreWCFService))] + public static void DefaultSettings_EchoWithPost_Xml_RoundTrips_String() + { + WebChannelFactory factory = null; + IWcfWebHttpService serviceProxy = null; + const string testString = "Hello-POST"; + try + { + WebHttpBinding binding = new WebHttpBinding(); + factory = new WebChannelFactory( + binding, + new Uri(Endpoints.HttpBaseAddress_WebHttp)); + serviceProxy = factory.CreateChannel(); + + string result = serviceProxy.EchoWithPost(testString); + + Assert.Equal(testString, result); + + ((ICommunicationObject)serviceProxy).Close(); + factory.Close(); + } + finally + { + ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory); + } + } + + [WcfFact] + [OuterLoop] + [Condition(nameof(Run_With_CoreWCFService))] + public static void DefaultSettings_EchoWithGetPath_PathVar_RoundTrips_String() + { + WebChannelFactory factory = null; + IWcfWebHttpService serviceProxy = null; + const string testString = "Hello-PATH"; + try + { + WebHttpBinding binding = new WebHttpBinding(); + factory = new WebChannelFactory( + binding, + new Uri(Endpoints.HttpBaseAddress_WebHttp)); + serviceProxy = factory.CreateChannel(); + + string result = serviceProxy.EchoWithGetPath(testString); + + Assert.Equal(testString, result); + + ((ICommunicationObject)serviceProxy).Close(); + factory.Close(); + } + finally + { + ScenarioTestHelpers.CloseCommunicationObjects((ICommunicationObject)serviceProxy, factory); + } + } + + // ---- Unit tests (no network) --------------------------------------- + // + // These do not require an outer-loop test service. They validate that + // the binding, factory, and behavior can be constructed and composed. + + [WcfFact] + public static void WebHttpBinding_CanBeConstructed() + { + WebHttpBinding binding = new WebHttpBinding(); + Assert.NotNull(binding); + Assert.Equal("http", binding.Scheme); + Assert.Equal(WebHttpSecurityMode.None, binding.Security.Mode); + } + + [WcfFact] + public static void WebHttpBinding_TransportMode_UsesHttps() + { + WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.Transport); + Assert.Equal("https", binding.Scheme); + } + + [WcfFact] + public static void WebChannelFactory_Endpoint_HasWebHttpBinding() + { + WebHttpBinding binding = new WebHttpBinding(); + using var factory = new WebChannelFactory( + binding, new Uri("http://localhost/dummy/")); + ServiceEndpoint endpoint = factory.Endpoint; + Assert.NotNull(endpoint); + Assert.IsType(endpoint.Binding); + } + + // Verify AllowCookies flows to BOTH the HTTP and HTTPS transport binding + // elements (WebHttpBinding wraps both). This is how WSHttpBinding / + // HttpBindingBase already model shared HTTP settings. + [WcfFact] + public static void WebHttpBinding_AllowCookies_PropagatesToBothTransports() + { + WebHttpBinding binding = new WebHttpBinding(); + Assert.False(binding.AllowCookies); + + binding.AllowCookies = true; + AssertTransportPropertyFlows(binding, (http, https) => + { + Assert.True(http.AllowCookies); + Assert.True(https.AllowCookies); + }); + } + + [WcfFact] + public static void WebHttpBinding_ProxyAddress_PropagatesToBothTransports() + { + WebHttpBinding binding = new WebHttpBinding(); + Assert.Null(binding.ProxyAddress); + + var proxy = new Uri("http://proxy.contoso.example:8080/"); + binding.ProxyAddress = proxy; + AssertTransportPropertyFlows(binding, (http, https) => + { + Assert.Equal(proxy, http.ProxyAddress); + Assert.Equal(proxy, https.ProxyAddress); + }); + } + + [WcfFact] + public static void WebHttpBinding_UseDefaultWebProxy_And_BypassProxyOnLocal_PropagateToBothTransports() + { + WebHttpBinding binding = new WebHttpBinding(); + Assert.True(binding.UseDefaultWebProxy); + Assert.False(binding.BypassProxyOnLocal); + + binding.UseDefaultWebProxy = false; + binding.BypassProxyOnLocal = true; + AssertTransportPropertyFlows(binding, (http, https) => + { + Assert.False(http.UseDefaultWebProxy); + Assert.False(https.UseDefaultWebProxy); + Assert.True(http.BypassProxyOnLocal); + Assert.True(https.BypassProxyOnLocal); + }); + } + + // Verify Security.Transport.ProxyCredentialType is mapped onto the + // transport's ProxyAuthenticationScheme so HttpChannelFactory can + // authenticate against an explicit proxy. Uses TransportCredentialOnly + // because that's the mode where WebHttpSecurity actually runs + // HttpTransportHelpers.ConfigureAuthentication against the HTTP + // transport element. + [WcfTheory] + [InlineData(HttpProxyCredentialType.None, System.Net.AuthenticationSchemes.Anonymous)] + [InlineData(HttpProxyCredentialType.Basic, System.Net.AuthenticationSchemes.Basic)] + [InlineData(HttpProxyCredentialType.Digest, System.Net.AuthenticationSchemes.Digest)] + [InlineData(HttpProxyCredentialType.Ntlm, System.Net.AuthenticationSchemes.Ntlm)] + [InlineData(HttpProxyCredentialType.Windows, System.Net.AuthenticationSchemes.Negotiate)] + public static void WebHttpBinding_ProxyCredentialType_FlowsToTransportProxyAuthenticationScheme( + HttpProxyCredentialType proxyCredential, System.Net.AuthenticationSchemes expectedScheme) + { + WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.TransportCredentialOnly); + binding.Security.Transport.ProxyCredentialType = proxyCredential; + + HttpTransportBindingElement httpBe = null; + foreach (var be in binding.CreateBindingElements()) + { + if (be is HttpTransportBindingElement http && !(be is HttpsTransportBindingElement)) + { + httpBe = http; + } + } + Assert.NotNull(httpBe); + Assert.Equal(expectedScheme, httpBe.ProxyAuthenticationScheme); + } + + // ClientCredentialType.InheritedFromHost is only valid on server hosts. + // Constructing a client channel factory with it should throw + // InvalidOperationException up front (matching .NET Framework), not fail + // deeper inside HttpTransportBindingElement with ArgumentException. + // We exercise the guard by calling binding.BuildChannelFactory directly + // — the same path ChannelFactory.CreateFactory() takes during Open(). + [WcfTheory] + [InlineData(WebHttpSecurityMode.Transport)] + [InlineData(WebHttpSecurityMode.TransportCredentialOnly)] + public static void WebHttpBinding_InheritedFromHost_ThrowsInvalidOperationExceptionAtFactoryCreation( + WebHttpSecurityMode mode) + { + WebHttpBinding binding = new WebHttpBinding(mode); + binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.InheritedFromHost; + + var ex = Assert.Throws(() => + binding.BuildChannelFactory()); + Assert.Contains("InheritedFromHost", ex.Message); + } + + // In WebHttpSecurityMode.None, InheritedFromHost is not applicable so + // the guard must NOT fire. + [WcfFact] + public static void WebHttpBinding_InheritedFromHost_DoesNotThrow_WhenSecurityModeIsNone() + { + WebHttpBinding binding = new WebHttpBinding(WebHttpSecurityMode.None); + binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.InheritedFromHost; + + // The guard doesn't apply in None mode, so BuildChannelFactory itself + // should succeed (although downstream HttpTransportBindingElement may + // still reject the resulting AuthenticationSchemes.None). We only + // assert that our guard doesn't fire. + try + { + var factory = binding.BuildChannelFactory(); + factory.Close(); + } + catch (InvalidOperationException ex) when (ex.Message.Contains("InheritedFromHost")) + { + Assert.Fail("Guard should not fire in WebHttpSecurityMode.None"); + } + catch + { + // Any other exception is unrelated to our guard and acceptable. + } + } + + // Walk both the HTTP and HTTPS transport elements the binding owns and + // invoke assertions against them. We CreateBindingElements() for both + // security modes (None -> yields HTTP, Transport -> yields HTTPS) so + // both underlying elements are observed. + private static void AssertTransportPropertyFlows( + WebHttpBinding binding, Action assertions) + { + HttpTransportBindingElement httpBe = null; + HttpsTransportBindingElement httpsBe = null; + + binding.Security.Mode = WebHttpSecurityMode.None; + foreach (var be in binding.CreateBindingElements()) + { + if (be is HttpsTransportBindingElement https) httpsBe = https; + else if (be is HttpTransportBindingElement http) httpBe = http; + } + binding.Security.Mode = WebHttpSecurityMode.Transport; + foreach (var be in binding.CreateBindingElements()) + { + if (be is HttpsTransportBindingElement https) httpsBe = https; + else if (be is HttpTransportBindingElement http) httpBe = http; + } + + Assert.NotNull(httpBe); + Assert.NotNull(httpsBe); + assertions(httpBe, httpsBe); + } + + // Test-only helper for the 3 WebHttpBinding_*_RoundTripsAgainstLocalHttpListener + // regression tests. Picks a random loopback port in the Windows dynamic / + // ephemeral range (49152-65535 per RFC 6335), then starts an HttpListener + // on it. Retries up to MaxPortRetries times to survive transient port + // collisions. Fails loudly via Assert.Fail if no port works within the + // budget, so the tests can NEVER silently skip on a busy-port machine + // and mask a regression (flagged by Gemini 3.1 Pro during multi-model + // code review of PR #5959). + private const int MaxPortRetries = 10; + + private static (System.Net.HttpListener listener, string baseUrl) StartLoopbackHttpListener() + { + var random = new Random(); + var errors = new System.Collections.Generic.List(); + for (int attempt = 1; attempt <= MaxPortRetries; attempt++) + { + int port = random.Next(49152, 65536); + string url = "http://127.0.0.1:" + port + "/WebHttp.svc/"; + var listener = new System.Net.HttpListener(); + listener.Prefixes.Add(url); + try + { + listener.Start(); + return (listener, url); + } + catch (System.Net.HttpListenerException ex) + { + errors.Add("attempt " + attempt + " port " + port + + ": " + ex.ErrorCode + "/" + ex.Message); + } + } + Assert.Fail( + "Unable to find a random port number after " + MaxPortRetries + + " attempts. Errors: " + string.Join("; ", errors)); + return default; // unreachable + } + + // Test 1 of 3 that use StartLoopbackHttpListener - see the helper for the + // rationale (random port + retry + fail-loud, per code-review of PR #5959). + [WcfFact] + public static void WebHttpBinding_RoundTripsAgainstLocalHttpListener() + { + var (listener, baseUrl) = StartLoopbackHttpListener(); + string capturedUrl = null; + var done = new System.Threading.ManualResetEventSlim(); + + System.Threading.Tasks.Task.Run(() => + { + try + { + var ctx = listener.GetContext(); + capturedUrl = ctx.Request.Url.AbsoluteUri; + ctx.Response.ContentType = "application/xml; charset=utf-8"; + byte[] body = System.Text.Encoding.UTF8.GetBytes( + "Hello-PATH"); + ctx.Response.OutputStream.Write(body, 0, body.Length); + ctx.Response.OutputStream.Close(); + } + catch { } + finally { done.Set(); } + }); + + WebHttpBinding binding = new WebHttpBinding(); + var factory = new WebChannelFactory(binding, new Uri(baseUrl)); + IWcfWebHttpService channel = factory.CreateChannel(); + string result = null; + try + { + result = channel.EchoWithGetPath("Hello-PATH"); + done.Wait(TimeSpan.FromSeconds(10)); + } + finally + { + try { ((ICommunicationObject)channel).Close(); } catch { } + try { factory.Close(); } catch { } + try { listener.Stop(); } catch { } + } + + Assert.Equal(baseUrl + "EchoWithGetPath/Hello-PATH", capturedUrl); + Assert.Equal("Hello-PATH", result); + } + + // Regression test for the JSON reply-deserialization path: when an + // operation declares ResponseFormat=Json, the client must use the JSON + // formatter to read the body, not DataContractSerializer. + // Test 2 of 3 that use StartLoopbackHttpListener - see the helper for the + // rationale (random port + retry + fail-loud, per code-review of PR #5959). + [WcfFact] + public static void WebHttpBinding_JsonReply_RoundTripsAgainstLocalHttpListener() + { + var (listener, baseUrl) = StartLoopbackHttpListener(); + var done = new System.Threading.ManualResetEventSlim(); + + System.Threading.Tasks.Task.Run(() => + { + try + { + var ctx = listener.GetContext(); + ctx.Response.ContentType = "application/json; charset=utf-8"; + byte[] body = System.Text.Encoding.UTF8.GetBytes("\"Hello-JSON\""); + ctx.Response.OutputStream.Write(body, 0, body.Length); + ctx.Response.OutputStream.Close(); + } + catch { } + finally { done.Set(); } + }); + + WebHttpBinding binding = new WebHttpBinding(); + var factory = new WebChannelFactory(binding, new Uri(baseUrl)); + IWcfWebHttpService channel = factory.CreateChannel(); + string result = null; + try + { + result = channel.EchoWithGetJson("Hello-JSON"); + done.Wait(TimeSpan.FromSeconds(10)); + } + finally + { + try { ((ICommunicationObject)channel).Close(); } catch { } + try { factory.Close(); } catch { } + try { listener.Stop(); } catch { } + } + + Assert.Equal("Hello-JSON", result); + } + + // End-to-end regression test for AllowCookies: with AllowCookies=true, + // the client's underlying HttpMessageHandler should retain the cookie + // set by the server on the first response and echo it back on the + // second request. With AllowCookies=false (the default) the cookie + // is NOT echoed back. Runs against a local HttpListener so it needs + // no external service. + // Test 3 of 3 that use StartLoopbackHttpListener - see the helper for the + // rationale (random port + retry + fail-loud, per code-review of PR #5959). + [WcfFact] + public static void WebHttpBinding_AllowCookies_RoundTripsCookieHeader() + { + var (listener, baseUrl) = StartLoopbackHttpListener(); + string secondRequestCookieHeader = null; + var done = new System.Threading.ManualResetEventSlim(); + + System.Threading.Tasks.Task.Run(() => + { + try + { + // First request: set a cookie. + var ctx1 = listener.GetContext(); + ctx1.Response.Headers.Add("Set-Cookie", "sid=abc123; Path=/"); + ctx1.Response.ContentType = "application/xml; charset=utf-8"; + byte[] body1 = System.Text.Encoding.UTF8.GetBytes( + "first"); + ctx1.Response.OutputStream.Write(body1, 0, body1.Length); + ctx1.Response.OutputStream.Close(); + + // Second request: capture Cookie header. + var ctx2 = listener.GetContext(); + secondRequestCookieHeader = ctx2.Request.Headers["Cookie"]; + ctx2.Response.ContentType = "application/xml; charset=utf-8"; + byte[] body2 = System.Text.Encoding.UTF8.GetBytes( + "second"); + ctx2.Response.OutputStream.Write(body2, 0, body2.Length); + ctx2.Response.OutputStream.Close(); + } + catch { } + finally { done.Set(); } + }); + + WebHttpBinding binding = new WebHttpBinding { AllowCookies = true }; + var factory = new WebChannelFactory(binding, new Uri(baseUrl)); + IWcfWebHttpService channel = factory.CreateChannel(); + try + { + channel.EchoWithGetPath("first"); + channel.EchoWithGetPath("second"); + done.Wait(TimeSpan.FromSeconds(10)); + } + finally + { + try { ((ICommunicationObject)channel).Close(); } catch { } + try { factory.Close(); } catch { } + try { listener.Stop(); } catch { } + } + + Assert.NotNull(secondRequestCookieHeader); + Assert.Contains("sid=abc123", secondRequestCookieHeader); + } +} diff --git a/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/TestDefinitionHelper.cs b/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/TestDefinitionHelper.cs index a9b1f017fa7..5455973341a 100644 --- a/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/TestDefinitionHelper.cs +++ b/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/TestDefinitionHelper.cs @@ -237,7 +237,14 @@ internal static async Task StartHosts(bool useWebSocket) if (!useWebSocket && (schema == ServiceSchema.WS || schema == ServiceSchema.WSS)) continue; string basePath = serviceTestHostOptionsDict[serviceHostTypeName].endpointBasePath[schema]; - string endpointAddress = string.Format("{0}/{1}", basePath, endpoint.Address); + // When the endpoint Address is empty (e.g. for WebHttpBinding hosts + // that anchor URI templates at the base path), avoid appending a + // trailing slash. CoreWCF's WebHttp routing builds prefix matches + // off the registered URI and a trailing slash causes everything + // except the bare base address to 404. + string endpointAddress = string.IsNullOrEmpty(endpoint.Address) + ? basePath + : string.Format("{0}/{1}", basePath, endpoint.Address); serviceBuilder.AddServiceEndpoint(serviceHost.ServiceType, endpoint.ContractType, endpoint.Binding, new Uri(endpointAddress, UriKind.RelativeOrAbsolute), null); } diff --git a/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/WebHttpTestServiceHost.cs b/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/WebHttpTestServiceHost.cs new file mode 100644 index 00000000000..ae4dea64e6c --- /dev/null +++ b/src/System.Private.ServiceModel/tools/IISHostedWcfService/App_code/testhosts/WebHttpTestServiceHost.cs @@ -0,0 +1,107 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#if NET +using CoreWCF; +using CoreWCF.Channels; +using CoreWCF.Web; +#else +using System; +using System.ServiceModel; +using System.ServiceModel.Channels; +using System.ServiceModel.Web; +#endif + +namespace WcfService +{ + // ---- Contract -------------------------------------------------------- + // Shared between server (CoreWCF on .NET, full .NET FX on net4xx via IIS) + // and client (this repo's new System.ServiceModel.Web). The attribute + // parameter names match across CoreWCF.Web.WebGet/WebInvoke and + // System.ServiceModel.Web.WebGet/WebInvoke, so a single contract works + // for both. + [ServiceContract] + public interface IWcfWebHttpService + { + [OperationContract] + [WebGet(UriTemplate = "EchoWithGet?message={message}", + BodyStyle = WebMessageBodyStyle.Bare, + ResponseFormat = WebMessageFormat.Xml)] + string EchoWithGet(string message); + + [OperationContract] + [WebGet(UriTemplate = "EchoWithGetJson?message={message}", + BodyStyle = WebMessageBodyStyle.Bare, + ResponseFormat = WebMessageFormat.Json)] + string EchoWithGetJson(string message); + + [OperationContract] + [WebInvoke(Method = "POST", UriTemplate = "EchoWithPost", + BodyStyle = WebMessageBodyStyle.Bare, + ResponseFormat = WebMessageFormat.Xml, + RequestFormat = WebMessageFormat.Xml)] + string EchoWithPost(string message); + + [OperationContract] + [WebInvoke(Method = "POST", UriTemplate = "EchoWithPostJson", + BodyStyle = WebMessageBodyStyle.Bare, + ResponseFormat = WebMessageFormat.Json, + RequestFormat = WebMessageFormat.Json)] + string EchoWithPostJson(string message); + + [OperationContract] + [WebGet(UriTemplate = "EchoWithGetPath/{message}", + BodyStyle = WebMessageBodyStyle.Bare, + ResponseFormat = WebMessageFormat.Xml)] + string EchoWithGetPath(string message); + } + + // ---- Implementation -------------------------------------------------- + public class WcfWebHttpService : IWcfWebHttpService + { + public string EchoWithGet(string message) { return message; } + public string EchoWithGetJson(string message) { return message; } + public string EchoWithPost(string message) { return message; } + public string EchoWithPostJson(string message) { return message; } + public string EchoWithGetPath(string message) { return message; } + } + + // ---- Test Host ------------------------------------------------------- + // + // Registers a CoreWCF (or IIS .NET FX) REST endpoint at: + // HTTP -> http://:8081/WebHttp.svc/ + // + // On the CoreWCF (#if NET) path, TestDefinitionHelper.StartHosts() already + // calls services.AddServiceModelWebServices(), so the WebHttpServiceBehavior + // in CoreWCF.WebHttp will automatically install a WebHttpBehavior on this + // endpoint when it sees the WebMessageEncodingBindingElement that the + // WebHttpBinding produces. + // + // On the .NET FX path we need to install WebHttpBehavior manually since + // TestServiceHostBase does not. + [TestServiceDefinition(BasePath = "WebHttp.svc", Schema = ServiceSchema.HTTP)] + public class WebHttpTestServiceHost : TestServiceHostBase + { + protected override string Address { get { return ""; } } + + protected override Binding GetBinding() { return new WebHttpBinding(); } + + public WebHttpTestServiceHost(params Uri[] baseAddresses) + : base(typeof(WcfWebHttpService), baseAddresses) { } + +#if !NET + protected override void ApplyConfiguration() + { + base.ApplyConfiguration(); + foreach (var ep in Description.Endpoints) + { + if (ep.Binding is WebHttpBinding && ep.Behaviors.Find() == null) + { + ep.Behaviors.Add(new System.ServiceModel.Description.WebHttpBehavior()); + } + } + } +#endif + } +} diff --git a/src/System.ServiceModel.Http/src/Resources/Strings.resx b/src/System.ServiceModel.Http/src/Resources/Strings.resx index 6ac5023c405..6007c6c1550 100644 --- a/src/System.ServiceModel.Http/src/Resources/Strings.resx +++ b/src/System.ServiceModel.Http/src/Resources/Strings.resx @@ -250,7 +250,7 @@ Extended protection is not supported on this platform. Please install the appropriate patch or change the ExtendedProtectionPolicy on the Binding or BindingElement to a value with a PolicyEnforcement value of "Never" or "WhenSupported". - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. The value '{1}' is not supported in this context for the binding security property '{0}'. diff --git a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.cs.xlf b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.cs.xlf index 3e5ed772ca5..6a4103fa3cf 100644 --- a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.cs.xlf +++ b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.cs.xlf @@ -113,8 +113,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - Typ ClientCredentialType {0} může být použit pouze na straně serveru, nikoli na straně klienta. Namísto toho použijte jednu z hodnot None, Basic, Client, Digest, Ntlm, Windows. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + Typ ClientCredentialType {0} může být použit pouze na straně serveru, nikoli na straně klienta. Namísto toho použijte jednu z hodnot None, Basic, Client, Digest, Ntlm, Windows. diff --git a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.de.xlf b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.de.xlf index 96ae0eef208..979c79d03f7 100644 --- a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.de.xlf +++ b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.de.xlf @@ -113,8 +113,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - Der ClientCredentialType "{0}" kann nur auf dem Server und nicht auf dem Client verwendet werden. Verwenden Sie stattdessen einen der folgenden Werte: None, Basic, Client, Digest, Ntlm, Windows. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + Der ClientCredentialType "{0}" kann nur auf dem Server und nicht auf dem Client verwendet werden. Verwenden Sie stattdessen einen der folgenden Werte: None, Basic, Client, Digest, Ntlm, Windows. diff --git a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.es.xlf b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.es.xlf index 3728c8dd124..c588433b723 100644 --- a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.es.xlf +++ b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.es.xlf @@ -113,8 +113,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - Solo se puede usar ClientCredentialType "{0}" en el lado del servidor y no en el del cliente. Use en su lugar los siguientes valores: "None, Basic, Client, Digest, Ntlm, Windows". + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + Solo se puede usar ClientCredentialType "{0}" en el lado del servidor y no en el del cliente. Use en su lugar los siguientes valores: "None, Basic, Client, Digest, Ntlm, Windows". diff --git a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.fr.xlf b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.fr.xlf index 5f48d297549..65ad7919fb2 100644 --- a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.fr.xlf +++ b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.fr.xlf @@ -113,8 +113,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - Le ClientCredentialType '{0}' peut uniquement être utilisé côté serveur, et non côté client. Utilisez une des valeurs suivantes à la place : 'None, Basic, Client, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + Le ClientCredentialType '{0}' peut uniquement être utilisé côté serveur, et non côté client. Utilisez une des valeurs suivantes à la place : 'None, Basic, Client, Digest, Ntlm, Windows'. diff --git a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.it.xlf b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.it.xlf index 49076ebb27d..23ec4dc38a8 100644 --- a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.it.xlf +++ b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.it.xlf @@ -113,8 +113,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - L'elemento ClientCredentialType '{0}' può essere usato solo per il server e non per il client. Usare uno dei valori seguenti: 'None, Basic, Client, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + L'elemento ClientCredentialType '{0}' può essere usato solo per il server e non per il client. Usare uno dei valori seguenti: 'None, Basic, Client, Digest, Ntlm, Windows'. diff --git a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.ja.xlf b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.ja.xlf index 56b1a2f0d70..d3ab69aed50 100644 --- a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.ja.xlf +++ b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.ja.xlf @@ -113,8 +113,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - ClientCredentialType '{0}' を使用できるのはサーバー側のみで、クライアント側では使用できません。'None'、'Basic'、'Client'、'Digest'、'Ntlm'、'Windows' のいずれかの値を代わりに使用してください。 + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' を使用できるのはサーバー側のみで、クライアント側では使用できません。'None'、'Basic'、'Client'、'Digest'、'Ntlm'、'Windows' のいずれかの値を代わりに使用してください。 diff --git a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.ko.xlf b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.ko.xlf index 2c4bb87e9d6..275a16bf9bd 100644 --- a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.ko.xlf +++ b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.ko.xlf @@ -113,8 +113,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - ClientCredentialType '{0}'은(는) 클라이언트 쪽이 아닌 서버 쪽에서만 사용할 수 있습니다. 대신 '없음, 기본, 클라이언트, 다이제스트, NTLM, Windows' 값 중 하나를 사용하세요. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}'은(는) 클라이언트 쪽이 아닌 서버 쪽에서만 사용할 수 있습니다. 대신 '없음, 기본, 클라이언트, 다이제스트, NTLM, Windows' 값 중 하나를 사용하세요. diff --git a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.pl.xlf b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.pl.xlf index 96297b597ba..2b10a78e1c1 100644 --- a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.pl.xlf +++ b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.pl.xlf @@ -113,8 +113,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - Właściwości ClientCredentialType o wartości „{0}” można użyć tylko po stronie serwera, a nie po stronie klienta. Zamiast niej użyj jednej z następujących wartości: „None, Basic, Client, Digest, Ntlm, Windows”. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + Właściwości ClientCredentialType o wartości „{0}” można użyć tylko po stronie serwera, a nie po stronie klienta. Zamiast niej użyj jednej z następujących wartości: „None, Basic, Client, Digest, Ntlm, Windows”. diff --git a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.pt-BR.xlf b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.pt-BR.xlf index 9d046cd6329..bac755d8aeb 100644 --- a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.pt-BR.xlf +++ b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.pt-BR.xlf @@ -113,8 +113,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - ClientCredentialType '{0}' somente pode ser usado no lado do servidor, não no lado do cliente. Use um dos seguintes valores: 'None, Basic, Client, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' somente pode ser usado no lado do servidor, não no lado do cliente. Use um dos seguintes valores: 'None, Basic, Client, Digest, Ntlm, Windows'. diff --git a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.ru.xlf b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.ru.xlf index 66ddad72aca..9e7d23ff0bd 100644 --- a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.ru.xlf +++ b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.ru.xlf @@ -113,8 +113,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - Тип ClientCredentialType "{0}" может использоваться на стороне сервера, но не клиента. Используйте вместо этого одно из следующих значений: None, Basic, Client, Digest, Ntlm, Windows. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + Тип ClientCredentialType "{0}" может использоваться на стороне сервера, но не клиента. Используйте вместо этого одно из следующих значений: None, Basic, Client, Digest, Ntlm, Windows. diff --git a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.tr.xlf b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.tr.xlf index fcb5d5a876f..37462c934b5 100644 --- a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.tr.xlf +++ b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.tr.xlf @@ -113,8 +113,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - ClientCredentialType '{0}' yalnızca sunucu tarafında kullanılabilir, istemci tarafında kullanılamaz. Lütfen şu değerlerden birini kullanın: 'None, Basic, Client, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' yalnızca sunucu tarafında kullanılabilir, istemci tarafında kullanılamaz. Lütfen şu değerlerden birini kullanın: 'None, Basic, Client, Digest, Ntlm, Windows'. diff --git a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.zh-Hans.xlf b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.zh-Hans.xlf index 3cf60175219..9cbf4182e48 100644 --- a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.zh-Hans.xlf @@ -113,8 +113,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - ClientCredentialType“{0}”只能在服务器端使用,而不能在客户端使用。请改用以下值之一: None、Basic、Client、Digest、Ntlm、Windows。 + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType“{0}”只能在服务器端使用,而不能在客户端使用。请改用以下值之一: None、Basic、Client、Digest、Ntlm、Windows。 diff --git a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.zh-Hant.xlf b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.zh-Hant.xlf index 71206117018..c6cbb20da1a 100644 --- a/src/System.ServiceModel.Http/src/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/System.ServiceModel.Http/src/Resources/xlf/Strings.zh-Hant.xlf @@ -113,8 +113,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - ClientCredentialType '{0}' 只能在伺服器端使用,而非用戶端。請使用下列其中一個值來取代 'None, Basic, Client, Digest, Ntlm, Windows'。 + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' 只能在伺服器端使用,而非用戶端。請使用下列其中一個值來取代 'None, Basic, Client, Digest, Ntlm, Windows'。 diff --git a/src/System.ServiceModel.Http/src/System.ServiceModel.Http.csproj b/src/System.ServiceModel.Http/src/System.ServiceModel.Http.csproj index 751b86e8168..9666d5002fe 100644 --- a/src/System.ServiceModel.Http/src/System.ServiceModel.Http.csproj +++ b/src/System.ServiceModel.Http/src/System.ServiceModel.Http.csproj @@ -15,6 +15,10 @@ + + + + diff --git a/src/System.ServiceModel.Primitives/src/Resources/Strings.resx b/src/System.ServiceModel.Primitives/src/Resources/Strings.resx index 216300e5e7a..069ecfd2922 100644 --- a/src/System.ServiceModel.Primitives/src/Resources/Strings.resx +++ b/src/System.ServiceModel.Primitives/src/Resources/Strings.resx @@ -910,7 +910,7 @@ Extended protection is not supported on this platform. Please install the appropriate patch or change the ExtendedProtectionPolicy on the Binding or BindingElement to a value with a PolicyEnforcement value of "Never" or "WhenSupported". - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. The transport configured on this binding does not appear to support the CompressionFormat specified ({0}) on the message encoder. To resolve this issue, set the CompressionFormat on the {1} to '{2}' or use a different transport. diff --git a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.cs.xlf b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.cs.xlf index 9656942af8e..c080ee6bf02 100644 --- a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.cs.xlf +++ b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.cs.xlf @@ -1203,8 +1203,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - Typ ClientCredentialType {0} může být použit pouze na straně serveru, nikoli na straně klienta. Namísto toho použijte jednu z hodnot None, Basic, Client, Digest, Ntlm, Windows. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + Typ ClientCredentialType {0} může být použit pouze na straně serveru, nikoli na straně klienta. Namísto toho použijte jednu z hodnot None, Basic, Client, Digest, Ntlm, Windows. diff --git a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.de.xlf b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.de.xlf index 3e62a6f1fc3..d88b4a052e3 100644 --- a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.de.xlf +++ b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.de.xlf @@ -1203,8 +1203,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - Der ClientCredentialType "{0}" kann nur auf dem Server und nicht auf dem Client verwendet werden. Verwenden Sie stattdessen einen der folgenden Werte: None, Basic, Client, Digest, Ntlm, Windows. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + Der ClientCredentialType "{0}" kann nur auf dem Server und nicht auf dem Client verwendet werden. Verwenden Sie stattdessen einen der folgenden Werte: None, Basic, Client, Digest, Ntlm, Windows. diff --git a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.es.xlf b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.es.xlf index 21df1384234..0777ace7257 100644 --- a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.es.xlf +++ b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.es.xlf @@ -1203,8 +1203,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - Solo se puede usar ClientCredentialType "{0}" en el lado del servidor y no en el del cliente. Use en su lugar los siguientes valores: "None, Basic, Client, Digest, Ntlm, Windows". + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + Solo se puede usar ClientCredentialType "{0}" en el lado del servidor y no en el del cliente. Use en su lugar los siguientes valores: "None, Basic, Client, Digest, Ntlm, Windows". diff --git a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.fr.xlf b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.fr.xlf index fb424c7785f..d19224f87bd 100644 --- a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.fr.xlf +++ b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.fr.xlf @@ -1203,8 +1203,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - Le ClientCredentialType '{0}' peut uniquement être utilisé côté serveur, et non côté client. Utilisez une des valeurs suivantes à la place : 'None, Basic, Client, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + Le ClientCredentialType '{0}' peut uniquement être utilisé côté serveur, et non côté client. Utilisez une des valeurs suivantes à la place : 'None, Basic, Client, Digest, Ntlm, Windows'. diff --git a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.it.xlf b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.it.xlf index 04a0482e4d3..f02df2c3d09 100644 --- a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.it.xlf +++ b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.it.xlf @@ -1203,8 +1203,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - L'elemento ClientCredentialType '{0}' può essere usato solo per il server e non per il client. Usare uno dei valori seguenti: 'None, Basic, Client, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + L'elemento ClientCredentialType '{0}' può essere usato solo per il server e non per il client. Usare uno dei valori seguenti: 'None, Basic, Client, Digest, Ntlm, Windows'. diff --git a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.ja.xlf b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.ja.xlf index 7bf5480362e..95d5d33ff62 100644 --- a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.ja.xlf +++ b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.ja.xlf @@ -1203,8 +1203,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - ClientCredentialType '{0}' を使用できるのはサーバー側のみで、クライアント側では使用できません。'None'、'Basic'、'Client'、'Digest'、'Ntlm'、'Windows' のいずれかの値を代わりに使用してください。 + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' を使用できるのはサーバー側のみで、クライアント側では使用できません。'None'、'Basic'、'Client'、'Digest'、'Ntlm'、'Windows' のいずれかの値を代わりに使用してください。 diff --git a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.ko.xlf b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.ko.xlf index 024993b7d09..2c3490f8bc4 100644 --- a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.ko.xlf +++ b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.ko.xlf @@ -1203,8 +1203,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - ClientCredentialType '{0}'은(는) 클라이언트 쪽이 아닌 서버 쪽에서만 사용할 수 있습니다. 대신 '없음, 기본, 클라이언트, 다이제스트, NTLM, Windows' 값 중 하나를 사용하세요. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}'은(는) 클라이언트 쪽이 아닌 서버 쪽에서만 사용할 수 있습니다. 대신 '없음, 기본, 클라이언트, 다이제스트, NTLM, Windows' 값 중 하나를 사용하세요. diff --git a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.pl.xlf b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.pl.xlf index f0e43de7532..aef433f244b 100644 --- a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.pl.xlf +++ b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.pl.xlf @@ -1203,8 +1203,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - Właściwości ClientCredentialType o wartości „{0}” można użyć tylko po stronie serwera, a nie po stronie klienta. Zamiast niej użyj jednej z następujących wartości: „None, Basic, Client, Digest, Ntlm, Windows”. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + Właściwości ClientCredentialType o wartości „{0}” można użyć tylko po stronie serwera, a nie po stronie klienta. Zamiast niej użyj jednej z następujących wartości: „None, Basic, Client, Digest, Ntlm, Windows”. diff --git a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.pt-BR.xlf b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.pt-BR.xlf index 81006e9d0db..92338005af4 100644 --- a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.pt-BR.xlf +++ b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.pt-BR.xlf @@ -1203,8 +1203,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - ClientCredentialType '{0}' somente pode ser usado no lado do servidor, não no lado do cliente. Use um dos seguintes valores: 'None, Basic, Client, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' somente pode ser usado no lado do servidor, não no lado do cliente. Use um dos seguintes valores: 'None, Basic, Client, Digest, Ntlm, Windows'. diff --git a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.ru.xlf b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.ru.xlf index 11640ff72f9..df06527b37c 100644 --- a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.ru.xlf +++ b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.ru.xlf @@ -1203,8 +1203,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - Тип ClientCredentialType "{0}" может использоваться на стороне сервера, но не клиента. Используйте вместо этого одно из следующих значений: None, Basic, Client, Digest, Ntlm, Windows. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + Тип ClientCredentialType "{0}" может использоваться на стороне сервера, но не клиента. Используйте вместо этого одно из следующих значений: None, Basic, Client, Digest, Ntlm, Windows. diff --git a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.tr.xlf b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.tr.xlf index a18c12a45d1..25e4ee4bee6 100644 --- a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.tr.xlf +++ b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.tr.xlf @@ -1203,8 +1203,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - ClientCredentialType '{0}' yalnızca sunucu tarafında kullanılabilir, istemci tarafında kullanılamaz. Lütfen şu değerlerden birini kullanın: 'None, Basic, Client, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' yalnızca sunucu tarafında kullanılabilir, istemci tarafında kullanılamaz. Lütfen şu değerlerden birini kullanın: 'None, Basic, Client, Digest, Ntlm, Windows'. diff --git a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.zh-Hans.xlf b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.zh-Hans.xlf index 2b4e6e090fd..9403a08a150 100644 --- a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.zh-Hans.xlf @@ -1203,8 +1203,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - ClientCredentialType“{0}”只能在服务器端使用,而不能在客户端使用。请改用以下值之一: None、Basic、Client、Digest、Ntlm、Windows。 + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType“{0}”只能在服务器端使用,而不能在客户端使用。请改用以下值之一: None、Basic、Client、Digest、Ntlm、Windows。 diff --git a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.zh-Hant.xlf b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.zh-Hant.xlf index ba755efeae0..ac77162da72 100644 --- a/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/System.ServiceModel.Primitives/src/Resources/xlf/Strings.zh-Hant.xlf @@ -1203,8 +1203,8 @@ - ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Client, Digest, Ntlm, Windows'. - ClientCredentialType '{0}' 只能在伺服器端使用,而非用戶端。請使用下列其中一個值來取代 'None, Basic, Client, Digest, Ntlm, Windows'。 + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' 只能在伺服器端使用,而非用戶端。請使用下列其中一個值來取代 'None, Basic, Client, Digest, Ntlm, Windows'。 diff --git a/src/System.ServiceModel.Primitives/src/System.ServiceModel.Primitives.csproj b/src/System.ServiceModel.Primitives/src/System.ServiceModel.Primitives.csproj index 72f157b96ab..44d90989bd6 100644 --- a/src/System.ServiceModel.Primitives/src/System.ServiceModel.Primitives.csproj +++ b/src/System.ServiceModel.Primitives/src/System.ServiceModel.Primitives.csproj @@ -25,6 +25,7 @@ + diff --git a/src/System.ServiceModel.Web/src/Resources/Strings.resx b/src/System.ServiceModel.Web/src/Resources/Strings.resx new file mode 100644 index 00000000000..33dcec8e6d1 --- /dev/null +++ b/src/System.ServiceModel.Web/src/Resources/Strings.resx @@ -0,0 +1,558 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Object is read-only. + + + Bind parameters cannot be null or empty for path variable '{0}'. + + + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + + + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + + + UriTemplate.BindByName was called with an empty key in the parameters collection. + + + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + + + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + + + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + + + Cannot look up compound segment results before a successful Match has been performed. + + + The Defaults dictionary on the UriTemplate is immutable. + + + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + + + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + + + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + + + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + + + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + + + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + + + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + + + UriTemplate '{0}' has invalid variable declaration '{1}'. + + + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + + + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + + + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + + + UriTemplate '{0}' has a query string that ends in '&'. + + + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + + + UriTemplate '{0}' has a query parameter with an empty name. + + + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + + + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + + + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + + + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + + + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + + + The base address of the UriTemplateTable must be an absolute URI. + + + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + + + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + + + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + + + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + + + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + + + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + + + The base address of the UriTemplateTable must be an absolute URI. + + + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + + + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + + + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + + + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + + + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + + + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + + + WebMessageEncodingBindingElement only supports MessageVersion.None. + + + The value must be in the range [{0}, {1}]. + + + The maximum message size quota for outgoing messages ({0}) has been exceeded. + + + The message body is a Stream and cannot be re-read. + + + The message body is missing or empty. + + + The XmlReader used to read the message body is in an invalid read state '{0}'. + + + The MessageBuffer has been closed and can no longer be used. + + + The message has been closed and can no longer be used. + + + Unknown MessageVersion. + + + Unknown WebContentFormat '{0}'. + + + The value supplied must be non-negative. + + + The value supplied must be greater than zero. + + + WebBodyFormatMessageProperty(Format={0}) + + + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + + + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + + + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + + + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + + + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + + + Weak entity tags (W/"...") are not supported in this context. + + + The XmlBuffer's quota has been exceeded. + + + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + + + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + + + The size quota for this stream ({0}) has been exceeded. + + + This buffer cannot be returned to the buffer manager because it is the wrong size. + + + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + + + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + + + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + + + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + + + Cross domain javascript callback is not supported in authenticated services. + + + CrossDomainScriptAccessEnabled cannot be used in Clients. + + + A registration already exists for URI '{0}'. + + + Cannot process contentType. + + + Unrecognized charSet '{0}' in contentType. + + + The ServiceEndpoint's Address is null. Address must be an absolute uri. + + + This message formatter cannot be used to process response messages. + + + This message formatter cannot be used to process request messages. + + + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + + + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + + + Endpoint not found. + + + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + + + Method not allowed. + + + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + + + Request Error + + + Service + + + The server encountered an error processing the request. See server logs for more details. + + + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + + + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + + + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + + + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + + + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + + + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + + + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + + + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + + + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + + + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + + + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + The text encoding '{0}' used in the text message format is not supported. + + + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + + + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + + + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + + + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + + + The {0} object has been disposed. + + + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + + + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + + + The operation '{0}' does not support '{1}' as a response format. + + + Could not find operation name in the message properties. + + + This operation is supported only when the operation selector is of type '{0}'. + + + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + + + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + + + Read is not supported on this stream. + + + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + + + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + ReplyAlreadySent + + + The requestContext has been aborted. + + + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + + + Seek is not supported on this stream. + + + The formatter '{0}' does not support serializing replies. + + + The formatter '{0}' does not support serializing requests. + + + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + + + IAsyncResult not provided or of wrong type. + + + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + + + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + + + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + + + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + Argument {0} must be a non-negative timeout value. Provided value was {1}. + + + Argument {0} must be a positive timeout value. Provided value was {1}. + + + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + + + Type '{0}' is not supported by '{1}'. + + + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + + + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + + + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + + + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + + + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + + + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + + + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + + + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + + + The incoming HTTP request's URI '{0}' does not match any service operation. + + + New types cannot be registered with serializer manager after the service has been opened. + + + The '{0}' method is not supported by the stream. + + + The get accessor of the '{0}' property is not supported by the stream. + + + The set accessor of the '{0}' property is not supported by the stream. + + \ No newline at end of file diff --git a/src/System.ServiceModel.Web/src/Resources/xlf/Strings.cs.xlf b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.cs.xlf new file mode 100644 index 00000000000..5202e677bf0 --- /dev/null +++ b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.cs.xlf @@ -0,0 +1,827 @@ + + + + + + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + + + + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + + + + Bind parameters cannot be null or empty for path variable '{0}'. + Bind parameters cannot be null or empty for path variable '{0}'. + + + + This buffer cannot be returned to the buffer manager because it is the wrong size. + This buffer cannot be returned to the buffer manager because it is the wrong size. + + + + The size quota for this stream ({0}) has been exceeded. + The size quota for this stream ({0}) has been exceeded. + + + + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + + + + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + + + + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + + + + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + + + + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + + + + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + + + + Cross domain javascript callback is not supported in authenticated services. + Cross domain javascript callback is not supported in authenticated services. + + + + CrossDomainScriptAccessEnabled cannot be used in Clients. + CrossDomainScriptAccessEnabled cannot be used in Clients. + + + + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + + + + A registration already exists for URI '{0}'. + A registration already exists for URI '{0}'. + + + + Cannot process contentType. + Cannot process contentType. + + + + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + + + + Unrecognized charSet '{0}' in contentType. + Unrecognized charSet '{0}' in contentType. + + + + The ServiceEndpoint's Address is null. Address must be an absolute uri. + The ServiceEndpoint's Address is null. Address must be an absolute uri. + + + + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + + + + This message formatter cannot be used to process response messages. + This message formatter cannot be used to process response messages. + + + + This message formatter cannot be used to process request messages. + This message formatter cannot be used to process request messages. + + + + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + + + + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + + + + Endpoint not found. + Endpoint not found. + + + + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + + + + Method not allowed. + Method not allowed. + + + + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + + + + Request Error + Request Error + + + + Service + Service + + + + The server encountered an error processing the request. See server logs for more details. + The server encountered an error processing the request. See server logs for more details. + + + + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + + + + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + + + + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + + + + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + + + + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + + + + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + + + + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + + + + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + + + + WebMessageEncodingBindingElement only supports MessageVersion.None. + WebMessageEncodingBindingElement only supports MessageVersion.None. + + + + The value must be in the range [{0}, {1}]. + The value must be in the range [{0}, {1}]. + + + + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + + + + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + + + + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + + + + The maximum message size quota for outgoing messages ({0}) has been exceeded. + The maximum message size quota for outgoing messages ({0}) has been exceeded. + + + + The message body is a Stream and cannot be re-read. + The message body is a Stream and cannot be re-read. + + + + The message body is missing or empty. + The message body is missing or empty. + + + + The XmlReader used to read the message body is in an invalid read state '{0}'. + The XmlReader used to read the message body is in an invalid read state '{0}'. + + + + The MessageBuffer has been closed and can no longer be used. + The MessageBuffer has been closed and can no longer be used. + + + + The message has been closed and can no longer be used. + The message has been closed and can no longer be used. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + + + + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + The text encoding '{0}' used in the text message format is not supported. + The text encoding '{0}' used in the text message format is not supported. + + + + Unknown MessageVersion. + Unknown MessageVersion. + + + + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + + + + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + + + + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + + + + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + + + + The {0} object has been disposed. + The {0} object has been disposed. + + + + Object is read-only. + Object is read-only. + + + + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + + + + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + + + + The operation '{0}' does not support '{1}' as a response format. + The operation '{0}' does not support '{1}' as a response format. + + + + Could not find operation name in the message properties. + Could not find operation name in the message properties. + + + + This operation is supported only when the operation selector is of type '{0}'. + This operation is supported only when the operation selector is of type '{0}'. + + + + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + + + + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + + + + Read is not supported on this stream. + Read is not supported on this stream. + + + + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + + + + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + ReplyAlreadySent + ReplyAlreadySent + + + + The requestContext has been aborted. + The requestContext has been aborted. + + + + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + + + + IAsyncResult not provided or of wrong type. + IAsyncResult not provided or of wrong type. + + + + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + + + + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + + + + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + Seek is not supported on this stream. + Seek is not supported on this stream. + + + + The formatter '{0}' does not support serializing replies. + The formatter '{0}' does not support serializing replies. + + + + The formatter '{0}' does not support serializing requests. + The formatter '{0}' does not support serializing requests. + + + + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + + + + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + + + + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Argument {0} must be a non-negative timeout value. Provided value was {1}. + Argument {0} must be a non-negative timeout value. Provided value was {1}. + + + + Argument {0} must be a positive timeout value. Provided value was {1}. + Argument {0} must be a positive timeout value. Provided value was {1}. + + + + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + + + + Type '{0}' is not supported by '{1}'. + Type '{0}' is not supported by '{1}'. + + + + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + + + + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + + + + UriTemplate.BindByName was called with an empty key in the parameters collection. + UriTemplate.BindByName was called with an empty key in the parameters collection. + + + + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + + + + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + + + + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + + + + Cannot look up compound segment results before a successful Match has been performed. + Cannot look up compound segment results before a successful Match has been performed. + + + + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + + + + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + + + + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + + + + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + + + + The Defaults dictionary on the UriTemplate is immutable. + The Defaults dictionary on the UriTemplate is immutable. + + + + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + + + + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + + + + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + + + + UriTemplate '{0}' has invalid variable declaration '{1}'. + UriTemplate '{0}' has invalid variable declaration '{1}'. + + + + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + + + + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + + + + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + + + + UriTemplate '{0}' has a query string that ends in '&'. + UriTemplate '{0}' has a query string that ends in '&'. + + + + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + + + + UriTemplate '{0}' has a query parameter with an empty name. + UriTemplate '{0}' has a query parameter with an empty name. + + + + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + + + + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + + + + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + + + + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + + + + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + + + + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + + + + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + + + + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + + + + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + + + + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + + + + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + + + + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + + + + Unknown WebContentFormat '{0}'. + Unknown WebContentFormat '{0}'. + + + + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + + + + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + + + + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + + + + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + + + + The value supplied must be non-negative. + The value supplied must be non-negative. + + + + The value supplied must be greater than zero. + The value supplied must be greater than zero. + + + + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + Weak entity tags (W/"...") are not supported in this context. + Weak entity tags (W/"...") are not supported in this context. + + + + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + + + + WebBodyFormatMessageProperty(Format={0}) + WebBodyFormatMessageProperty(Format={0}) + + + + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + + + + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + + + + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + + + + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + + + + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + + + + The incoming HTTP request's URI '{0}' does not match any service operation. + The incoming HTTP request's URI '{0}' does not match any service operation. + + + + The XmlBuffer's quota has been exceeded. + The XmlBuffer's quota has been exceeded. + + + + New types cannot be registered with serializer manager after the service has been opened. + New types cannot be registered with serializer manager after the service has been opened. + + + + The '{0}' method is not supported by the stream. + The '{0}' method is not supported by the stream. + + + + The get accessor of the '{0}' property is not supported by the stream. + The get accessor of the '{0}' property is not supported by the stream. + + + + The set accessor of the '{0}' property is not supported by the stream. + The set accessor of the '{0}' property is not supported by the stream. + + + + + \ No newline at end of file diff --git a/src/System.ServiceModel.Web/src/Resources/xlf/Strings.de.xlf b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.de.xlf new file mode 100644 index 00000000000..2e14c5f62e0 --- /dev/null +++ b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.de.xlf @@ -0,0 +1,827 @@ + + + + + + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + + + + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + + + + Bind parameters cannot be null or empty for path variable '{0}'. + Bind parameters cannot be null or empty for path variable '{0}'. + + + + This buffer cannot be returned to the buffer manager because it is the wrong size. + This buffer cannot be returned to the buffer manager because it is the wrong size. + + + + The size quota for this stream ({0}) has been exceeded. + The size quota for this stream ({0}) has been exceeded. + + + + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + + + + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + + + + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + + + + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + + + + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + + + + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + + + + Cross domain javascript callback is not supported in authenticated services. + Cross domain javascript callback is not supported in authenticated services. + + + + CrossDomainScriptAccessEnabled cannot be used in Clients. + CrossDomainScriptAccessEnabled cannot be used in Clients. + + + + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + + + + A registration already exists for URI '{0}'. + A registration already exists for URI '{0}'. + + + + Cannot process contentType. + Cannot process contentType. + + + + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + + + + Unrecognized charSet '{0}' in contentType. + Unrecognized charSet '{0}' in contentType. + + + + The ServiceEndpoint's Address is null. Address must be an absolute uri. + The ServiceEndpoint's Address is null. Address must be an absolute uri. + + + + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + + + + This message formatter cannot be used to process response messages. + This message formatter cannot be used to process response messages. + + + + This message formatter cannot be used to process request messages. + This message formatter cannot be used to process request messages. + + + + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + + + + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + + + + Endpoint not found. + Endpoint not found. + + + + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + + + + Method not allowed. + Method not allowed. + + + + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + + + + Request Error + Request Error + + + + Service + Service + + + + The server encountered an error processing the request. See server logs for more details. + The server encountered an error processing the request. See server logs for more details. + + + + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + + + + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + + + + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + + + + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + + + + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + + + + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + + + + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + + + + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + + + + WebMessageEncodingBindingElement only supports MessageVersion.None. + WebMessageEncodingBindingElement only supports MessageVersion.None. + + + + The value must be in the range [{0}, {1}]. + The value must be in the range [{0}, {1}]. + + + + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + + + + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + + + + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + + + + The maximum message size quota for outgoing messages ({0}) has been exceeded. + The maximum message size quota for outgoing messages ({0}) has been exceeded. + + + + The message body is a Stream and cannot be re-read. + The message body is a Stream and cannot be re-read. + + + + The message body is missing or empty. + The message body is missing or empty. + + + + The XmlReader used to read the message body is in an invalid read state '{0}'. + The XmlReader used to read the message body is in an invalid read state '{0}'. + + + + The MessageBuffer has been closed and can no longer be used. + The MessageBuffer has been closed and can no longer be used. + + + + The message has been closed and can no longer be used. + The message has been closed and can no longer be used. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + + + + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + The text encoding '{0}' used in the text message format is not supported. + The text encoding '{0}' used in the text message format is not supported. + + + + Unknown MessageVersion. + Unknown MessageVersion. + + + + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + + + + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + + + + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + + + + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + + + + The {0} object has been disposed. + The {0} object has been disposed. + + + + Object is read-only. + Object is read-only. + + + + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + + + + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + + + + The operation '{0}' does not support '{1}' as a response format. + The operation '{0}' does not support '{1}' as a response format. + + + + Could not find operation name in the message properties. + Could not find operation name in the message properties. + + + + This operation is supported only when the operation selector is of type '{0}'. + This operation is supported only when the operation selector is of type '{0}'. + + + + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + + + + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + + + + Read is not supported on this stream. + Read is not supported on this stream. + + + + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + + + + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + ReplyAlreadySent + ReplyAlreadySent + + + + The requestContext has been aborted. + The requestContext has been aborted. + + + + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + + + + IAsyncResult not provided or of wrong type. + IAsyncResult not provided or of wrong type. + + + + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + + + + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + + + + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + Seek is not supported on this stream. + Seek is not supported on this stream. + + + + The formatter '{0}' does not support serializing replies. + The formatter '{0}' does not support serializing replies. + + + + The formatter '{0}' does not support serializing requests. + The formatter '{0}' does not support serializing requests. + + + + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + + + + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + + + + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Argument {0} must be a non-negative timeout value. Provided value was {1}. + Argument {0} must be a non-negative timeout value. Provided value was {1}. + + + + Argument {0} must be a positive timeout value. Provided value was {1}. + Argument {0} must be a positive timeout value. Provided value was {1}. + + + + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + + + + Type '{0}' is not supported by '{1}'. + Type '{0}' is not supported by '{1}'. + + + + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + + + + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + + + + UriTemplate.BindByName was called with an empty key in the parameters collection. + UriTemplate.BindByName was called with an empty key in the parameters collection. + + + + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + + + + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + + + + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + + + + Cannot look up compound segment results before a successful Match has been performed. + Cannot look up compound segment results before a successful Match has been performed. + + + + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + + + + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + + + + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + + + + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + + + + The Defaults dictionary on the UriTemplate is immutable. + The Defaults dictionary on the UriTemplate is immutable. + + + + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + + + + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + + + + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + + + + UriTemplate '{0}' has invalid variable declaration '{1}'. + UriTemplate '{0}' has invalid variable declaration '{1}'. + + + + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + + + + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + + + + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + + + + UriTemplate '{0}' has a query string that ends in '&'. + UriTemplate '{0}' has a query string that ends in '&'. + + + + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + + + + UriTemplate '{0}' has a query parameter with an empty name. + UriTemplate '{0}' has a query parameter with an empty name. + + + + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + + + + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + + + + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + + + + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + + + + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + + + + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + + + + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + + + + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + + + + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + + + + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + + + + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + + + + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + + + + Unknown WebContentFormat '{0}'. + Unknown WebContentFormat '{0}'. + + + + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + + + + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + + + + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + + + + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + + + + The value supplied must be non-negative. + The value supplied must be non-negative. + + + + The value supplied must be greater than zero. + The value supplied must be greater than zero. + + + + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + Weak entity tags (W/"...") are not supported in this context. + Weak entity tags (W/"...") are not supported in this context. + + + + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + + + + WebBodyFormatMessageProperty(Format={0}) + WebBodyFormatMessageProperty(Format={0}) + + + + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + + + + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + + + + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + + + + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + + + + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + + + + The incoming HTTP request's URI '{0}' does not match any service operation. + The incoming HTTP request's URI '{0}' does not match any service operation. + + + + The XmlBuffer's quota has been exceeded. + The XmlBuffer's quota has been exceeded. + + + + New types cannot be registered with serializer manager after the service has been opened. + New types cannot be registered with serializer manager after the service has been opened. + + + + The '{0}' method is not supported by the stream. + The '{0}' method is not supported by the stream. + + + + The get accessor of the '{0}' property is not supported by the stream. + The get accessor of the '{0}' property is not supported by the stream. + + + + The set accessor of the '{0}' property is not supported by the stream. + The set accessor of the '{0}' property is not supported by the stream. + + + + + \ No newline at end of file diff --git a/src/System.ServiceModel.Web/src/Resources/xlf/Strings.es.xlf b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.es.xlf new file mode 100644 index 00000000000..a05d82fff5a --- /dev/null +++ b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.es.xlf @@ -0,0 +1,827 @@ + + + + + + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + + + + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + + + + Bind parameters cannot be null or empty for path variable '{0}'. + Bind parameters cannot be null or empty for path variable '{0}'. + + + + This buffer cannot be returned to the buffer manager because it is the wrong size. + This buffer cannot be returned to the buffer manager because it is the wrong size. + + + + The size quota for this stream ({0}) has been exceeded. + The size quota for this stream ({0}) has been exceeded. + + + + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + + + + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + + + + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + + + + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + + + + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + + + + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + + + + Cross domain javascript callback is not supported in authenticated services. + Cross domain javascript callback is not supported in authenticated services. + + + + CrossDomainScriptAccessEnabled cannot be used in Clients. + CrossDomainScriptAccessEnabled cannot be used in Clients. + + + + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + + + + A registration already exists for URI '{0}'. + A registration already exists for URI '{0}'. + + + + Cannot process contentType. + Cannot process contentType. + + + + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + + + + Unrecognized charSet '{0}' in contentType. + Unrecognized charSet '{0}' in contentType. + + + + The ServiceEndpoint's Address is null. Address must be an absolute uri. + The ServiceEndpoint's Address is null. Address must be an absolute uri. + + + + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + + + + This message formatter cannot be used to process response messages. + This message formatter cannot be used to process response messages. + + + + This message formatter cannot be used to process request messages. + This message formatter cannot be used to process request messages. + + + + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + + + + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + + + + Endpoint not found. + Endpoint not found. + + + + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + + + + Method not allowed. + Method not allowed. + + + + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + + + + Request Error + Request Error + + + + Service + Service + + + + The server encountered an error processing the request. See server logs for more details. + The server encountered an error processing the request. See server logs for more details. + + + + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + + + + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + + + + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + + + + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + + + + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + + + + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + + + + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + + + + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + + + + WebMessageEncodingBindingElement only supports MessageVersion.None. + WebMessageEncodingBindingElement only supports MessageVersion.None. + + + + The value must be in the range [{0}, {1}]. + The value must be in the range [{0}, {1}]. + + + + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + + + + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + + + + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + + + + The maximum message size quota for outgoing messages ({0}) has been exceeded. + The maximum message size quota for outgoing messages ({0}) has been exceeded. + + + + The message body is a Stream and cannot be re-read. + The message body is a Stream and cannot be re-read. + + + + The message body is missing or empty. + The message body is missing or empty. + + + + The XmlReader used to read the message body is in an invalid read state '{0}'. + The XmlReader used to read the message body is in an invalid read state '{0}'. + + + + The MessageBuffer has been closed and can no longer be used. + The MessageBuffer has been closed and can no longer be used. + + + + The message has been closed and can no longer be used. + The message has been closed and can no longer be used. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + + + + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + The text encoding '{0}' used in the text message format is not supported. + The text encoding '{0}' used in the text message format is not supported. + + + + Unknown MessageVersion. + Unknown MessageVersion. + + + + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + + + + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + + + + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + + + + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + + + + The {0} object has been disposed. + The {0} object has been disposed. + + + + Object is read-only. + Object is read-only. + + + + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + + + + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + + + + The operation '{0}' does not support '{1}' as a response format. + The operation '{0}' does not support '{1}' as a response format. + + + + Could not find operation name in the message properties. + Could not find operation name in the message properties. + + + + This operation is supported only when the operation selector is of type '{0}'. + This operation is supported only when the operation selector is of type '{0}'. + + + + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + + + + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + + + + Read is not supported on this stream. + Read is not supported on this stream. + + + + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + + + + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + ReplyAlreadySent + ReplyAlreadySent + + + + The requestContext has been aborted. + The requestContext has been aborted. + + + + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + + + + IAsyncResult not provided or of wrong type. + IAsyncResult not provided or of wrong type. + + + + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + + + + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + + + + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + Seek is not supported on this stream. + Seek is not supported on this stream. + + + + The formatter '{0}' does not support serializing replies. + The formatter '{0}' does not support serializing replies. + + + + The formatter '{0}' does not support serializing requests. + The formatter '{0}' does not support serializing requests. + + + + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + + + + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + + + + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Argument {0} must be a non-negative timeout value. Provided value was {1}. + Argument {0} must be a non-negative timeout value. Provided value was {1}. + + + + Argument {0} must be a positive timeout value. Provided value was {1}. + Argument {0} must be a positive timeout value. Provided value was {1}. + + + + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + + + + Type '{0}' is not supported by '{1}'. + Type '{0}' is not supported by '{1}'. + + + + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + + + + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + + + + UriTemplate.BindByName was called with an empty key in the parameters collection. + UriTemplate.BindByName was called with an empty key in the parameters collection. + + + + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + + + + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + + + + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + + + + Cannot look up compound segment results before a successful Match has been performed. + Cannot look up compound segment results before a successful Match has been performed. + + + + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + + + + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + + + + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + + + + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + + + + The Defaults dictionary on the UriTemplate is immutable. + The Defaults dictionary on the UriTemplate is immutable. + + + + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + + + + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + + + + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + + + + UriTemplate '{0}' has invalid variable declaration '{1}'. + UriTemplate '{0}' has invalid variable declaration '{1}'. + + + + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + + + + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + + + + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + + + + UriTemplate '{0}' has a query string that ends in '&'. + UriTemplate '{0}' has a query string that ends in '&'. + + + + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + + + + UriTemplate '{0}' has a query parameter with an empty name. + UriTemplate '{0}' has a query parameter with an empty name. + + + + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + + + + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + + + + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + + + + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + + + + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + + + + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + + + + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + + + + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + + + + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + + + + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + + + + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + + + + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + + + + Unknown WebContentFormat '{0}'. + Unknown WebContentFormat '{0}'. + + + + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + + + + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + + + + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + + + + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + + + + The value supplied must be non-negative. + The value supplied must be non-negative. + + + + The value supplied must be greater than zero. + The value supplied must be greater than zero. + + + + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + Weak entity tags (W/"...") are not supported in this context. + Weak entity tags (W/"...") are not supported in this context. + + + + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + + + + WebBodyFormatMessageProperty(Format={0}) + WebBodyFormatMessageProperty(Format={0}) + + + + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + + + + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + + + + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + + + + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + + + + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + + + + The incoming HTTP request's URI '{0}' does not match any service operation. + The incoming HTTP request's URI '{0}' does not match any service operation. + + + + The XmlBuffer's quota has been exceeded. + The XmlBuffer's quota has been exceeded. + + + + New types cannot be registered with serializer manager after the service has been opened. + New types cannot be registered with serializer manager after the service has been opened. + + + + The '{0}' method is not supported by the stream. + The '{0}' method is not supported by the stream. + + + + The get accessor of the '{0}' property is not supported by the stream. + The get accessor of the '{0}' property is not supported by the stream. + + + + The set accessor of the '{0}' property is not supported by the stream. + The set accessor of the '{0}' property is not supported by the stream. + + + + + \ No newline at end of file diff --git a/src/System.ServiceModel.Web/src/Resources/xlf/Strings.fr.xlf b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.fr.xlf new file mode 100644 index 00000000000..0d8b959d3ca --- /dev/null +++ b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.fr.xlf @@ -0,0 +1,827 @@ + + + + + + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + + + + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + + + + Bind parameters cannot be null or empty for path variable '{0}'. + Bind parameters cannot be null or empty for path variable '{0}'. + + + + This buffer cannot be returned to the buffer manager because it is the wrong size. + This buffer cannot be returned to the buffer manager because it is the wrong size. + + + + The size quota for this stream ({0}) has been exceeded. + The size quota for this stream ({0}) has been exceeded. + + + + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + + + + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + + + + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + + + + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + + + + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + + + + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + + + + Cross domain javascript callback is not supported in authenticated services. + Cross domain javascript callback is not supported in authenticated services. + + + + CrossDomainScriptAccessEnabled cannot be used in Clients. + CrossDomainScriptAccessEnabled cannot be used in Clients. + + + + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + + + + A registration already exists for URI '{0}'. + A registration already exists for URI '{0}'. + + + + Cannot process contentType. + Cannot process contentType. + + + + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + + + + Unrecognized charSet '{0}' in contentType. + Unrecognized charSet '{0}' in contentType. + + + + The ServiceEndpoint's Address is null. Address must be an absolute uri. + The ServiceEndpoint's Address is null. Address must be an absolute uri. + + + + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + + + + This message formatter cannot be used to process response messages. + This message formatter cannot be used to process response messages. + + + + This message formatter cannot be used to process request messages. + This message formatter cannot be used to process request messages. + + + + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + + + + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + + + + Endpoint not found. + Endpoint not found. + + + + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + + + + Method not allowed. + Method not allowed. + + + + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + + + + Request Error + Request Error + + + + Service + Service + + + + The server encountered an error processing the request. See server logs for more details. + The server encountered an error processing the request. See server logs for more details. + + + + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + + + + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + + + + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + + + + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + + + + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + + + + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + + + + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + + + + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + + + + WebMessageEncodingBindingElement only supports MessageVersion.None. + WebMessageEncodingBindingElement only supports MessageVersion.None. + + + + The value must be in the range [{0}, {1}]. + The value must be in the range [{0}, {1}]. + + + + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + + + + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + + + + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + + + + The maximum message size quota for outgoing messages ({0}) has been exceeded. + The maximum message size quota for outgoing messages ({0}) has been exceeded. + + + + The message body is a Stream and cannot be re-read. + The message body is a Stream and cannot be re-read. + + + + The message body is missing or empty. + The message body is missing or empty. + + + + The XmlReader used to read the message body is in an invalid read state '{0}'. + The XmlReader used to read the message body is in an invalid read state '{0}'. + + + + The MessageBuffer has been closed and can no longer be used. + The MessageBuffer has been closed and can no longer be used. + + + + The message has been closed and can no longer be used. + The message has been closed and can no longer be used. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + + + + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + The text encoding '{0}' used in the text message format is not supported. + The text encoding '{0}' used in the text message format is not supported. + + + + Unknown MessageVersion. + Unknown MessageVersion. + + + + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + + + + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + + + + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + + + + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + + + + The {0} object has been disposed. + The {0} object has been disposed. + + + + Object is read-only. + Object is read-only. + + + + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + + + + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + + + + The operation '{0}' does not support '{1}' as a response format. + The operation '{0}' does not support '{1}' as a response format. + + + + Could not find operation name in the message properties. + Could not find operation name in the message properties. + + + + This operation is supported only when the operation selector is of type '{0}'. + This operation is supported only when the operation selector is of type '{0}'. + + + + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + + + + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + + + + Read is not supported on this stream. + Read is not supported on this stream. + + + + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + + + + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + ReplyAlreadySent + ReplyAlreadySent + + + + The requestContext has been aborted. + The requestContext has been aborted. + + + + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + + + + IAsyncResult not provided or of wrong type. + IAsyncResult not provided or of wrong type. + + + + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + + + + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + + + + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + Seek is not supported on this stream. + Seek is not supported on this stream. + + + + The formatter '{0}' does not support serializing replies. + The formatter '{0}' does not support serializing replies. + + + + The formatter '{0}' does not support serializing requests. + The formatter '{0}' does not support serializing requests. + + + + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + + + + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + + + + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Argument {0} must be a non-negative timeout value. Provided value was {1}. + Argument {0} must be a non-negative timeout value. Provided value was {1}. + + + + Argument {0} must be a positive timeout value. Provided value was {1}. + Argument {0} must be a positive timeout value. Provided value was {1}. + + + + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + + + + Type '{0}' is not supported by '{1}'. + Type '{0}' is not supported by '{1}'. + + + + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + + + + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + + + + UriTemplate.BindByName was called with an empty key in the parameters collection. + UriTemplate.BindByName was called with an empty key in the parameters collection. + + + + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + + + + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + + + + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + + + + Cannot look up compound segment results before a successful Match has been performed. + Cannot look up compound segment results before a successful Match has been performed. + + + + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + + + + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + + + + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + + + + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + + + + The Defaults dictionary on the UriTemplate is immutable. + The Defaults dictionary on the UriTemplate is immutable. + + + + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + + + + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + + + + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + + + + UriTemplate '{0}' has invalid variable declaration '{1}'. + UriTemplate '{0}' has invalid variable declaration '{1}'. + + + + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + + + + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + + + + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + + + + UriTemplate '{0}' has a query string that ends in '&'. + UriTemplate '{0}' has a query string that ends in '&'. + + + + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + + + + UriTemplate '{0}' has a query parameter with an empty name. + UriTemplate '{0}' has a query parameter with an empty name. + + + + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + + + + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + + + + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + + + + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + + + + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + + + + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + + + + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + + + + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + + + + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + + + + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + + + + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + + + + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + + + + Unknown WebContentFormat '{0}'. + Unknown WebContentFormat '{0}'. + + + + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + + + + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + + + + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + + + + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + + + + The value supplied must be non-negative. + The value supplied must be non-negative. + + + + The value supplied must be greater than zero. + The value supplied must be greater than zero. + + + + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + Weak entity tags (W/"...") are not supported in this context. + Weak entity tags (W/"...") are not supported in this context. + + + + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + + + + WebBodyFormatMessageProperty(Format={0}) + WebBodyFormatMessageProperty(Format={0}) + + + + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + + + + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + + + + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + + + + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + + + + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + + + + The incoming HTTP request's URI '{0}' does not match any service operation. + The incoming HTTP request's URI '{0}' does not match any service operation. + + + + The XmlBuffer's quota has been exceeded. + The XmlBuffer's quota has been exceeded. + + + + New types cannot be registered with serializer manager after the service has been opened. + New types cannot be registered with serializer manager after the service has been opened. + + + + The '{0}' method is not supported by the stream. + The '{0}' method is not supported by the stream. + + + + The get accessor of the '{0}' property is not supported by the stream. + The get accessor of the '{0}' property is not supported by the stream. + + + + The set accessor of the '{0}' property is not supported by the stream. + The set accessor of the '{0}' property is not supported by the stream. + + + + + \ No newline at end of file diff --git a/src/System.ServiceModel.Web/src/Resources/xlf/Strings.it.xlf b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.it.xlf new file mode 100644 index 00000000000..34d16e09b79 --- /dev/null +++ b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.it.xlf @@ -0,0 +1,827 @@ + + + + + + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + + + + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + + + + Bind parameters cannot be null or empty for path variable '{0}'. + Bind parameters cannot be null or empty for path variable '{0}'. + + + + This buffer cannot be returned to the buffer manager because it is the wrong size. + This buffer cannot be returned to the buffer manager because it is the wrong size. + + + + The size quota for this stream ({0}) has been exceeded. + The size quota for this stream ({0}) has been exceeded. + + + + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + + + + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + + + + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + + + + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + + + + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + + + + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + + + + Cross domain javascript callback is not supported in authenticated services. + Cross domain javascript callback is not supported in authenticated services. + + + + CrossDomainScriptAccessEnabled cannot be used in Clients. + CrossDomainScriptAccessEnabled cannot be used in Clients. + + + + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + + + + A registration already exists for URI '{0}'. + A registration already exists for URI '{0}'. + + + + Cannot process contentType. + Cannot process contentType. + + + + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + + + + Unrecognized charSet '{0}' in contentType. + Unrecognized charSet '{0}' in contentType. + + + + The ServiceEndpoint's Address is null. Address must be an absolute uri. + The ServiceEndpoint's Address is null. Address must be an absolute uri. + + + + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + + + + This message formatter cannot be used to process response messages. + This message formatter cannot be used to process response messages. + + + + This message formatter cannot be used to process request messages. + This message formatter cannot be used to process request messages. + + + + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + + + + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + + + + Endpoint not found. + Endpoint not found. + + + + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + + + + Method not allowed. + Method not allowed. + + + + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + + + + Request Error + Request Error + + + + Service + Service + + + + The server encountered an error processing the request. See server logs for more details. + The server encountered an error processing the request. See server logs for more details. + + + + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + + + + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + + + + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + + + + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + + + + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + + + + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + + + + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + + + + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + + + + WebMessageEncodingBindingElement only supports MessageVersion.None. + WebMessageEncodingBindingElement only supports MessageVersion.None. + + + + The value must be in the range [{0}, {1}]. + The value must be in the range [{0}, {1}]. + + + + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + + + + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + + + + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + + + + The maximum message size quota for outgoing messages ({0}) has been exceeded. + The maximum message size quota for outgoing messages ({0}) has been exceeded. + + + + The message body is a Stream and cannot be re-read. + The message body is a Stream and cannot be re-read. + + + + The message body is missing or empty. + The message body is missing or empty. + + + + The XmlReader used to read the message body is in an invalid read state '{0}'. + The XmlReader used to read the message body is in an invalid read state '{0}'. + + + + The MessageBuffer has been closed and can no longer be used. + The MessageBuffer has been closed and can no longer be used. + + + + The message has been closed and can no longer be used. + The message has been closed and can no longer be used. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + + + + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + The text encoding '{0}' used in the text message format is not supported. + The text encoding '{0}' used in the text message format is not supported. + + + + Unknown MessageVersion. + Unknown MessageVersion. + + + + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + + + + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + + + + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + + + + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + + + + The {0} object has been disposed. + The {0} object has been disposed. + + + + Object is read-only. + Object is read-only. + + + + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + + + + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + + + + The operation '{0}' does not support '{1}' as a response format. + The operation '{0}' does not support '{1}' as a response format. + + + + Could not find operation name in the message properties. + Could not find operation name in the message properties. + + + + This operation is supported only when the operation selector is of type '{0}'. + This operation is supported only when the operation selector is of type '{0}'. + + + + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + + + + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + + + + Read is not supported on this stream. + Read is not supported on this stream. + + + + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + + + + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + ReplyAlreadySent + ReplyAlreadySent + + + + The requestContext has been aborted. + The requestContext has been aborted. + + + + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + + + + IAsyncResult not provided or of wrong type. + IAsyncResult not provided or of wrong type. + + + + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + + + + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + + + + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + Seek is not supported on this stream. + Seek is not supported on this stream. + + + + The formatter '{0}' does not support serializing replies. + The formatter '{0}' does not support serializing replies. + + + + The formatter '{0}' does not support serializing requests. + The formatter '{0}' does not support serializing requests. + + + + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + + + + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + + + + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Argument {0} must be a non-negative timeout value. Provided value was {1}. + Argument {0} must be a non-negative timeout value. Provided value was {1}. + + + + Argument {0} must be a positive timeout value. Provided value was {1}. + Argument {0} must be a positive timeout value. Provided value was {1}. + + + + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + + + + Type '{0}' is not supported by '{1}'. + Type '{0}' is not supported by '{1}'. + + + + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + + + + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + + + + UriTemplate.BindByName was called with an empty key in the parameters collection. + UriTemplate.BindByName was called with an empty key in the parameters collection. + + + + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + + + + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + + + + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + + + + Cannot look up compound segment results before a successful Match has been performed. + Cannot look up compound segment results before a successful Match has been performed. + + + + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + + + + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + + + + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + + + + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + + + + The Defaults dictionary on the UriTemplate is immutable. + The Defaults dictionary on the UriTemplate is immutable. + + + + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + + + + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + + + + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + + + + UriTemplate '{0}' has invalid variable declaration '{1}'. + UriTemplate '{0}' has invalid variable declaration '{1}'. + + + + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + + + + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + + + + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + + + + UriTemplate '{0}' has a query string that ends in '&'. + UriTemplate '{0}' has a query string that ends in '&'. + + + + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + + + + UriTemplate '{0}' has a query parameter with an empty name. + UriTemplate '{0}' has a query parameter with an empty name. + + + + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + + + + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + + + + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + + + + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + + + + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + + + + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + + + + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + + + + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + + + + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + + + + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + + + + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + + + + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + + + + Unknown WebContentFormat '{0}'. + Unknown WebContentFormat '{0}'. + + + + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + + + + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + + + + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + + + + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + + + + The value supplied must be non-negative. + The value supplied must be non-negative. + + + + The value supplied must be greater than zero. + The value supplied must be greater than zero. + + + + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + Weak entity tags (W/"...") are not supported in this context. + Weak entity tags (W/"...") are not supported in this context. + + + + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + + + + WebBodyFormatMessageProperty(Format={0}) + WebBodyFormatMessageProperty(Format={0}) + + + + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + + + + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + + + + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + + + + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + + + + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + + + + The incoming HTTP request's URI '{0}' does not match any service operation. + The incoming HTTP request's URI '{0}' does not match any service operation. + + + + The XmlBuffer's quota has been exceeded. + The XmlBuffer's quota has been exceeded. + + + + New types cannot be registered with serializer manager after the service has been opened. + New types cannot be registered with serializer manager after the service has been opened. + + + + The '{0}' method is not supported by the stream. + The '{0}' method is not supported by the stream. + + + + The get accessor of the '{0}' property is not supported by the stream. + The get accessor of the '{0}' property is not supported by the stream. + + + + The set accessor of the '{0}' property is not supported by the stream. + The set accessor of the '{0}' property is not supported by the stream. + + + + + \ No newline at end of file diff --git a/src/System.ServiceModel.Web/src/Resources/xlf/Strings.ja.xlf b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.ja.xlf new file mode 100644 index 00000000000..480244f2367 --- /dev/null +++ b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.ja.xlf @@ -0,0 +1,827 @@ + + + + + + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + + + + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + + + + Bind parameters cannot be null or empty for path variable '{0}'. + Bind parameters cannot be null or empty for path variable '{0}'. + + + + This buffer cannot be returned to the buffer manager because it is the wrong size. + This buffer cannot be returned to the buffer manager because it is the wrong size. + + + + The size quota for this stream ({0}) has been exceeded. + The size quota for this stream ({0}) has been exceeded. + + + + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + + + + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + + + + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + + + + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + + + + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + + + + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + + + + Cross domain javascript callback is not supported in authenticated services. + Cross domain javascript callback is not supported in authenticated services. + + + + CrossDomainScriptAccessEnabled cannot be used in Clients. + CrossDomainScriptAccessEnabled cannot be used in Clients. + + + + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + + + + A registration already exists for URI '{0}'. + A registration already exists for URI '{0}'. + + + + Cannot process contentType. + Cannot process contentType. + + + + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + + + + Unrecognized charSet '{0}' in contentType. + Unrecognized charSet '{0}' in contentType. + + + + The ServiceEndpoint's Address is null. Address must be an absolute uri. + The ServiceEndpoint's Address is null. Address must be an absolute uri. + + + + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + + + + This message formatter cannot be used to process response messages. + This message formatter cannot be used to process response messages. + + + + This message formatter cannot be used to process request messages. + This message formatter cannot be used to process request messages. + + + + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + + + + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + + + + Endpoint not found. + Endpoint not found. + + + + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + + + + Method not allowed. + Method not allowed. + + + + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + + + + Request Error + Request Error + + + + Service + Service + + + + The server encountered an error processing the request. See server logs for more details. + The server encountered an error processing the request. See server logs for more details. + + + + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + + + + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + + + + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + + + + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + + + + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + + + + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + + + + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + + + + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + + + + WebMessageEncodingBindingElement only supports MessageVersion.None. + WebMessageEncodingBindingElement only supports MessageVersion.None. + + + + The value must be in the range [{0}, {1}]. + The value must be in the range [{0}, {1}]. + + + + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + + + + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + + + + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + + + + The maximum message size quota for outgoing messages ({0}) has been exceeded. + The maximum message size quota for outgoing messages ({0}) has been exceeded. + + + + The message body is a Stream and cannot be re-read. + The message body is a Stream and cannot be re-read. + + + + The message body is missing or empty. + The message body is missing or empty. + + + + The XmlReader used to read the message body is in an invalid read state '{0}'. + The XmlReader used to read the message body is in an invalid read state '{0}'. + + + + The MessageBuffer has been closed and can no longer be used. + The MessageBuffer has been closed and can no longer be used. + + + + The message has been closed and can no longer be used. + The message has been closed and can no longer be used. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + + + + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + The text encoding '{0}' used in the text message format is not supported. + The text encoding '{0}' used in the text message format is not supported. + + + + Unknown MessageVersion. + Unknown MessageVersion. + + + + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + + + + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + + + + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + + + + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + + + + The {0} object has been disposed. + The {0} object has been disposed. + + + + Object is read-only. + Object is read-only. + + + + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + + + + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + + + + The operation '{0}' does not support '{1}' as a response format. + The operation '{0}' does not support '{1}' as a response format. + + + + Could not find operation name in the message properties. + Could not find operation name in the message properties. + + + + This operation is supported only when the operation selector is of type '{0}'. + This operation is supported only when the operation selector is of type '{0}'. + + + + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + + + + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + + + + Read is not supported on this stream. + Read is not supported on this stream. + + + + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + + + + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + ReplyAlreadySent + ReplyAlreadySent + + + + The requestContext has been aborted. + The requestContext has been aborted. + + + + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + + + + IAsyncResult not provided or of wrong type. + IAsyncResult not provided or of wrong type. + + + + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + + + + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + + + + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + Seek is not supported on this stream. + Seek is not supported on this stream. + + + + The formatter '{0}' does not support serializing replies. + The formatter '{0}' does not support serializing replies. + + + + The formatter '{0}' does not support serializing requests. + The formatter '{0}' does not support serializing requests. + + + + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + + + + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + + + + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Argument {0} must be a non-negative timeout value. Provided value was {1}. + Argument {0} must be a non-negative timeout value. Provided value was {1}. + + + + Argument {0} must be a positive timeout value. Provided value was {1}. + Argument {0} must be a positive timeout value. Provided value was {1}. + + + + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + + + + Type '{0}' is not supported by '{1}'. + Type '{0}' is not supported by '{1}'. + + + + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + + + + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + + + + UriTemplate.BindByName was called with an empty key in the parameters collection. + UriTemplate.BindByName was called with an empty key in the parameters collection. + + + + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + + + + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + + + + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + + + + Cannot look up compound segment results before a successful Match has been performed. + Cannot look up compound segment results before a successful Match has been performed. + + + + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + + + + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + + + + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + + + + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + + + + The Defaults dictionary on the UriTemplate is immutable. + The Defaults dictionary on the UriTemplate is immutable. + + + + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + + + + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + + + + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + + + + UriTemplate '{0}' has invalid variable declaration '{1}'. + UriTemplate '{0}' has invalid variable declaration '{1}'. + + + + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + + + + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + + + + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + + + + UriTemplate '{0}' has a query string that ends in '&'. + UriTemplate '{0}' has a query string that ends in '&'. + + + + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + + + + UriTemplate '{0}' has a query parameter with an empty name. + UriTemplate '{0}' has a query parameter with an empty name. + + + + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + + + + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + + + + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + + + + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + + + + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + + + + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + + + + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + + + + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + + + + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + + + + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + + + + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + + + + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + + + + Unknown WebContentFormat '{0}'. + Unknown WebContentFormat '{0}'. + + + + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + + + + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + + + + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + + + + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + + + + The value supplied must be non-negative. + The value supplied must be non-negative. + + + + The value supplied must be greater than zero. + The value supplied must be greater than zero. + + + + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + Weak entity tags (W/"...") are not supported in this context. + Weak entity tags (W/"...") are not supported in this context. + + + + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + + + + WebBodyFormatMessageProperty(Format={0}) + WebBodyFormatMessageProperty(Format={0}) + + + + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + + + + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + + + + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + + + + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + + + + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + + + + The incoming HTTP request's URI '{0}' does not match any service operation. + The incoming HTTP request's URI '{0}' does not match any service operation. + + + + The XmlBuffer's quota has been exceeded. + The XmlBuffer's quota has been exceeded. + + + + New types cannot be registered with serializer manager after the service has been opened. + New types cannot be registered with serializer manager after the service has been opened. + + + + The '{0}' method is not supported by the stream. + The '{0}' method is not supported by the stream. + + + + The get accessor of the '{0}' property is not supported by the stream. + The get accessor of the '{0}' property is not supported by the stream. + + + + The set accessor of the '{0}' property is not supported by the stream. + The set accessor of the '{0}' property is not supported by the stream. + + + + + \ No newline at end of file diff --git a/src/System.ServiceModel.Web/src/Resources/xlf/Strings.ko.xlf b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.ko.xlf new file mode 100644 index 00000000000..b5ed372cbdb --- /dev/null +++ b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.ko.xlf @@ -0,0 +1,827 @@ + + + + + + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + + + + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + + + + Bind parameters cannot be null or empty for path variable '{0}'. + Bind parameters cannot be null or empty for path variable '{0}'. + + + + This buffer cannot be returned to the buffer manager because it is the wrong size. + This buffer cannot be returned to the buffer manager because it is the wrong size. + + + + The size quota for this stream ({0}) has been exceeded. + The size quota for this stream ({0}) has been exceeded. + + + + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + + + + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + + + + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + + + + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + + + + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + + + + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + + + + Cross domain javascript callback is not supported in authenticated services. + Cross domain javascript callback is not supported in authenticated services. + + + + CrossDomainScriptAccessEnabled cannot be used in Clients. + CrossDomainScriptAccessEnabled cannot be used in Clients. + + + + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + + + + A registration already exists for URI '{0}'. + A registration already exists for URI '{0}'. + + + + Cannot process contentType. + Cannot process contentType. + + + + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + + + + Unrecognized charSet '{0}' in contentType. + Unrecognized charSet '{0}' in contentType. + + + + The ServiceEndpoint's Address is null. Address must be an absolute uri. + The ServiceEndpoint's Address is null. Address must be an absolute uri. + + + + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + + + + This message formatter cannot be used to process response messages. + This message formatter cannot be used to process response messages. + + + + This message formatter cannot be used to process request messages. + This message formatter cannot be used to process request messages. + + + + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + + + + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + + + + Endpoint not found. + Endpoint not found. + + + + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + + + + Method not allowed. + Method not allowed. + + + + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + + + + Request Error + Request Error + + + + Service + Service + + + + The server encountered an error processing the request. See server logs for more details. + The server encountered an error processing the request. See server logs for more details. + + + + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + + + + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + + + + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + + + + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + + + + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + + + + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + + + + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + + + + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + + + + WebMessageEncodingBindingElement only supports MessageVersion.None. + WebMessageEncodingBindingElement only supports MessageVersion.None. + + + + The value must be in the range [{0}, {1}]. + The value must be in the range [{0}, {1}]. + + + + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + + + + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + + + + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + + + + The maximum message size quota for outgoing messages ({0}) has been exceeded. + The maximum message size quota for outgoing messages ({0}) has been exceeded. + + + + The message body is a Stream and cannot be re-read. + The message body is a Stream and cannot be re-read. + + + + The message body is missing or empty. + The message body is missing or empty. + + + + The XmlReader used to read the message body is in an invalid read state '{0}'. + The XmlReader used to read the message body is in an invalid read state '{0}'. + + + + The MessageBuffer has been closed and can no longer be used. + The MessageBuffer has been closed and can no longer be used. + + + + The message has been closed and can no longer be used. + The message has been closed and can no longer be used. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + + + + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + The text encoding '{0}' used in the text message format is not supported. + The text encoding '{0}' used in the text message format is not supported. + + + + Unknown MessageVersion. + Unknown MessageVersion. + + + + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + + + + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + + + + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + + + + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + + + + The {0} object has been disposed. + The {0} object has been disposed. + + + + Object is read-only. + Object is read-only. + + + + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + + + + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + + + + The operation '{0}' does not support '{1}' as a response format. + The operation '{0}' does not support '{1}' as a response format. + + + + Could not find operation name in the message properties. + Could not find operation name in the message properties. + + + + This operation is supported only when the operation selector is of type '{0}'. + This operation is supported only when the operation selector is of type '{0}'. + + + + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + + + + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + + + + Read is not supported on this stream. + Read is not supported on this stream. + + + + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + + + + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + ReplyAlreadySent + ReplyAlreadySent + + + + The requestContext has been aborted. + The requestContext has been aborted. + + + + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + + + + IAsyncResult not provided or of wrong type. + IAsyncResult not provided or of wrong type. + + + + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + + + + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + + + + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + Seek is not supported on this stream. + Seek is not supported on this stream. + + + + The formatter '{0}' does not support serializing replies. + The formatter '{0}' does not support serializing replies. + + + + The formatter '{0}' does not support serializing requests. + The formatter '{0}' does not support serializing requests. + + + + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + + + + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + + + + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Argument {0} must be a non-negative timeout value. Provided value was {1}. + Argument {0} must be a non-negative timeout value. Provided value was {1}. + + + + Argument {0} must be a positive timeout value. Provided value was {1}. + Argument {0} must be a positive timeout value. Provided value was {1}. + + + + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + + + + Type '{0}' is not supported by '{1}'. + Type '{0}' is not supported by '{1}'. + + + + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + + + + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + + + + UriTemplate.BindByName was called with an empty key in the parameters collection. + UriTemplate.BindByName was called with an empty key in the parameters collection. + + + + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + + + + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + + + + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + + + + Cannot look up compound segment results before a successful Match has been performed. + Cannot look up compound segment results before a successful Match has been performed. + + + + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + + + + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + + + + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + + + + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + + + + The Defaults dictionary on the UriTemplate is immutable. + The Defaults dictionary on the UriTemplate is immutable. + + + + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + + + + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + + + + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + + + + UriTemplate '{0}' has invalid variable declaration '{1}'. + UriTemplate '{0}' has invalid variable declaration '{1}'. + + + + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + + + + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + + + + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + + + + UriTemplate '{0}' has a query string that ends in '&'. + UriTemplate '{0}' has a query string that ends in '&'. + + + + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + + + + UriTemplate '{0}' has a query parameter with an empty name. + UriTemplate '{0}' has a query parameter with an empty name. + + + + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + + + + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + + + + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + + + + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + + + + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + + + + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + + + + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + + + + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + + + + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + + + + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + + + + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + + + + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + + + + Unknown WebContentFormat '{0}'. + Unknown WebContentFormat '{0}'. + + + + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + + + + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + + + + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + + + + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + + + + The value supplied must be non-negative. + The value supplied must be non-negative. + + + + The value supplied must be greater than zero. + The value supplied must be greater than zero. + + + + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + Weak entity tags (W/"...") are not supported in this context. + Weak entity tags (W/"...") are not supported in this context. + + + + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + + + + WebBodyFormatMessageProperty(Format={0}) + WebBodyFormatMessageProperty(Format={0}) + + + + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + + + + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + + + + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + + + + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + + + + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + + + + The incoming HTTP request's URI '{0}' does not match any service operation. + The incoming HTTP request's URI '{0}' does not match any service operation. + + + + The XmlBuffer's quota has been exceeded. + The XmlBuffer's quota has been exceeded. + + + + New types cannot be registered with serializer manager after the service has been opened. + New types cannot be registered with serializer manager after the service has been opened. + + + + The '{0}' method is not supported by the stream. + The '{0}' method is not supported by the stream. + + + + The get accessor of the '{0}' property is not supported by the stream. + The get accessor of the '{0}' property is not supported by the stream. + + + + The set accessor of the '{0}' property is not supported by the stream. + The set accessor of the '{0}' property is not supported by the stream. + + + + + \ No newline at end of file diff --git a/src/System.ServiceModel.Web/src/Resources/xlf/Strings.pl.xlf b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.pl.xlf new file mode 100644 index 00000000000..f1924820845 --- /dev/null +++ b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.pl.xlf @@ -0,0 +1,827 @@ + + + + + + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + + + + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + + + + Bind parameters cannot be null or empty for path variable '{0}'. + Bind parameters cannot be null or empty for path variable '{0}'. + + + + This buffer cannot be returned to the buffer manager because it is the wrong size. + This buffer cannot be returned to the buffer manager because it is the wrong size. + + + + The size quota for this stream ({0}) has been exceeded. + The size quota for this stream ({0}) has been exceeded. + + + + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + + + + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + + + + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + + + + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + + + + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + + + + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + + + + Cross domain javascript callback is not supported in authenticated services. + Cross domain javascript callback is not supported in authenticated services. + + + + CrossDomainScriptAccessEnabled cannot be used in Clients. + CrossDomainScriptAccessEnabled cannot be used in Clients. + + + + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + + + + A registration already exists for URI '{0}'. + A registration already exists for URI '{0}'. + + + + Cannot process contentType. + Cannot process contentType. + + + + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + + + + Unrecognized charSet '{0}' in contentType. + Unrecognized charSet '{0}' in contentType. + + + + The ServiceEndpoint's Address is null. Address must be an absolute uri. + The ServiceEndpoint's Address is null. Address must be an absolute uri. + + + + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + + + + This message formatter cannot be used to process response messages. + This message formatter cannot be used to process response messages. + + + + This message formatter cannot be used to process request messages. + This message formatter cannot be used to process request messages. + + + + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + + + + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + + + + Endpoint not found. + Endpoint not found. + + + + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + + + + Method not allowed. + Method not allowed. + + + + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + + + + Request Error + Request Error + + + + Service + Service + + + + The server encountered an error processing the request. See server logs for more details. + The server encountered an error processing the request. See server logs for more details. + + + + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + + + + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + + + + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + + + + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + + + + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + + + + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + + + + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + + + + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + + + + WebMessageEncodingBindingElement only supports MessageVersion.None. + WebMessageEncodingBindingElement only supports MessageVersion.None. + + + + The value must be in the range [{0}, {1}]. + The value must be in the range [{0}, {1}]. + + + + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + + + + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + + + + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + + + + The maximum message size quota for outgoing messages ({0}) has been exceeded. + The maximum message size quota for outgoing messages ({0}) has been exceeded. + + + + The message body is a Stream and cannot be re-read. + The message body is a Stream and cannot be re-read. + + + + The message body is missing or empty. + The message body is missing or empty. + + + + The XmlReader used to read the message body is in an invalid read state '{0}'. + The XmlReader used to read the message body is in an invalid read state '{0}'. + + + + The MessageBuffer has been closed and can no longer be used. + The MessageBuffer has been closed and can no longer be used. + + + + The message has been closed and can no longer be used. + The message has been closed and can no longer be used. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + + + + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + The text encoding '{0}' used in the text message format is not supported. + The text encoding '{0}' used in the text message format is not supported. + + + + Unknown MessageVersion. + Unknown MessageVersion. + + + + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + + + + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + + + + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + + + + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + + + + The {0} object has been disposed. + The {0} object has been disposed. + + + + Object is read-only. + Object is read-only. + + + + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + + + + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + + + + The operation '{0}' does not support '{1}' as a response format. + The operation '{0}' does not support '{1}' as a response format. + + + + Could not find operation name in the message properties. + Could not find operation name in the message properties. + + + + This operation is supported only when the operation selector is of type '{0}'. + This operation is supported only when the operation selector is of type '{0}'. + + + + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + + + + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + + + + Read is not supported on this stream. + Read is not supported on this stream. + + + + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + + + + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + ReplyAlreadySent + ReplyAlreadySent + + + + The requestContext has been aborted. + The requestContext has been aborted. + + + + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + + + + IAsyncResult not provided or of wrong type. + IAsyncResult not provided or of wrong type. + + + + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + + + + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + + + + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + Seek is not supported on this stream. + Seek is not supported on this stream. + + + + The formatter '{0}' does not support serializing replies. + The formatter '{0}' does not support serializing replies. + + + + The formatter '{0}' does not support serializing requests. + The formatter '{0}' does not support serializing requests. + + + + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + + + + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + + + + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Argument {0} must be a non-negative timeout value. Provided value was {1}. + Argument {0} must be a non-negative timeout value. Provided value was {1}. + + + + Argument {0} must be a positive timeout value. Provided value was {1}. + Argument {0} must be a positive timeout value. Provided value was {1}. + + + + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + + + + Type '{0}' is not supported by '{1}'. + Type '{0}' is not supported by '{1}'. + + + + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + + + + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + + + + UriTemplate.BindByName was called with an empty key in the parameters collection. + UriTemplate.BindByName was called with an empty key in the parameters collection. + + + + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + + + + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + + + + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + + + + Cannot look up compound segment results before a successful Match has been performed. + Cannot look up compound segment results before a successful Match has been performed. + + + + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + + + + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + + + + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + + + + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + + + + The Defaults dictionary on the UriTemplate is immutable. + The Defaults dictionary on the UriTemplate is immutable. + + + + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + + + + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + + + + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + + + + UriTemplate '{0}' has invalid variable declaration '{1}'. + UriTemplate '{0}' has invalid variable declaration '{1}'. + + + + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + + + + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + + + + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + + + + UriTemplate '{0}' has a query string that ends in '&'. + UriTemplate '{0}' has a query string that ends in '&'. + + + + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + + + + UriTemplate '{0}' has a query parameter with an empty name. + UriTemplate '{0}' has a query parameter with an empty name. + + + + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + + + + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + + + + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + + + + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + + + + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + + + + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + + + + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + + + + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + + + + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + + + + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + + + + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + + + + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + + + + Unknown WebContentFormat '{0}'. + Unknown WebContentFormat '{0}'. + + + + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + + + + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + + + + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + + + + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + + + + The value supplied must be non-negative. + The value supplied must be non-negative. + + + + The value supplied must be greater than zero. + The value supplied must be greater than zero. + + + + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + Weak entity tags (W/"...") are not supported in this context. + Weak entity tags (W/"...") are not supported in this context. + + + + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + + + + WebBodyFormatMessageProperty(Format={0}) + WebBodyFormatMessageProperty(Format={0}) + + + + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + + + + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + + + + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + + + + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + + + + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + + + + The incoming HTTP request's URI '{0}' does not match any service operation. + The incoming HTTP request's URI '{0}' does not match any service operation. + + + + The XmlBuffer's quota has been exceeded. + The XmlBuffer's quota has been exceeded. + + + + New types cannot be registered with serializer manager after the service has been opened. + New types cannot be registered with serializer manager after the service has been opened. + + + + The '{0}' method is not supported by the stream. + The '{0}' method is not supported by the stream. + + + + The get accessor of the '{0}' property is not supported by the stream. + The get accessor of the '{0}' property is not supported by the stream. + + + + The set accessor of the '{0}' property is not supported by the stream. + The set accessor of the '{0}' property is not supported by the stream. + + + + + \ No newline at end of file diff --git a/src/System.ServiceModel.Web/src/Resources/xlf/Strings.pt-BR.xlf b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.pt-BR.xlf new file mode 100644 index 00000000000..609d9213100 --- /dev/null +++ b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.pt-BR.xlf @@ -0,0 +1,827 @@ + + + + + + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + + + + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + + + + Bind parameters cannot be null or empty for path variable '{0}'. + Bind parameters cannot be null or empty for path variable '{0}'. + + + + This buffer cannot be returned to the buffer manager because it is the wrong size. + This buffer cannot be returned to the buffer manager because it is the wrong size. + + + + The size quota for this stream ({0}) has been exceeded. + The size quota for this stream ({0}) has been exceeded. + + + + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + + + + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + + + + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + + + + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + + + + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + + + + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + + + + Cross domain javascript callback is not supported in authenticated services. + Cross domain javascript callback is not supported in authenticated services. + + + + CrossDomainScriptAccessEnabled cannot be used in Clients. + CrossDomainScriptAccessEnabled cannot be used in Clients. + + + + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + + + + A registration already exists for URI '{0}'. + A registration already exists for URI '{0}'. + + + + Cannot process contentType. + Cannot process contentType. + + + + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + + + + Unrecognized charSet '{0}' in contentType. + Unrecognized charSet '{0}' in contentType. + + + + The ServiceEndpoint's Address is null. Address must be an absolute uri. + The ServiceEndpoint's Address is null. Address must be an absolute uri. + + + + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + + + + This message formatter cannot be used to process response messages. + This message formatter cannot be used to process response messages. + + + + This message formatter cannot be used to process request messages. + This message formatter cannot be used to process request messages. + + + + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + + + + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + + + + Endpoint not found. + Endpoint not found. + + + + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + + + + Method not allowed. + Method not allowed. + + + + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + + + + Request Error + Request Error + + + + Service + Service + + + + The server encountered an error processing the request. See server logs for more details. + The server encountered an error processing the request. See server logs for more details. + + + + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + + + + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + + + + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + + + + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + + + + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + + + + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + + + + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + + + + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + + + + WebMessageEncodingBindingElement only supports MessageVersion.None. + WebMessageEncodingBindingElement only supports MessageVersion.None. + + + + The value must be in the range [{0}, {1}]. + The value must be in the range [{0}, {1}]. + + + + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + + + + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + + + + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + + + + The maximum message size quota for outgoing messages ({0}) has been exceeded. + The maximum message size quota for outgoing messages ({0}) has been exceeded. + + + + The message body is a Stream and cannot be re-read. + The message body is a Stream and cannot be re-read. + + + + The message body is missing or empty. + The message body is missing or empty. + + + + The XmlReader used to read the message body is in an invalid read state '{0}'. + The XmlReader used to read the message body is in an invalid read state '{0}'. + + + + The MessageBuffer has been closed and can no longer be used. + The MessageBuffer has been closed and can no longer be used. + + + + The message has been closed and can no longer be used. + The message has been closed and can no longer be used. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + + + + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + The text encoding '{0}' used in the text message format is not supported. + The text encoding '{0}' used in the text message format is not supported. + + + + Unknown MessageVersion. + Unknown MessageVersion. + + + + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + + + + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + + + + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + + + + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + + + + The {0} object has been disposed. + The {0} object has been disposed. + + + + Object is read-only. + Object is read-only. + + + + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + + + + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + + + + The operation '{0}' does not support '{1}' as a response format. + The operation '{0}' does not support '{1}' as a response format. + + + + Could not find operation name in the message properties. + Could not find operation name in the message properties. + + + + This operation is supported only when the operation selector is of type '{0}'. + This operation is supported only when the operation selector is of type '{0}'. + + + + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + + + + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + + + + Read is not supported on this stream. + Read is not supported on this stream. + + + + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + + + + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + ReplyAlreadySent + ReplyAlreadySent + + + + The requestContext has been aborted. + The requestContext has been aborted. + + + + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + + + + IAsyncResult not provided or of wrong type. + IAsyncResult not provided or of wrong type. + + + + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + + + + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + + + + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + Seek is not supported on this stream. + Seek is not supported on this stream. + + + + The formatter '{0}' does not support serializing replies. + The formatter '{0}' does not support serializing replies. + + + + The formatter '{0}' does not support serializing requests. + The formatter '{0}' does not support serializing requests. + + + + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + + + + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + + + + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Argument {0} must be a non-negative timeout value. Provided value was {1}. + Argument {0} must be a non-negative timeout value. Provided value was {1}. + + + + Argument {0} must be a positive timeout value. Provided value was {1}. + Argument {0} must be a positive timeout value. Provided value was {1}. + + + + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + + + + Type '{0}' is not supported by '{1}'. + Type '{0}' is not supported by '{1}'. + + + + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + + + + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + + + + UriTemplate.BindByName was called with an empty key in the parameters collection. + UriTemplate.BindByName was called with an empty key in the parameters collection. + + + + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + + + + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + + + + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + + + + Cannot look up compound segment results before a successful Match has been performed. + Cannot look up compound segment results before a successful Match has been performed. + + + + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + + + + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + + + + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + + + + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + + + + The Defaults dictionary on the UriTemplate is immutable. + The Defaults dictionary on the UriTemplate is immutable. + + + + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + + + + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + + + + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + + + + UriTemplate '{0}' has invalid variable declaration '{1}'. + UriTemplate '{0}' has invalid variable declaration '{1}'. + + + + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + + + + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + + + + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + + + + UriTemplate '{0}' has a query string that ends in '&'. + UriTemplate '{0}' has a query string that ends in '&'. + + + + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + + + + UriTemplate '{0}' has a query parameter with an empty name. + UriTemplate '{0}' has a query parameter with an empty name. + + + + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + + + + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + + + + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + + + + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + + + + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + + + + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + + + + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + + + + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + + + + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + + + + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + + + + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + + + + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + + + + Unknown WebContentFormat '{0}'. + Unknown WebContentFormat '{0}'. + + + + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + + + + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + + + + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + + + + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + + + + The value supplied must be non-negative. + The value supplied must be non-negative. + + + + The value supplied must be greater than zero. + The value supplied must be greater than zero. + + + + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + Weak entity tags (W/"...") are not supported in this context. + Weak entity tags (W/"...") are not supported in this context. + + + + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + + + + WebBodyFormatMessageProperty(Format={0}) + WebBodyFormatMessageProperty(Format={0}) + + + + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + + + + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + + + + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + + + + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + + + + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + + + + The incoming HTTP request's URI '{0}' does not match any service operation. + The incoming HTTP request's URI '{0}' does not match any service operation. + + + + The XmlBuffer's quota has been exceeded. + The XmlBuffer's quota has been exceeded. + + + + New types cannot be registered with serializer manager after the service has been opened. + New types cannot be registered with serializer manager after the service has been opened. + + + + The '{0}' method is not supported by the stream. + The '{0}' method is not supported by the stream. + + + + The get accessor of the '{0}' property is not supported by the stream. + The get accessor of the '{0}' property is not supported by the stream. + + + + The set accessor of the '{0}' property is not supported by the stream. + The set accessor of the '{0}' property is not supported by the stream. + + + + + \ No newline at end of file diff --git a/src/System.ServiceModel.Web/src/Resources/xlf/Strings.ru.xlf b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.ru.xlf new file mode 100644 index 00000000000..a1c2f133797 --- /dev/null +++ b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.ru.xlf @@ -0,0 +1,827 @@ + + + + + + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + + + + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + + + + Bind parameters cannot be null or empty for path variable '{0}'. + Bind parameters cannot be null or empty for path variable '{0}'. + + + + This buffer cannot be returned to the buffer manager because it is the wrong size. + This buffer cannot be returned to the buffer manager because it is the wrong size. + + + + The size quota for this stream ({0}) has been exceeded. + The size quota for this stream ({0}) has been exceeded. + + + + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + + + + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + + + + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + + + + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + + + + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + + + + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + + + + Cross domain javascript callback is not supported in authenticated services. + Cross domain javascript callback is not supported in authenticated services. + + + + CrossDomainScriptAccessEnabled cannot be used in Clients. + CrossDomainScriptAccessEnabled cannot be used in Clients. + + + + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + + + + A registration already exists for URI '{0}'. + A registration already exists for URI '{0}'. + + + + Cannot process contentType. + Cannot process contentType. + + + + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + + + + Unrecognized charSet '{0}' in contentType. + Unrecognized charSet '{0}' in contentType. + + + + The ServiceEndpoint's Address is null. Address must be an absolute uri. + The ServiceEndpoint's Address is null. Address must be an absolute uri. + + + + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + + + + This message formatter cannot be used to process response messages. + This message formatter cannot be used to process response messages. + + + + This message formatter cannot be used to process request messages. + This message formatter cannot be used to process request messages. + + + + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + + + + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + + + + Endpoint not found. + Endpoint not found. + + + + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + + + + Method not allowed. + Method not allowed. + + + + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + + + + Request Error + Request Error + + + + Service + Service + + + + The server encountered an error processing the request. See server logs for more details. + The server encountered an error processing the request. See server logs for more details. + + + + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + + + + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + + + + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + + + + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + + + + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + + + + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + + + + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + + + + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + + + + WebMessageEncodingBindingElement only supports MessageVersion.None. + WebMessageEncodingBindingElement only supports MessageVersion.None. + + + + The value must be in the range [{0}, {1}]. + The value must be in the range [{0}, {1}]. + + + + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + + + + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + + + + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + + + + The maximum message size quota for outgoing messages ({0}) has been exceeded. + The maximum message size quota for outgoing messages ({0}) has been exceeded. + + + + The message body is a Stream and cannot be re-read. + The message body is a Stream and cannot be re-read. + + + + The message body is missing or empty. + The message body is missing or empty. + + + + The XmlReader used to read the message body is in an invalid read state '{0}'. + The XmlReader used to read the message body is in an invalid read state '{0}'. + + + + The MessageBuffer has been closed and can no longer be used. + The MessageBuffer has been closed and can no longer be used. + + + + The message has been closed and can no longer be used. + The message has been closed and can no longer be used. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + + + + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + The text encoding '{0}' used in the text message format is not supported. + The text encoding '{0}' used in the text message format is not supported. + + + + Unknown MessageVersion. + Unknown MessageVersion. + + + + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + + + + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + + + + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + + + + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + + + + The {0} object has been disposed. + The {0} object has been disposed. + + + + Object is read-only. + Object is read-only. + + + + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + + + + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + + + + The operation '{0}' does not support '{1}' as a response format. + The operation '{0}' does not support '{1}' as a response format. + + + + Could not find operation name in the message properties. + Could not find operation name in the message properties. + + + + This operation is supported only when the operation selector is of type '{0}'. + This operation is supported only when the operation selector is of type '{0}'. + + + + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + + + + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + + + + Read is not supported on this stream. + Read is not supported on this stream. + + + + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + + + + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + ReplyAlreadySent + ReplyAlreadySent + + + + The requestContext has been aborted. + The requestContext has been aborted. + + + + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + + + + IAsyncResult not provided or of wrong type. + IAsyncResult not provided or of wrong type. + + + + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + + + + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + + + + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + Seek is not supported on this stream. + Seek is not supported on this stream. + + + + The formatter '{0}' does not support serializing replies. + The formatter '{0}' does not support serializing replies. + + + + The formatter '{0}' does not support serializing requests. + The formatter '{0}' does not support serializing requests. + + + + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + + + + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + + + + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Argument {0} must be a non-negative timeout value. Provided value was {1}. + Argument {0} must be a non-negative timeout value. Provided value was {1}. + + + + Argument {0} must be a positive timeout value. Provided value was {1}. + Argument {0} must be a positive timeout value. Provided value was {1}. + + + + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + + + + Type '{0}' is not supported by '{1}'. + Type '{0}' is not supported by '{1}'. + + + + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + + + + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + + + + UriTemplate.BindByName was called with an empty key in the parameters collection. + UriTemplate.BindByName was called with an empty key in the parameters collection. + + + + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + + + + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + + + + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + + + + Cannot look up compound segment results before a successful Match has been performed. + Cannot look up compound segment results before a successful Match has been performed. + + + + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + + + + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + + + + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + + + + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + + + + The Defaults dictionary on the UriTemplate is immutable. + The Defaults dictionary on the UriTemplate is immutable. + + + + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + + + + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + + + + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + + + + UriTemplate '{0}' has invalid variable declaration '{1}'. + UriTemplate '{0}' has invalid variable declaration '{1}'. + + + + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + + + + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + + + + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + + + + UriTemplate '{0}' has a query string that ends in '&'. + UriTemplate '{0}' has a query string that ends in '&'. + + + + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + + + + UriTemplate '{0}' has a query parameter with an empty name. + UriTemplate '{0}' has a query parameter with an empty name. + + + + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + + + + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + + + + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + + + + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + + + + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + + + + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + + + + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + + + + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + + + + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + + + + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + + + + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + + + + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + + + + Unknown WebContentFormat '{0}'. + Unknown WebContentFormat '{0}'. + + + + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + + + + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + + + + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + + + + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + + + + The value supplied must be non-negative. + The value supplied must be non-negative. + + + + The value supplied must be greater than zero. + The value supplied must be greater than zero. + + + + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + Weak entity tags (W/"...") are not supported in this context. + Weak entity tags (W/"...") are not supported in this context. + + + + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + + + + WebBodyFormatMessageProperty(Format={0}) + WebBodyFormatMessageProperty(Format={0}) + + + + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + + + + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + + + + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + + + + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + + + + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + + + + The incoming HTTP request's URI '{0}' does not match any service operation. + The incoming HTTP request's URI '{0}' does not match any service operation. + + + + The XmlBuffer's quota has been exceeded. + The XmlBuffer's quota has been exceeded. + + + + New types cannot be registered with serializer manager after the service has been opened. + New types cannot be registered with serializer manager after the service has been opened. + + + + The '{0}' method is not supported by the stream. + The '{0}' method is not supported by the stream. + + + + The get accessor of the '{0}' property is not supported by the stream. + The get accessor of the '{0}' property is not supported by the stream. + + + + The set accessor of the '{0}' property is not supported by the stream. + The set accessor of the '{0}' property is not supported by the stream. + + + + + \ No newline at end of file diff --git a/src/System.ServiceModel.Web/src/Resources/xlf/Strings.tr.xlf b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.tr.xlf new file mode 100644 index 00000000000..9db6faa80b8 --- /dev/null +++ b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.tr.xlf @@ -0,0 +1,827 @@ + + + + + + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + + + + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + + + + Bind parameters cannot be null or empty for path variable '{0}'. + Bind parameters cannot be null or empty for path variable '{0}'. + + + + This buffer cannot be returned to the buffer manager because it is the wrong size. + This buffer cannot be returned to the buffer manager because it is the wrong size. + + + + The size quota for this stream ({0}) has been exceeded. + The size quota for this stream ({0}) has been exceeded. + + + + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + + + + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + + + + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + + + + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + + + + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + + + + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + + + + Cross domain javascript callback is not supported in authenticated services. + Cross domain javascript callback is not supported in authenticated services. + + + + CrossDomainScriptAccessEnabled cannot be used in Clients. + CrossDomainScriptAccessEnabled cannot be used in Clients. + + + + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + + + + A registration already exists for URI '{0}'. + A registration already exists for URI '{0}'. + + + + Cannot process contentType. + Cannot process contentType. + + + + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + + + + Unrecognized charSet '{0}' in contentType. + Unrecognized charSet '{0}' in contentType. + + + + The ServiceEndpoint's Address is null. Address must be an absolute uri. + The ServiceEndpoint's Address is null. Address must be an absolute uri. + + + + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + + + + This message formatter cannot be used to process response messages. + This message formatter cannot be used to process response messages. + + + + This message formatter cannot be used to process request messages. + This message formatter cannot be used to process request messages. + + + + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + + + + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + + + + Endpoint not found. + Endpoint not found. + + + + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + + + + Method not allowed. + Method not allowed. + + + + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + + + + Request Error + Request Error + + + + Service + Service + + + + The server encountered an error processing the request. See server logs for more details. + The server encountered an error processing the request. See server logs for more details. + + + + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + + + + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + + + + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + + + + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + + + + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + + + + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + + + + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + + + + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + + + + WebMessageEncodingBindingElement only supports MessageVersion.None. + WebMessageEncodingBindingElement only supports MessageVersion.None. + + + + The value must be in the range [{0}, {1}]. + The value must be in the range [{0}, {1}]. + + + + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + + + + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + + + + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + + + + The maximum message size quota for outgoing messages ({0}) has been exceeded. + The maximum message size quota for outgoing messages ({0}) has been exceeded. + + + + The message body is a Stream and cannot be re-read. + The message body is a Stream and cannot be re-read. + + + + The message body is missing or empty. + The message body is missing or empty. + + + + The XmlReader used to read the message body is in an invalid read state '{0}'. + The XmlReader used to read the message body is in an invalid read state '{0}'. + + + + The MessageBuffer has been closed and can no longer be used. + The MessageBuffer has been closed and can no longer be used. + + + + The message has been closed and can no longer be used. + The message has been closed and can no longer be used. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + + + + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + The text encoding '{0}' used in the text message format is not supported. + The text encoding '{0}' used in the text message format is not supported. + + + + Unknown MessageVersion. + Unknown MessageVersion. + + + + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + + + + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + + + + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + + + + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + + + + The {0} object has been disposed. + The {0} object has been disposed. + + + + Object is read-only. + Object is read-only. + + + + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + + + + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + + + + The operation '{0}' does not support '{1}' as a response format. + The operation '{0}' does not support '{1}' as a response format. + + + + Could not find operation name in the message properties. + Could not find operation name in the message properties. + + + + This operation is supported only when the operation selector is of type '{0}'. + This operation is supported only when the operation selector is of type '{0}'. + + + + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + + + + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + + + + Read is not supported on this stream. + Read is not supported on this stream. + + + + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + + + + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + ReplyAlreadySent + ReplyAlreadySent + + + + The requestContext has been aborted. + The requestContext has been aborted. + + + + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + + + + IAsyncResult not provided or of wrong type. + IAsyncResult not provided or of wrong type. + + + + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + + + + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + + + + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + Seek is not supported on this stream. + Seek is not supported on this stream. + + + + The formatter '{0}' does not support serializing replies. + The formatter '{0}' does not support serializing replies. + + + + The formatter '{0}' does not support serializing requests. + The formatter '{0}' does not support serializing requests. + + + + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + + + + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + + + + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Argument {0} must be a non-negative timeout value. Provided value was {1}. + Argument {0} must be a non-negative timeout value. Provided value was {1}. + + + + Argument {0} must be a positive timeout value. Provided value was {1}. + Argument {0} must be a positive timeout value. Provided value was {1}. + + + + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + + + + Type '{0}' is not supported by '{1}'. + Type '{0}' is not supported by '{1}'. + + + + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + + + + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + + + + UriTemplate.BindByName was called with an empty key in the parameters collection. + UriTemplate.BindByName was called with an empty key in the parameters collection. + + + + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + + + + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + + + + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + + + + Cannot look up compound segment results before a successful Match has been performed. + Cannot look up compound segment results before a successful Match has been performed. + + + + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + + + + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + + + + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + + + + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + + + + The Defaults dictionary on the UriTemplate is immutable. + The Defaults dictionary on the UriTemplate is immutable. + + + + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + + + + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + + + + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + + + + UriTemplate '{0}' has invalid variable declaration '{1}'. + UriTemplate '{0}' has invalid variable declaration '{1}'. + + + + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + + + + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + + + + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + + + + UriTemplate '{0}' has a query string that ends in '&'. + UriTemplate '{0}' has a query string that ends in '&'. + + + + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + + + + UriTemplate '{0}' has a query parameter with an empty name. + UriTemplate '{0}' has a query parameter with an empty name. + + + + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + + + + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + + + + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + + + + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + + + + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + + + + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + + + + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + + + + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + + + + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + + + + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + + + + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + + + + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + + + + Unknown WebContentFormat '{0}'. + Unknown WebContentFormat '{0}'. + + + + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + + + + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + + + + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + + + + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + + + + The value supplied must be non-negative. + The value supplied must be non-negative. + + + + The value supplied must be greater than zero. + The value supplied must be greater than zero. + + + + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + Weak entity tags (W/"...") are not supported in this context. + Weak entity tags (W/"...") are not supported in this context. + + + + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + + + + WebBodyFormatMessageProperty(Format={0}) + WebBodyFormatMessageProperty(Format={0}) + + + + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + + + + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + + + + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + + + + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + + + + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + + + + The incoming HTTP request's URI '{0}' does not match any service operation. + The incoming HTTP request's URI '{0}' does not match any service operation. + + + + The XmlBuffer's quota has been exceeded. + The XmlBuffer's quota has been exceeded. + + + + New types cannot be registered with serializer manager after the service has been opened. + New types cannot be registered with serializer manager after the service has been opened. + + + + The '{0}' method is not supported by the stream. + The '{0}' method is not supported by the stream. + + + + The get accessor of the '{0}' property is not supported by the stream. + The get accessor of the '{0}' property is not supported by the stream. + + + + The set accessor of the '{0}' property is not supported by the stream. + The set accessor of the '{0}' property is not supported by the stream. + + + + + \ No newline at end of file diff --git a/src/System.ServiceModel.Web/src/Resources/xlf/Strings.zh-Hans.xlf b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.zh-Hans.xlf new file mode 100644 index 00000000000..301239ddc8a --- /dev/null +++ b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.zh-Hans.xlf @@ -0,0 +1,827 @@ + + + + + + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + + + + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + + + + Bind parameters cannot be null or empty for path variable '{0}'. + Bind parameters cannot be null or empty for path variable '{0}'. + + + + This buffer cannot be returned to the buffer manager because it is the wrong size. + This buffer cannot be returned to the buffer manager because it is the wrong size. + + + + The size quota for this stream ({0}) has been exceeded. + The size quota for this stream ({0}) has been exceeded. + + + + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + + + + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + + + + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + + + + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + + + + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + + + + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + + + + Cross domain javascript callback is not supported in authenticated services. + Cross domain javascript callback is not supported in authenticated services. + + + + CrossDomainScriptAccessEnabled cannot be used in Clients. + CrossDomainScriptAccessEnabled cannot be used in Clients. + + + + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + + + + A registration already exists for URI '{0}'. + A registration already exists for URI '{0}'. + + + + Cannot process contentType. + Cannot process contentType. + + + + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + + + + Unrecognized charSet '{0}' in contentType. + Unrecognized charSet '{0}' in contentType. + + + + The ServiceEndpoint's Address is null. Address must be an absolute uri. + The ServiceEndpoint's Address is null. Address must be an absolute uri. + + + + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + + + + This message formatter cannot be used to process response messages. + This message formatter cannot be used to process response messages. + + + + This message formatter cannot be used to process request messages. + This message formatter cannot be used to process request messages. + + + + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + + + + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + + + + Endpoint not found. + Endpoint not found. + + + + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + + + + Method not allowed. + Method not allowed. + + + + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + + + + Request Error + Request Error + + + + Service + Service + + + + The server encountered an error processing the request. See server logs for more details. + The server encountered an error processing the request. See server logs for more details. + + + + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + + + + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + + + + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + + + + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + + + + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + + + + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + + + + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + + + + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + + + + WebMessageEncodingBindingElement only supports MessageVersion.None. + WebMessageEncodingBindingElement only supports MessageVersion.None. + + + + The value must be in the range [{0}, {1}]. + The value must be in the range [{0}, {1}]. + + + + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + + + + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + + + + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + + + + The maximum message size quota for outgoing messages ({0}) has been exceeded. + The maximum message size quota for outgoing messages ({0}) has been exceeded. + + + + The message body is a Stream and cannot be re-read. + The message body is a Stream and cannot be re-read. + + + + The message body is missing or empty. + The message body is missing or empty. + + + + The XmlReader used to read the message body is in an invalid read state '{0}'. + The XmlReader used to read the message body is in an invalid read state '{0}'. + + + + The MessageBuffer has been closed and can no longer be used. + The MessageBuffer has been closed and can no longer be used. + + + + The message has been closed and can no longer be used. + The message has been closed and can no longer be used. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + + + + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + The text encoding '{0}' used in the text message format is not supported. + The text encoding '{0}' used in the text message format is not supported. + + + + Unknown MessageVersion. + Unknown MessageVersion. + + + + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + + + + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + + + + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + + + + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + + + + The {0} object has been disposed. + The {0} object has been disposed. + + + + Object is read-only. + Object is read-only. + + + + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + + + + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + + + + The operation '{0}' does not support '{1}' as a response format. + The operation '{0}' does not support '{1}' as a response format. + + + + Could not find operation name in the message properties. + Could not find operation name in the message properties. + + + + This operation is supported only when the operation selector is of type '{0}'. + This operation is supported only when the operation selector is of type '{0}'. + + + + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + + + + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + + + + Read is not supported on this stream. + Read is not supported on this stream. + + + + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + + + + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + ReplyAlreadySent + ReplyAlreadySent + + + + The requestContext has been aborted. + The requestContext has been aborted. + + + + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + + + + IAsyncResult not provided or of wrong type. + IAsyncResult not provided or of wrong type. + + + + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + + + + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + + + + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + Seek is not supported on this stream. + Seek is not supported on this stream. + + + + The formatter '{0}' does not support serializing replies. + The formatter '{0}' does not support serializing replies. + + + + The formatter '{0}' does not support serializing requests. + The formatter '{0}' does not support serializing requests. + + + + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + + + + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + + + + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Argument {0} must be a non-negative timeout value. Provided value was {1}. + Argument {0} must be a non-negative timeout value. Provided value was {1}. + + + + Argument {0} must be a positive timeout value. Provided value was {1}. + Argument {0} must be a positive timeout value. Provided value was {1}. + + + + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + + + + Type '{0}' is not supported by '{1}'. + Type '{0}' is not supported by '{1}'. + + + + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + + + + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + + + + UriTemplate.BindByName was called with an empty key in the parameters collection. + UriTemplate.BindByName was called with an empty key in the parameters collection. + + + + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + + + + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + + + + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + + + + Cannot look up compound segment results before a successful Match has been performed. + Cannot look up compound segment results before a successful Match has been performed. + + + + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + + + + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + + + + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + + + + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + + + + The Defaults dictionary on the UriTemplate is immutable. + The Defaults dictionary on the UriTemplate is immutable. + + + + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + + + + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + + + + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + + + + UriTemplate '{0}' has invalid variable declaration '{1}'. + UriTemplate '{0}' has invalid variable declaration '{1}'. + + + + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + + + + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + + + + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + + + + UriTemplate '{0}' has a query string that ends in '&'. + UriTemplate '{0}' has a query string that ends in '&'. + + + + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + + + + UriTemplate '{0}' has a query parameter with an empty name. + UriTemplate '{0}' has a query parameter with an empty name. + + + + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + + + + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + + + + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + + + + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + + + + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + + + + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + + + + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + + + + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + + + + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + + + + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + + + + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + + + + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + + + + Unknown WebContentFormat '{0}'. + Unknown WebContentFormat '{0}'. + + + + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + + + + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + + + + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + + + + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + + + + The value supplied must be non-negative. + The value supplied must be non-negative. + + + + The value supplied must be greater than zero. + The value supplied must be greater than zero. + + + + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + Weak entity tags (W/"...") are not supported in this context. + Weak entity tags (W/"...") are not supported in this context. + + + + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + + + + WebBodyFormatMessageProperty(Format={0}) + WebBodyFormatMessageProperty(Format={0}) + + + + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + + + + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + + + + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + + + + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + + + + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + + + + The incoming HTTP request's URI '{0}' does not match any service operation. + The incoming HTTP request's URI '{0}' does not match any service operation. + + + + The XmlBuffer's quota has been exceeded. + The XmlBuffer's quota has been exceeded. + + + + New types cannot be registered with serializer manager after the service has been opened. + New types cannot be registered with serializer manager after the service has been opened. + + + + The '{0}' method is not supported by the stream. + The '{0}' method is not supported by the stream. + + + + The get accessor of the '{0}' property is not supported by the stream. + The get accessor of the '{0}' property is not supported by the stream. + + + + The set accessor of the '{0}' property is not supported by the stream. + The set accessor of the '{0}' property is not supported by the stream. + + + + + \ No newline at end of file diff --git a/src/System.ServiceModel.Web/src/Resources/xlf/Strings.zh-Hant.xlf b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.zh-Hant.xlf new file mode 100644 index 00000000000..6e833ad8f8f --- /dev/null +++ b/src/System.ServiceModel.Web/src/Resources/xlf/Strings.zh-Hant.xlf @@ -0,0 +1,827 @@ + + + + + + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + Operation '{0}' in contract '{1}' has multiple request body parameters, one of which is a Stream. When the Stream is a parameter, there can be no other parameters in the body. + + + + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + Operation '{0}' of contract '{1}' specifies multiple request body parameters to be serialized without any wrapper elements. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the BodyStyle property on the WebGetAttribute/WebInvokeAttribute to Wrapped. + + + + Bind parameters cannot be null or empty for path variable '{0}'. + Bind parameters cannot be null or empty for path variable '{0}'. + + + + This buffer cannot be returned to the buffer manager because it is the wrong size. + This buffer cannot be returned to the buffer manager because it is the wrong size. + + + + The size quota for this stream ({0}) has been exceeded. + The size quota for this stream ({0}) has been exceeded. + + + + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + Unable to deserialize XML body with root name '{0}' and root namespace '{1}' (for operation '{2}' and contract ('{3}', '{4}')) using {5}. Ensure that the type corresponding to the XML is added to the known types collection of the service. + + + + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + Type '{0}' of operation '{1}' and contract ('{2}', '{3}') could not be serialized. Ensure that the type can be serialized using {4} and add the type to the known types collection of the service if required. + + + + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + Certificate-based client authentication is not supported in TransportCredentialOnly security mode. Select the Transport security mode. + + + + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + Conditional retrieval (If-Modified-Since, If-None-Match) is only supported for HTTP GET and HEAD requests. + + + + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + Conditional update (If-Match, If-Unmodified-Since) is only supported for HTTP PUT, POST, and DELETE requests. + + + + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + {0} is not a valid encoding string for System.Text.Encoding.GetEncoding(string). + + + + Cross domain javascript callback is not supported in authenticated services. + Cross domain javascript callback is not supported in authenticated services. + + + + CrossDomainScriptAccessEnabled cannot be used in Clients. + CrossDomainScriptAccessEnabled cannot be used in Clients. + + + + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + WebContentFormat.Default cannot be set on a WebBodyFormatMessageProperty; use Xml, Json, or Raw instead. + + + + A registration already exists for URI '{0}'. + A registration already exists for URI '{0}'. + + + + Cannot process contentType. + Cannot process contentType. + + + + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + The envelope version of the outgoing message ({0}) does not match the envelope version of the encoder ({1}). + + + + Unrecognized charSet '{0}' in contentType. + Unrecognized charSet '{0}' in contentType. + + + + The ServiceEndpoint's Address is null. Address must be an absolute uri. + The ServiceEndpoint's Address is null. Address must be an absolute uri. + + + + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + The WebContentTypeMapper threw an exception while attempting to map the content type. See the inner exception for details. + + + + This message formatter cannot be used to process response messages. + This message formatter cannot be used to process response messages. + + + + This message formatter cannot be used to process request messages. + This message formatter cannot be used to process request messages. + + + + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has body parameter '{2}'. GET operations cannot have a body. Either make the parameter '{2}' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute. + + + + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + Operation '{0}' in contract '{1}' uses GET, but also has a parameter of MessageContract type '{2}'. GET operations cannot have a body. To use a MessageContract parameter type, switch from WebGetAttribute to WebInvokeAttribute. + + + + Endpoint not found. + Endpoint not found. + + + + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Endpoint not found. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;} + + + + Method not allowed. + Method not allowed. + + + + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + <p>Method not allowed. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service.</p> + + + + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + <p>There is no operation listening for <a href="{0}">{0}</a>, but there is an operation listening for <a href="{1}">{1}</a>, so you are being redirected there.</p> + + + + Request Error + Request Error + + + + Service + Service + + + + The server encountered an error processing the request. See server logs for more details. + The server encountered an error processing the request. See server logs for more details. + + + + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + The server encountered an error processing the request. The exception message is '{0}'. See server logs for more details. The exception stack trace is: + + + + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + <p>The server encountered an error processing the request. Please see the <a rel="help-page" href="{0}">service help page</a> for constructing valid requests to the service. The exception message is '{1}'. See server logs for more details. The exception stack trace is: </p> + + + + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + &lt;p&gt;The server encountered an error processing the request. Please see the &lt;a rel="help-page" href="{0}"&gt;service help page&lt;/a&gt; for constructing valid requests to the service.&lt;/p&gt; + + + + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + ClientCredentialType '{0}' can only be used on the server side, not the client side. Please use one of the following values instead 'None, Basic, Certificate, Digest, Ntlm, Windows'. + + + + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + HTTP context property '{0}' is missing from the incoming message. This typically means the message did not arrive over the WebHttpBinding transport. + + + + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + A message was dispatched to the UnhandledDispatchOperation, but was invoked without a Message as input. This error might be caused by a behavior that provided a bad IDispatchMessageFormatter for the EndpointDispatcher's DispatchRuntime's UnhandledDispatchOperation's Formatter. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') contains an unrecognized http body format value '{3}'. The expected body format value is '{4}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + Incoming message for operation '{0}' contains an unrecognized http body format value '{1}'. The expected body format value is '{2}'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + Operation '{0}' in contract '{1}' has a MessageContract parameter (of type '{2}') without a wrapper name and with more than one body element. MessageContract parameters without a wrapper element are supported only if they have zero or one body element. + + + + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + Operation '{0}' in contract '{1}' uses a MessageContract that has SOAP headers. SOAP headers are not supported by the None MessageVersion. + + + + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + Operation '{0}' (in contract '{1}' with namespace '{2}') specifies the http body format to be JSON but the serialization mechanism for the operation is not DataContract. JSON format is only supported with DataContract serialization. If you have an XmlSerializerFormatAttribute on the operation consider replacing it with DataContractFormatAttribute. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'null'. Found value '{0}'. + + + + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + OperationFormatter encountered an invalid Message body. Expected to find an attribute with name 'type' and value 'object'. Found value '{0}'. + + + + WebMessageEncodingBindingElement only supports MessageVersion.None. + WebMessageEncodingBindingElement only supports MessageVersion.None. + + + + The value must be in the range [{0}, {1}]. + The value must be in the range [{0}, {1}]. + + + + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + Cannot claim lock within the allotted timeout of {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + Operation '{0}' of contract '{1}' specifies MessageContract type '{2}' which has IsWrapped as false but has multiple request body parameters. At most one body parameter can be serialized without wrapper elements. Either remove the extra body parameters or set the IsWrapped property on the MessageContractAttribute to true. + + + + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + In the endpoint at '{0}', in order to use '{1}', the '{2}' of the binding must have ManualAddressing set to true. + + + + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + The maximum message size quota for incoming messages ({0}) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element. + + + + The maximum message size quota for outgoing messages ({0}) has been exceeded. + The maximum message size quota for outgoing messages ({0}) has been exceeded. + + + + The message body is a Stream and cannot be re-read. + The message body is a Stream and cannot be re-read. + + + + The message body is missing or empty. + The message body is missing or empty. + + + + The XmlReader used to read the message body is in an invalid read state '{0}'. + The XmlReader used to read the message body is in an invalid read state '{0}'. + + + + The MessageBuffer has been closed and can no longer be used. + The MessageBuffer has been closed and can no longer be used. + + + + The message has been closed and can no longer be used. + The message has been closed and can no longer be used. + + + + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message for operation '{0}' (contract '{1}' with namespace '{2}') does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + Message does not contain the http body format property. The encoder expects the http format property to be '{0}'. + + + + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + Incoming message does not contain a WebBodyFormatMessageProperty. This can be because a WebContentTypeMapper or a WebMessageEncodingBindingElement has not been configured on the binding. See the documentation of WebContentTypeMapper and WebMessageEncodingBindingElement for more details. + + + + The text encoding '{0}' used in the text message format is not supported. + The text encoding '{0}' used in the text message format is not supported. + + + + Unknown MessageVersion. + Unknown MessageVersion. + + + + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + In contract '{0}', there are multiple operations with Method '{2}' and a UriTemplate that is equivalent to '{1}'. Each operation requires a unique combination of UriTemplate and Method to unambiguously dispatch messages. Use WebGetAttribute or WebInvokeAttribute to alter the UriTemplate and Method values of an operation. + + + + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + Operation '{0}' in contract '{1}' has both WebGetAttribute and WebInvokeAttribute; only one can be present. + + + + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + Operation '{0}' in contract '{1}' has a Stream return value and also has out or ref parameters. When Stream is the return value of the operation, it cannot have ref or out parameters. + + + + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + Parameter '{0}' of operation '{1}' in contract '{2}' is a Stream, and is also a ref or out parameter. Stream cannot be a ref or out parameter. + + + + The {0} object has been disposed. + The {0} object has been disposed. + + + + Object is read-only. + Object is read-only. + + + + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + WebGetAttribute/WebInvokeAttribute supports setting the BodyStyle property to Bare only with DataContract and XmlSerializer serializable types. Operation '{0}' does not specify serialization using any of these formats. Add a DataContractFormatAttribute or XmlSerializerFormatAttribute to this operation to specify one of these serialization formats. + + + + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + Operation '{0}' of contract '{1}' specifies at least one response body parameter that is not a return value of the operation. Only the return value is allowed when the BodyStyle property of WebGetAttribute/WebInvokeAttribute is set to Bare. Either remove the extra response body parameters or set the BodyStyle property to Wrapped. + + + + The operation '{0}' does not support '{1}' as a response format. + The operation '{0}' does not support '{1}' as a response format. + + + + Could not find operation name in the message properties. + Could not find operation name in the message properties. + + + + This operation is supported only when the operation selector is of type '{0}'. + This operation is supported only when the operation selector is of type '{0}'. + + + + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + Parameter type '{0}' of operation '{1}' (contract '{2}' with namespace '{3}') is not of type Stream. Ensure that the parameter is of type Stream or derives from Stream. + + + + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + This operation formatter can only be used for deserializing requests; serializing replies is not supported since query strings are not used to represent parameters in replies. + + + + Read is not supported on this stream. + Read is not supported on this stream. + + + + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + The channel received an unexpected fault input message while closing. The fault reason given is: '{0}' + + + + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected fault input message with Action = '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + The channel received an unexpected input message with Action '{0}' while closing. You should only close your channel when you are not expecting any more input messages. + + + + ReplyAlreadySent + ReplyAlreadySent + + + + The requestContext has been aborted. + The requestContext has been aborted. + + + + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + Operation '{0}', belonging to contract ('{1}', '{2}') has an XmlSerializerFormatAttribute configured with OperationUse Encoded or OperationStyle Rpc. OperationUse Encoded and OperationStyle Rpc are not supported for web bindings. Configure the endpoint with a SOAP binding (like WSHttpBinding) in order to use these options. + + + + IAsyncResult not provided or of wrong type. + IAsyncResult not provided or of wrong type. + + + + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name '{0}' and namespace '{1}'. Found node type '{2}' with name '{3}' and namespace '{4}' + + + + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. Please see InnerException for more details. + + + + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to deserialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + There was an error while trying to serialize parameter {0}:{1}. The InnerException message was '{2}'. Please see InnerException for more details. + + + + Seek is not supported on this stream. + Seek is not supported on this stream. + + + + The formatter '{0}' does not support serializing replies. + The formatter '{0}' does not support serializing replies. + + + + The formatter '{0}' does not support serializing requests. + The formatter '{0}' does not support serializing requests. + + + + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + Unable to find the endpoint behavior WebHttpBehavior for endpoint address '{0}'. This is possibly caused by not calling ServiceModelWebServiceCollectionExtensions.AddServiceModelWebServices(IServiceCollection services). + + + + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + '{0}' does not allow the use of Streams with the MessageContract programming model. The service '{1}' defines an operation '{2}' that uses the MessageContract type '{3}'. '{3}' contains MessageBodyMember '{4}' of type Stream. + + + + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + The task timed out after {0}. The time allotted to this operation may have been a portion of a longer timeout. + + + + Argument {0} must be a non-negative timeout value. Provided value was {1}. + Argument {0} must be a non-negative timeout value. Provided value was {1}. + + + + Argument {0} must be a positive timeout value. Provided value was {1}. + Argument {0} must be a positive timeout value. Provided value was {1}. + + + + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + Cannot serialize parameter of type '{0}' (for operation '{1}', contract '{2}') because it is not the exact type '{3}' in the method signature and is not in the known types collection. In order to serialize the parameter, add the type to the known types collection for the operation using ServiceKnownTypeAttribute. + + + + Type '{0}' is not supported by '{1}'. + Type '{0}' is not supported by '{1}'. + + + + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + The additional default value with key '{0}' is invalid because the UriTemplate '{1}' does not contain a variable with that name. + + + + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + The base address must be an absolute URI with a scheme of http or https and no query or fragment. + + + + UriTemplate.BindByName was called with an empty key in the parameters collection. + UriTemplate.BindByName was called with an empty key in the parameters collection. + + + + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + UriTemplate '{0}' has no variables; UriTemplate.BindByPosition cannot be called with {1} value(s). + + + + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + UriTemplate '{0}' has {1} path variable(s) and {2} query variable(s) but was passed {3} value(s). + + + + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + The key '{0}' appears as both a literal segment and as a name in the name-value collection passed to UriTemplate.BindByName. + + + + Cannot look up compound segment results before a successful Match has been performed. + Cannot look up compound segment results before a successful Match has been performed. + + + + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + UriTemplate '{0}' has a compound path segment '{1}' that contains the variable '{2}' for which a default value was specified. Variables in compound segments cannot have default values. + + + + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + UriTemplate '{0}' has an additional default value for variable '{1}', but that variable appears inside a compound segment and cannot have a default value. + + + + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + UriTemplate '{0}' has a query value variable '{1}' with default value '{2}'. Query variables cannot have default values. + + + + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + UriTemplate '{0}' has an additional default value for query variable '{1}'. Query variables cannot have default values. + + + + The Defaults dictionary on the UriTemplate is immutable. + The Defaults dictionary on the UriTemplate is immutable. + + + + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + UriTemplate '{0}' contains compound path segment '{1}' with two adjacent variables. Adjacent variables in compound segments are not supported. + + + + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + UriTemplate '{0}' has variable '{1}' with default value '{2}'. The default value of a path variable cannot be null, empty, or contain a path separator. + + + + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + The segment or query part '{0}' has an invalid format. Variable names must be enclosed in matching braces. + + + + UriTemplate '{0}' has invalid variable declaration '{1}'. + UriTemplate '{0}' has invalid variable declaration '{1}'. + + + + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + UriTemplate '{0}' has invalid usage of wildcard '{1}'. Wildcards are only allowed as the last path segment and cannot be combined with other characters in the same segment. + + + + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + UriTemplate '{0}' has an additional default value for variable '{1}' that is null. Nullable defaults are only allowed when declared inline in the template. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by variable '{2}' which is not nullable. All path variables after a nullable variable must also be nullable. + + + + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + UriTemplate '{0}' has nullable default for variable '{1}' but that variable is followed by literal segment '{2}'. Path variables with nullable defaults cannot be followed by literal segments. + + + + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + UriTemplate '{0}' has nullable default for variable '{1}'. Path variables with nullable defaults cannot be followed by a wildcard segment. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a Message parameter. Message and UriTemplate parameters are incompatible. + + + + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + Operation '{0}' in contract '{1}' uses UriTemplate parameters, but also uses a MessageContract parameter. MessageContract and UriTemplate parameters are incompatible. + + + + UriTemplate '{0}' has a query string that ends in '&'. + UriTemplate '{0}' has a query string that ends in '&'. + + + + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + UriTemplate '{0}' has a query value that is a compound (mixed literal and variable) expression. Query values must be either pure literals or pure variables. + + + + UriTemplate '{0}' has a query parameter with an empty name. + UriTemplate '{0}' has a query parameter with an empty name. + + + + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + UriTemplate '{0}' has a query parameter with a variable name. Query parameter names must be literals. + + + + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + UriTemplate '{0}' has multiple query parameters with the same name. Query parameter names must be unique within a template. + + + + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has wildcard variable '{1}' with default value '{2}'. Wildcard variables cannot have default values. + + + + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + UriTemplate '{0}' has additional default value for wildcard variable '{1}'. Wildcard variables cannot have default values. + + + + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + UriTemplateTable contains templates with ambiguous query strings. Conflicting templates: '{0}'. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + The UriTemplateTable's BaseAddress must be set before this operation can be performed. + + + + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + The BaseAddress of the UriTemplateTable cannot be changed after the table has been made read-only. + + + + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + UriTemplateTable contains duplicate templates: '{0}' and '{1}'. + + + + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + The KeyValuePairs collection of the UriTemplateTable cannot be empty. + + + + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + '{0}' is not a valid UriTemplate string for use as a key in a UriTemplateTable. + + + + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + The URI matched multiple UriTemplates in this UriTemplateTable. Use Match() instead of MatchSingle() to get all results. + + + + The base address of the UriTemplateTable must be an absolute URI. + The base address of the UriTemplateTable must be an absolute URI. + + + + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + A UriTemplate key in the UriTemplateTable's KeyValuePairs collection cannot be null. + + + + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + UriTemplateTable contains templates with ambiguous query strings: '{0}'. + + + + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + UriTemplate '{0}' has multiple variables with the name '{1}'. Variable names must be unique within a template. + + + + Unknown WebContentFormat '{0}'. + Unknown WebContentFormat '{0}'. + + + + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + The incoming message has an unexpected message format '{0}'. The expected message formats for the operation are {1}. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details. + + + + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + Operation '{0}' in contract '{1}' has a UriTemplate that expects a parameter named '{2}', but there is no input parameter with that name on the operation. + + + + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + Operation '{0}' in contract '{1}' has a path variable named '{2}' which does not have type 'string'. Variables for UriTemplate path segments must have type 'string'. + + + + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + Operation '{0}' in contract '{1}' has a query variable named '{2}' of type '{3}', but type '{3}' is not convertible by '{4}'. Variables for UriTemplate query values must have types that can be converted by '{4}'. + + + + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + Operation '{0}' in contract '{1}' has multiple parameters named '{2}' that vary only in uppercase versus lowercase. The parameter names must be distinct. + + + + The value supplied must be non-negative. + The value supplied must be non-negative. + + + + The value supplied must be greater than zero. + The value supplied must be greater than zero. + + + + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with the None MessageVersion. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + The endpoint at '{0}' does not have a Binding with Scheme 'http' or 'https'. '{1}' is only intended for use with WebHttpBinding or similar bindings. + + + + Weak entity tags (W/"...") are not supported in this context. + Weak entity tags (W/"...") are not supported in this context. + + + + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a behavior of type '{1}'. The endpoint is initialized with the proper behavior and it should not be removed or replaced. + + + + WebBodyFormatMessageProperty(Format={0}) + WebBodyFormatMessageProperty(Format={0}) + + + + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + The standard endpoint of type '{0}' does not have a binding of type '{1}'. The endpoint is initialized with the proper binding and it should not be removed or replaced. + + + + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + Raw (application/octet-stream pass-through) content is not yet supported by the WebHttpBinding client. Use Xml or Json instead, or convert your payload to a typed parameter. + + + + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + WebHttpDispatchOperationSelector is server-side and is not supported in the client-only port of System.ServiceModel.Web. Construct a UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + + + + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + The endpoint address '{0}' has message headers and is being used with a binding that's configured for message version None. Either change the endpoint address to not contain message headers or change the binding to be one that supports SOAP (for example, WSHttpBinding). + + + + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + The HTTP method '{0}' of the incoming request (with URI '{1}') is not allowed. + + + + The incoming HTTP request's URI '{0}' does not match any service operation. + The incoming HTTP request's URI '{0}' does not match any service operation. + + + + The XmlBuffer's quota has been exceeded. + The XmlBuffer's quota has been exceeded. + + + + New types cannot be registered with serializer manager after the service has been opened. + New types cannot be registered with serializer manager after the service has been opened. + + + + The '{0}' method is not supported by the stream. + The '{0}' method is not supported by the stream. + + + + The get accessor of the '{0}' property is not supported by the stream. + The get accessor of the '{0}' property is not supported by the stream. + + + + The set accessor of the '{0}' property is not supported by the stream. + The set accessor of the '{0}' property is not supported by the stream. + + + + + \ No newline at end of file diff --git a/src/System.ServiceModel.Web/src/System.ServiceModel.Web.csproj b/src/System.ServiceModel.Web/src/System.ServiceModel.Web.csproj new file mode 100644 index 00000000000..6ad2f99e6a4 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System.ServiceModel.Web.csproj @@ -0,0 +1,39 @@ + + + $(WcfAssemblyVersion) + Microsoft + System.ServiceModel.Web + true + true + $(Ship_WcfPackages) + $(DotNetVersion) + System.ServiceModel + + false + true + + $(NoWarn);CS0105;CS0108;CS0436 + + + + + + + + + + + true + FxResources.$(AssemblyName).SR + false + System.SR + + + diff --git a/src/System.ServiceModel.Web/src/System/Collections/ObjectModel/FreezableCollection.cs b/src/System.ServiceModel.Web/src/System/Collections/ObjectModel/FreezableCollection.cs new file mode 100644 index 00000000000..455fdc6720b --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/Collections/ObjectModel/FreezableCollection.cs @@ -0,0 +1,78 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.Collections.ObjectModel +{ + using System; + using System.Collections.Generic; + using System.ServiceModel; + + internal class FreezableCollection : Collection, ICollection + { + bool frozen; + + public FreezableCollection() + : base() + { + } + + public FreezableCollection(IList list) + : base(list) + { + } + + public bool IsFrozen + { + get + { + return this.frozen; + } + } + + bool ICollection.IsReadOnly + { + get + { + return this.frozen; + } + } + + public void Freeze() + { + this.frozen = true; + } + + protected override void ClearItems() + { + ThrowIfFrozen(); + base.ClearItems(); + } + + protected override void InsertItem(int index, T item) + { + ThrowIfFrozen(); + base.InsertItem(index, item); + } + + protected override void RemoveItem(int index) + { + ThrowIfFrozen(); + base.RemoveItem(index); + } + + protected override void SetItem(int index, T item) + { + ThrowIfFrozen(); + base.SetItem(index, item); + } + + void ThrowIfFrozen() + { + if (this.frozen) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.ObjectIsReadOnly)); + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/ContentEncoding.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/ContentEncoding.cs new file mode 100644 index 00000000000..1f29ca7ab32 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/ContentEncoding.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System.Text; + +namespace System.ServiceModel.Channels +{ + internal class ContentEncoding + { + public string contentType; + public Encoding encoding; + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/ContentTypeHelpers.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/ContentTypeHelpers.cs new file mode 100644 index 00000000000..0b1a423dad9 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/ContentTypeHelpers.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Text; + +namespace System.ServiceModel.Channels +{ + // Helpers for matching content-type headers to encodings. + // Mirrors CoreWCF.Runtime.ContentTypeHelpers (client subset). + internal static class ContentTypeHelpers + { + public static Encoding[] GetSupportedEncodings() + { + Encoding[] supported = TextEncoderDefaults.SupportedEncodings; + Encoding[] copy = new Encoding[supported.Length]; + Array.Copy(supported, copy, supported.Length); + return copy; + } + + public static Encoding GetEncodingFromContentType(string contentType, ContentEncoding[] contentEncodingMap) + { + if (contentType == null) + { + return null; + } + + for (int i = 0; i < contentEncodingMap.Length; i++) + { + if (contentType.Equals(contentEncodingMap[i].contentType, StringComparison.OrdinalIgnoreCase)) + { + return contentEncodingMap[i].encoding; + } + } + + // Fall back to parsing the charset parameter if present. + try + { + System.Net.Http.Headers.MediaTypeHeaderValue parsed = + System.Net.Http.Headers.MediaTypeHeaderValue.Parse(contentType); + string charset = parsed.CharSet; + if (!string.IsNullOrEmpty(charset)) + { + if (TextEncoderDefaults.TryGetEncoding(charset, out Encoding encoding)) + { + return encoding; + } + } + } + catch (FormatException) + { + // Malformed content-type: caller will surface the error. + } + + return null; + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/HttpStreamMessage.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/HttpStreamMessage.cs new file mode 100644 index 00000000000..02c21b3d87f --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/HttpStreamMessage.cs @@ -0,0 +1,203 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Xml; +using System.Runtime; + +namespace System.ServiceModel.Channels +{ + internal class HttpStreamMessage : Message + { + internal const string StreamElementName = "Binary"; + private BodyWriter _bodyWriter; + private readonly MessageHeaders _headers; + private readonly MessageProperties _properties; + + public HttpStreamMessage(BodyWriter writer) + { + _bodyWriter = writer ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(writer)); + _headers = new MessageHeaders(MessageVersion.None, 1); + _properties = new MessageProperties(); + } + + public HttpStreamMessage(MessageHeaders headers, MessageProperties properties, BodyWriter bodyWriter) + { + _headers = new MessageHeaders(headers); + _properties = new MessageProperties(properties); + _bodyWriter = bodyWriter ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(bodyWriter)); + } + + public override MessageHeaders Headers + { + get + { + if (IsDisposed) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateDisposedException()); + } + + return _headers; + } + } + + public override bool IsEmpty => false; + + public override bool IsFault => false; + + public override MessageProperties Properties + { + get + { + if (IsDisposed) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateDisposedException()); + } + + return _properties; + } + } + + public override MessageVersion Version + { + get + { + if (IsDisposed) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateDisposedException()); + } + + return MessageVersion.None; + } + } + + protected override void OnBodyToString(XmlDictionaryWriter writer) + { + if (_bodyWriter.IsBuffered) + { + _bodyWriter.WriteBodyContents(writer); + } + else + { + writer.WriteString(SR.Format(SR.MessageBodyIsStream)); + } + } + + protected override void OnClose() + { + Exception ex = null; + try + { + base.OnClose(); + } + catch (Exception e) + { + if (Fx.IsFatal(e)) + { + throw; + } + ex = e; + } + + try + { + if (_properties != null) + { + _properties.Dispose(); + } + } + catch (Exception e) + { + if (Fx.IsFatal(e)) + { + throw; + } + if (ex == null) + { + ex = e; + } + } + + if (ex != null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(ex); + } + + _bodyWriter = null; + } + + protected override MessageBuffer OnCreateBufferedCopy(int maxBufferSize) + { + BodyWriter bufferedBodyWriter; + if (_bodyWriter.IsBuffered) + { + bufferedBodyWriter = _bodyWriter; + } + else + { + bufferedBodyWriter = _bodyWriter.CreateBufferedCopy(maxBufferSize); + } + + return new HttpStreamMessageBuffer(Headers, new MessageProperties(Properties), bufferedBodyWriter); + } + + protected override void OnWriteBodyContents(XmlDictionaryWriter writer) + { + _bodyWriter.WriteBodyContents(writer); + } + + private Exception CreateDisposedException() => new ObjectDisposedException("", SR.Format(SR.MessageClosed)); + + internal class HttpStreamMessageBuffer : MessageBuffer + { + private BodyWriter _bodyWriter; + private bool _closed; + private MessageHeaders _headers; + private MessageProperties _properties; + + public HttpStreamMessageBuffer(MessageHeaders headers, + MessageProperties properties, BodyWriter bodyWriter) + : base() + { + _bodyWriter = bodyWriter; + _headers = headers; + _properties = properties; + } + + public override int BufferSize => 0; + + private object ThisLock { get; } = new object(); + + public override void Close() + { + lock (ThisLock) + { + if (!_closed) + { + _closed = true; + _bodyWriter = null; + _headers = null; + _properties = null; + } + } + } + + public override Message CreateMessage() + { + lock (ThisLock) + { + if (_closed) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateDisposedException()); + } + return new HttpStreamMessage(_headers, _properties, _bodyWriter); + } + } + + private Exception CreateDisposedException() + { + return new ObjectDisposedException("", SR.Format(SR.MessageBufferIsClosed)); + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/JsonGlobals.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/JsonGlobals.cs new file mode 100644 index 00000000000..2cf84d0c8a2 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/JsonGlobals.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.ServiceModel.Channels +{ + // Minimal subset of JsonGlobals constants used by the Web HTTP encoder factories. + // Mirrors CoreWCF.Runtime.JsonGlobals. + internal static class JsonGlobals + { + public const string ApplicationJsonMediaType = "application/json"; + public const string TextJsonMediaType = "text/json"; + + // XML dictionary string constants used by DataContractJsonSerializer-emitted XML. + public const string RootString = "root"; + public const string ItemString = "item"; + public const string TypeString = "type"; + public const string ObjectString = "object"; + public const string DString = "d"; + public const string NullString = "null"; + + // Pre-created dictionary strings. + public static readonly System.Xml.XmlDictionaryString RootDictionaryString = + new System.Xml.XmlDictionary().Add(RootString); + public static readonly System.Xml.XmlDictionaryString ItemDictionaryString = + new System.Xml.XmlDictionary().Add(ItemString); + public static readonly System.Xml.XmlDictionaryString DDictionaryString = + new System.Xml.XmlDictionary().Add(DString); + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/JsonMessageEncoderFactory.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/JsonMessageEncoderFactory.cs new file mode 100644 index 00000000000..ee2a0ed69e8 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/JsonMessageEncoderFactory.cs @@ -0,0 +1,529 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.IO; +using System.Runtime.Serialization.Json; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using System.Runtime; +using Microsoft.Extensions.ObjectPool; + +namespace System.ServiceModel.Channels +{ + internal class JsonMessageEncoderFactory : MessageEncoderFactory + { + private static readonly ContentEncoding[] s_applicationJsonContentEncoding = GetContentEncodingMap(JsonGlobals.ApplicationJsonMediaType); + private readonly JsonMessageEncoder _messageEncoder; + + public JsonMessageEncoderFactory(Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, XmlDictionaryReaderQuotas quotas, bool crossDomainScriptAccessEnabled) + { + _messageEncoder = new JsonMessageEncoder(writeEncoding, maxReadPoolSize, maxWritePoolSize, quotas, crossDomainScriptAccessEnabled); + } + + public override MessageEncoder Encoder => _messageEncoder; + + public override MessageVersion MessageVersion => _messageEncoder.MessageVersion; + + internal static string GetContentType(WebMessageEncodingBindingElement encodingElement) + { + if (encodingElement == null) + { + return WebMessageEncoderFactory.GetContentType(JsonGlobals.ApplicationJsonMediaType, TextEncoderDefaults.Encoding); + } + else + { + return WebMessageEncoderFactory.GetContentType(JsonGlobals.ApplicationJsonMediaType, encodingElement.WriteEncoding); + } + } + + private static ContentEncoding[] GetContentEncodingMap(string mediaType) + { + Encoding[] readEncodings = ContentTypeHelpers.GetSupportedEncodings(); + ContentEncoding[] map = new ContentEncoding[readEncodings.Length]; + for (int i = 0; i < readEncodings.Length; i++) + { + ContentEncoding contentEncoding = new ContentEncoding(); + contentEncoding.contentType = WebMessageEncoderFactory.GetContentType(mediaType, readEncodings[i]); + contentEncoding.encoding = readEncodings[i]; + map[i] = contentEncoding; + } + + return map; + } + + internal class JsonMessageEncoder : MessageEncoder + { + private const int MaxPooledXmlReadersPerMessage = 2; + + // Double-checked locking pattern requires volatile for read/write synchronization + private volatile SynchronizedPool _bufferedReaderPool; + private volatile SynchronizedPool _bufferedWriterPool; + private readonly int _maxReadPoolSize; + private readonly int _maxWritePoolSize; + private readonly OnXmlDictionaryReaderClose _onStreamedReaderClose; + private readonly XmlDictionaryReaderQuotas _readerQuotas; + private readonly XmlDictionaryReaderQuotas _bufferedReadReaderQuotas; + + // Double-checked locking pattern requires volatile for read/write synchronization + private volatile SynchronizedPool _recycledStatePool; + private volatile SynchronizedPool _streamedReaderPool; + private volatile SynchronizedPool _streamedWriterPool; + private readonly Encoding _writeEncoding; + + public JsonMessageEncoder(Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, XmlDictionaryReaderQuotas quotas, bool crossDomainScriptAccessEnabled) + { + if (writeEncoding == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(writeEncoding)); + } + + ThisLock = new object(); + + TextEncoderDefaults.ValidateEncoding(writeEncoding); + _writeEncoding = writeEncoding; + + _maxReadPoolSize = maxReadPoolSize; + _maxWritePoolSize = maxWritePoolSize; + + _readerQuotas = new XmlDictionaryReaderQuotas(); + _onStreamedReaderClose = new OnXmlDictionaryReaderClose(ReturnStreamedReader); + quotas.CopyTo(_readerQuotas); + + _bufferedReadReaderQuotas = EncoderHelpers.GetBufferedReadQuotas(_readerQuotas); + + ContentType = WebMessageEncoderFactory.GetContentType(JsonGlobals.ApplicationJsonMediaType, writeEncoding); + } + + public override string ContentType { get; } + + public override string MediaType => JsonGlobals.ApplicationJsonMediaType; + + public override MessageVersion MessageVersion => MessageVersion.None; + + private SynchronizedPool RecycledStatePool + { + get + { + if (_recycledStatePool == null) + { + lock (ThisLock) + { + if (_recycledStatePool == null) + { + _recycledStatePool = new SynchronizedPool(_maxReadPoolSize); + } + } + } + + return _recycledStatePool; + } + } + + private object ThisLock { get; } + + public override bool IsContentTypeSupported(string contentType) + { + if (contentType == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(contentType)); + } + + return IsJsonContentType(contentType); + } + + public override Message ReadMessage(ArraySegment buffer, BufferManager bufferManager, string contentType) + { + if (bufferManager == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(bufferManager))); + } + + //if (WebTD.JsonMessageDecodingStartIsEnabled()) + //{ + // WebTD.JsonMessageDecodingStart(); + //} + + Message message; + + JsonBufferedMessageData messageData = TakeBufferedReader(); + messageData.Encoding = ContentTypeHelpers.GetEncodingFromContentType(contentType, JsonMessageEncoderFactory.s_applicationJsonContentEncoding); + messageData.Open(buffer, bufferManager); + RecycledMessageState messageState = messageData.TakeMessageState(); + if (messageState == null) + { + messageState = new RecycledMessageState(); + } + message = new BufferedMessage(messageData, messageState); + + message.Properties.Encoder = this; + + //if (SMTD.MessageReadByEncoderIsEnabled() && buffer != null) + //{ + // SMTD.MessageReadByEncoder( + // EventTraceActivityHelper.TryExtractActivity(message, true), + // buffer.Count, + // this); + //} + + //if (MessageLogger.LogMessagesAtTransportLevel) + //{ + // MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportReceive); + //} + + return message; + } + + public override ValueTask ReadMessageAsync(Stream stream, int maxSizeOfHeaders, string contentType) + { + if (stream == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(stream))); + } + + XmlReader reader = TakeStreamedReader(stream, ContentTypeHelpers.GetEncodingFromContentType(contentType, JsonMessageEncoderFactory.s_applicationJsonContentEncoding)); + Message message = Message.CreateMessage(reader, maxSizeOfHeaders, MessageVersion.None); + message.Properties.Encoder = this; + return new ValueTask(message); + } + + public override ArraySegment WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset) + { + if (message == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(message))); + } + + if (bufferManager == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(bufferManager)), message); + } + + if (maxMessageSize < 0) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(maxMessageSize), maxMessageSize, + SR.Format(SR.ValueMustBeNonNegative)), message); + } + + if (messageOffset < 0 || messageOffset > maxMessageSize) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(messageOffset), messageOffset, + SR.Format(SR.JsonValueMustBeInRange, 0, maxMessageSize)), message); + } + + //EventTraceActivity eventTraceActivity = null; + //if (WebTD.JsonMessageEncodingStartIsEnabled()) + //{ + // eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message); + // WebTD.JsonMessageEncodingStart(eventTraceActivity); + //} + + ThrowIfMismatchedMessageVersion(message); + message.Properties.Encoder = this; + JsonBufferedMessageWriter messageWriter = TakeBufferedWriter(); + + ArraySegment messageData = messageWriter.WriteMessage(message, bufferManager, messageOffset, maxMessageSize); + ReturnMessageWriter(messageWriter); + + //if (SMTD.MessageWrittenByEncoderIsEnabled() && messageData != null) + //{ + // SMTD.MessageWrittenByEncoder( + // eventTraceActivity ?? EventTraceActivityHelper.TryExtractActivity(message), + // messageData.Count, + // this); + //} + + //if (MessageLogger.LogMessagesAtTransportLevel) + //{ + // XmlDictionaryReader xmlDictionaryReader = JsonReaderWriterFactory.CreateJsonReader( + // messageData.Array, messageData.Offset, messageData.Count, null, XmlDictionaryReaderQuotas.Max, null); + // MessageLogger.LogMessage(ref message, xmlDictionaryReader, MessageLoggingSource.TransportSend); + //} + + return messageData; + } + + public override ValueTask WriteMessageAsync(Message message, Stream stream) + { + if (message == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(message))); + } + + if (stream == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(stream)), message); + } + + ThrowIfMismatchedMessageVersion(message); + + //EventTraceActivity eventTraceActivity = null; + //if (WebTD.JsonMessageEncodingStartIsEnabled()) + //{ + // eventTraceActivity = EventTraceActivityHelper.TryExtractActivity(message); + // WebTD.JsonMessageEncodingStart(eventTraceActivity); + //} + + message.Properties.Encoder = this; + XmlDictionaryWriter xmlWriter = TakeStreamedWriter(stream); + + xmlWriter.WriteStartDocument(); + message.WriteMessage(xmlWriter); + xmlWriter.WriteEndDocument(); + xmlWriter.Flush(); + ReturnStreamedWriter(xmlWriter); + + //if (SMTD.StreamedMessageWrittenByEncoderIsEnabled()) + //{ + // SMTD.StreamedMessageWrittenByEncoder( + // eventTraceActivity ?? EventTraceActivityHelper.TryExtractActivity(message)); + //} + + //if (MessageLogger.LogMessagesAtTransportLevel) + //{ + // MessageLogger.LogMessage(ref message, MessageLoggingSource.TransportSend); + //} + + return new ValueTask(); + } + + internal override bool IsCharSetSupported(string charSet) => TextEncoderDefaults.TryGetEncoding(charSet, out _); + + public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType) + { + return ReadMessageAsync(stream, maxSizeOfHeaders, contentType).AsTask().GetAwaiter().GetResult(); + } + + public override void WriteMessage(Message message, Stream stream) + { + WriteMessageAsync(message, stream).AsTask().GetAwaiter().GetResult(); + } + + private bool IsJsonContentType(string contentType) => IsContentTypeSupported(contentType, JsonGlobals.ApplicationJsonMediaType, JsonGlobals.ApplicationJsonMediaType) || IsContentTypeSupported(contentType, JsonGlobals.TextJsonMediaType, JsonGlobals.TextJsonMediaType); + + private void ReturnBufferedData(JsonBufferedMessageData messageData) + { + _bufferedReaderPool.Return(messageData); + } + + private void ReturnMessageWriter(JsonBufferedMessageWriter messageWriter) + { + _bufferedWriterPool.Return(messageWriter); + } + + private void ReturnStreamedReader(XmlDictionaryReader xmlReader) + { + _streamedReaderPool.Return(xmlReader); + } + + private void ReturnStreamedWriter(XmlWriter xmlWriter) + { + xmlWriter.Close(); + _streamedWriterPool.Return((XmlDictionaryWriter)xmlWriter); + } + + private JsonBufferedMessageData TakeBufferedReader() + { + if (_bufferedReaderPool == null) + { + lock (ThisLock) + { + if (_bufferedReaderPool == null) + { + _bufferedReaderPool = new SynchronizedPool(_maxReadPoolSize); + } + } + } + + JsonBufferedMessageData messageData = _bufferedReaderPool.Take(); + if (messageData == null) + { + messageData = new JsonBufferedMessageData(this, MaxPooledXmlReadersPerMessage); + } + + return messageData; + } + + private JsonBufferedMessageWriter TakeBufferedWriter() + { + if (_bufferedWriterPool == null) + { + lock (ThisLock) + { + if (_bufferedWriterPool == null) + { + _bufferedWriterPool = new SynchronizedPool(_maxWritePoolSize); + } + } + } + + JsonBufferedMessageWriter messageWriter = _bufferedWriterPool.Take(); + if (messageWriter == null) + { + messageWriter = new JsonBufferedMessageWriter(this); + } + + return messageWriter; + } + + private XmlDictionaryReader TakeStreamedReader(Stream stream, Encoding enc) + { + if (_streamedReaderPool == null) + { + lock (ThisLock) + { + if (_streamedReaderPool == null) + { + _streamedReaderPool = new SynchronizedPool(_maxReadPoolSize); + } + } + } + + XmlDictionaryReader xmlReader = _streamedReaderPool.Take(); + if (xmlReader == null) + { + xmlReader = JsonReaderWriterFactory.CreateJsonReader(stream, enc, _readerQuotas, _onStreamedReaderClose); + } + else + { + ((IXmlJsonReaderInitializer)xmlReader).SetInput(stream, enc, _readerQuotas, _onStreamedReaderClose); + } + + return xmlReader; + } + + private XmlDictionaryWriter TakeStreamedWriter(Stream stream) + { + if (_streamedWriterPool == null) + { + lock (ThisLock) + { + if (_streamedWriterPool == null) + { + _streamedWriterPool = new SynchronizedPool(_maxWritePoolSize); + } + } + } + + XmlDictionaryWriter xmlWriter = _streamedWriterPool.Take(); + if (xmlWriter == null) + { + xmlWriter = JsonReaderWriterFactory.CreateJsonWriter(stream, _writeEncoding, false); + } + else + { + ((IXmlJsonWriterInitializer)xmlWriter).SetOutput(stream, _writeEncoding, false); + } + + return xmlWriter; + } + + internal class JsonBufferedMessageData : BufferedMessageData + { + private Encoding _encoding; + private readonly JsonMessageEncoder _messageEncoder; + private readonly OnXmlDictionaryReaderClose _onClose; + private readonly Pool _readerPool; + + public JsonBufferedMessageData(JsonMessageEncoder messageEncoder, int maxReaderPoolSize) + : base(messageEncoder.RecycledStatePool) + { + _messageEncoder = messageEncoder; + _onClose = new OnXmlDictionaryReaderClose(OnXmlReaderClosed); + _readerPool = new Pool(maxReaderPoolSize); + } + + public override MessageEncoder MessageEncoder => _messageEncoder; + + public override XmlDictionaryReaderQuotas Quotas => _messageEncoder._bufferedReadReaderQuotas; + + internal Encoding Encoding + { + set + { + _encoding = value; + } + } + + protected override void OnClosed() + { + _messageEncoder.ReturnBufferedData(this); + } + + protected override void ReturnXmlReader(XmlDictionaryReader xmlReader) + { + if (xmlReader != null) + { + _readerPool.Return(xmlReader); + } + } + + protected override XmlDictionaryReader TakeXmlReader() + { + ArraySegment buffer = Buffer; + + XmlDictionaryReader xmlReader = _readerPool.Take(); + if (xmlReader == null) + { + xmlReader = JsonReaderWriterFactory.CreateJsonReader(buffer.Array, buffer.Offset, buffer.Count, _encoding, Quotas, _onClose); + } + else + { + ((IXmlJsonReaderInitializer)xmlReader).SetInput(buffer.Array, buffer.Offset, buffer.Count, _encoding, Quotas, _onClose); + } + + return xmlReader; + } + } + + internal class JsonBufferedMessageWriter : BufferedMessageWriter + { + private readonly JsonMessageEncoder _messageEncoder; + private XmlDictionaryWriter _returnedWriter; + + public JsonBufferedMessageWriter(JsonMessageEncoder messageEncoder) + { + _messageEncoder = messageEncoder; + } + + protected override void OnWriteEndMessage(XmlDictionaryWriter writer) + { + writer.WriteEndDocument(); + } + + protected override void OnWriteStartMessage(XmlDictionaryWriter writer) + { + writer.WriteStartDocument(); + } + + protected override void ReturnXmlWriter(XmlDictionaryWriter writer) + { + writer.Close(); + + if (_returnedWriter == null) + { + _returnedWriter = writer; + } + } + + protected override XmlDictionaryWriter TakeXmlWriter(Stream stream) + { + XmlDictionaryWriter writer; + if (_returnedWriter == null) + { + writer = JsonReaderWriterFactory.CreateJsonWriter(stream, _messageEncoder._writeEncoding, false); + } + else + { + writer = _returnedWriter; + ((IXmlJsonWriterInitializer)writer).SetOutput(stream, _messageEncoder._writeEncoding, false); + _returnedWriter = null; + } + + return writer; + } + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/MessageExtensions.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/MessageExtensions.cs new file mode 100644 index 00000000000..626cc7b701f --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/MessageExtensions.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; + +namespace System.ServiceModel.Channels +{ + internal static class MessageExtensions + { + internal static Exception CreateMessageDisposedException(this Message _) + { + return new ObjectDisposedException("", SR.MessageClosed); + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebBodyFormatMessageProperty.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebBodyFormatMessageProperty.cs new file mode 100644 index 00000000000..045537e7ff6 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebBodyFormatMessageProperty.cs @@ -0,0 +1,72 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Globalization; + +namespace System.ServiceModel.Channels +{ + public sealed class WebBodyFormatMessageProperty : IMessageProperty + { + public const string Name = "WebBodyFormatMessageProperty"; + + private static WebBodyFormatMessageProperty s_jsonProperty; + private static WebBodyFormatMessageProperty s_xmlProperty; + private static WebBodyFormatMessageProperty s_rawProperty; + + public WebBodyFormatMessageProperty(WebContentFormat format) + { + if (format == WebContentFormat.Default) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.Format(SR.DefaultContentFormatNotAllowedInProperty))); + } + + Format = format; + } + + public WebContentFormat Format { get; } + + internal static WebBodyFormatMessageProperty JsonProperty + { + get + { + if (s_jsonProperty == null) + { + s_jsonProperty = new WebBodyFormatMessageProperty(WebContentFormat.Json); + } + + return s_jsonProperty; + } + } + + internal static WebBodyFormatMessageProperty XmlProperty + { + get + { + if (s_xmlProperty == null) + { + s_xmlProperty = new WebBodyFormatMessageProperty(WebContentFormat.Xml); + } + + return s_xmlProperty; + } + } + + internal static WebBodyFormatMessageProperty RawProperty + { + get + { + if (s_rawProperty == null) + { + s_rawProperty = new WebBodyFormatMessageProperty(WebContentFormat.Raw); + } + + return s_rawProperty; + } + } + + public IMessageProperty CreateCopy() => this; + + public override string ToString() => string.Format(CultureInfo.InvariantCulture, SR.Format(SR.WebBodyFormatPropertyToString, Format.ToString())); + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebContentFormat.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebContentFormat.cs new file mode 100644 index 00000000000..310cc5e04ca --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebContentFormat.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System.ServiceModel.Channels +{ + public enum WebContentFormat + { + Default, + Xml, + Json, + Raw + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebContentFormatHelper.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebContentFormatHelper.cs new file mode 100644 index 00000000000..3bf7cefe5f8 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebContentFormatHelper.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System.ServiceModel.Channels +{ + internal static class WebContentFormatHelper + { + internal static bool IsDefined(WebContentFormat format) + { + return (format == WebContentFormat.Default + || format == WebContentFormat.Xml + || format == WebContentFormat.Json + || format == WebContentFormat.Raw); + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebContentTypeMapper.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebContentTypeMapper.cs new file mode 100644 index 00000000000..16678e71c16 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebContentTypeMapper.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System.ServiceModel.Channels +{ + public abstract class WebContentTypeMapper + { + public abstract WebContentFormat GetMessageFormatForContentType(string contentType); + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebMessageEncoderFactory.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebMessageEncoderFactory.cs new file mode 100644 index 00000000000..8c4fcbd3cd3 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebMessageEncoderFactory.cs @@ -0,0 +1,435 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Globalization; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using System.Xml; +using System.Runtime; + +namespace System.ServiceModel.Channels +{ + public class WebMessageEncoderFactory : MessageEncoderFactory + { + private readonly WebMessageEncoder _messageEncoder; + + public WebMessageEncoderFactory(Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, XmlDictionaryReaderQuotas quotas, WebContentTypeMapper contentTypeMapper, bool javascriptCallbackEnabled) + { + _messageEncoder = new WebMessageEncoder(writeEncoding, maxReadPoolSize, maxWritePoolSize, quotas, contentTypeMapper, javascriptCallbackEnabled); + } + + public override MessageEncoder Encoder => _messageEncoder; + + public override MessageVersion MessageVersion => _messageEncoder.MessageVersion; + + internal static string GetContentType(string mediaType, Encoding encoding) + { + string charset = TextEncoderDefaults.EncodingToCharSet(encoding); + if (!string.IsNullOrEmpty(charset)) + { + return string.Format(CultureInfo.InvariantCulture, "{0}; charset={1}", mediaType, charset); + } + + return mediaType; + } + + internal class WebMessageEncoder : MessageEncoder + { + private const string DefaultMediaType = "application/xml"; + private readonly WebContentTypeMapper _contentTypeMapper; + private readonly string _defaultContentType; + + // Double-checked locking pattern requires volatile for read/write synchronization + private volatile MessageEncoder _jsonMessageEncoder; + private readonly int _maxReadPoolSize; + private readonly int _maxWritePoolSize; + + // _rawMessageEncoder removed: raw (octet-stream) content path is currently + // unsupported by this client port. See WebHttpRawContentNotSupported. + private readonly XmlDictionaryReaderQuotas _readerQuotas; + + // Double-checked locking pattern requires volatile for read/write synchronization + private volatile MessageEncoder _textMessageEncoder; + private readonly Encoding _writeEncoding; + //bool javascriptCallbackEnabled; + + public WebMessageEncoder(Encoding writeEncoding, int maxReadPoolSize, int maxWritePoolSize, XmlDictionaryReaderQuotas quotas, WebContentTypeMapper contentTypeMapper, bool javascriptCallbackEnabled) + { + if (writeEncoding == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(writeEncoding)); + } + + ThisLock = new object(); + + TextEncoderDefaults.ValidateEncoding(writeEncoding); + _writeEncoding = writeEncoding; + + _maxReadPoolSize = maxReadPoolSize; + _maxWritePoolSize = maxWritePoolSize; + _contentTypeMapper = contentTypeMapper; + //this.javascriptCallbackEnabled = javascriptCallbackEnabled; + + _readerQuotas = new XmlDictionaryReaderQuotas(); + quotas.CopyTo(_readerQuotas); + + _defaultContentType = GetContentType(DefaultMediaType, writeEncoding); + } + + public override string ContentType => _defaultContentType; + + public override string MediaType => DefaultMediaType; + + public override MessageVersion MessageVersion => MessageVersion.None; + + private MessageEncoder JsonMessageEncoder + { + get + { + if (_jsonMessageEncoder == null) + { + lock (ThisLock) + { + if (_jsonMessageEncoder == null) + { + _jsonMessageEncoder = new JsonMessageEncoderFactory(_writeEncoding, _maxReadPoolSize, _maxWritePoolSize, _readerQuotas, false).Encoder; + } + } + } + + return _jsonMessageEncoder; + } + } + + private MessageEncoder RawMessageEncoder + { + get + { + // ByteStreamMessageEncodingBindingElement is not yet ported to dotnet/wcf. + // Raw (Content-Type: application/octet-stream pass-through) support is deferred + // to a follow-up; the WebHttp client today rejects raw content with a clear error. + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + new NotSupportedException(SR.WebHttpRawContentNotSupported)); + } + } + + private MessageEncoder TextMessageEncoder + { + get + { + if (_textMessageEncoder == null) + { + lock (ThisLock) + { + if (_textMessageEncoder == null) + { + _textMessageEncoder = new TextMessageEncodingBindingElement(MessageVersion.None, _writeEncoding).CreateMessageEncoderFactory().Encoder; + } + } + } + + return _textMessageEncoder; + } + } + + private object ThisLock { get; } + + public override bool IsContentTypeSupported(string contentType) + { + if (contentType == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(contentType)); + } + + if (TryGetContentTypeMapping(contentType, out WebContentFormat messageFormat) && + (messageFormat != WebContentFormat.Default)) + { + return true; + } + + // Raw (application/octet-stream pass-through) support is not yet ported, so probe + // Json and Text directly to avoid materializing the raw encoder. The raw fallback + // path below short-circuits without throwing for non-raw content types. + if (JsonMessageEncoder.IsContentTypeSupported(contentType) || TextMessageEncoder.IsContentTypeSupported(contentType)) + { + return true; + } + + return IsRawContentType(contentType); + } + + private static bool IsRawContentType(string contentType) + { + // Mirrors ByteStreamMessageEncoder.IsContentTypeSupported semantics so callers + // can determine support without instantiating the (unported) raw encoder. + return !string.IsNullOrEmpty(contentType) + && contentType.StartsWith("application/octet-stream", StringComparison.OrdinalIgnoreCase); + } + + public override Message ReadMessage(ArraySegment buffer, BufferManager bufferManager, string contentType) + { + if (bufferManager == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(bufferManager))); + } + + WebContentFormat format = GetFormatForContentType(contentType); + Message message; + + switch (format) + { + case WebContentFormat.Json: + message = JsonMessageEncoder.ReadMessage(buffer, bufferManager, contentType); + message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.JsonProperty); + break; + case WebContentFormat.Xml: + message = TextMessageEncoder.ReadMessage(buffer, bufferManager, contentType); + message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.XmlProperty); + break; + case WebContentFormat.Raw: + message = RawMessageEncoder.ReadMessage(buffer, bufferManager, contentType); + message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.RawProperty); + break; + default: + throw Fx.AssertAndThrow("This should never get hit because GetFormatForContentType shouldn't return a WebContentFormat other than Json, Xml, and Raw"); + } + + return message; + } + + public override async ValueTask ReadMessageAsync(Stream stream, int maxSizeOfHeaders, string contentType) + { + if (stream == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(stream))); + } + + WebContentFormat format = GetFormatForContentType(contentType); + Message message; + switch (format) + { + case WebContentFormat.Json: + message = await JsonMessageEncoder.ReadMessageAsync(stream, maxSizeOfHeaders, contentType); + message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.JsonProperty); + break; + case WebContentFormat.Xml: + message = await TextMessageEncoder.ReadMessageAsync(stream, maxSizeOfHeaders, contentType); + message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.XmlProperty); + break; + case WebContentFormat.Raw: + message = await RawMessageEncoder.ReadMessageAsync(stream, maxSizeOfHeaders, contentType); + message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.RawProperty); + break; + default: + throw Fx.AssertAndThrow("This should never get hit because GetFormatForContentType shouldn't return a WebContentFormat other than Json, Xml, and Raw"); + } + return message; + } + + public override ArraySegment WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset) + { + if (message == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(message))); + } + + if (bufferManager == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(bufferManager)), message); + } + + if (maxMessageSize < 0) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(maxMessageSize), maxMessageSize, + SR.Format(SR.ValueMustBeNonNegative)), message); + } + + if (messageOffset < 0 || messageOffset > maxMessageSize) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(messageOffset), messageOffset, + SR.Format(SR.JsonValueMustBeInRange, 0, maxMessageSize)), message); + } + + ThrowIfMismatchedMessageVersion(message); + + WebContentFormat messageFormat = ExtractFormatFromMessage(message); + //JavascriptCallbackResponseMessageProperty javascriptResponseMessageProperty; + switch (messageFormat) + { + case WebContentFormat.Json: + return JsonMessageEncoder.WriteMessage(message, maxMessageSize, bufferManager, messageOffset); + case WebContentFormat.Xml: + //if (message.Properties.TryGetValue(JavascriptCallbackResponseMessageProperty.Name, out javascriptResponseMessageProperty) && + // javascriptResponseMessageProperty != null && + // !String.IsNullOrEmpty(javascriptResponseMessageProperty.CallbackFunctionName)) + //{ + // throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.JavascriptCallbackNotsupported), message); + //} + return TextMessageEncoder.WriteMessage(message, maxMessageSize, bufferManager, messageOffset); + case WebContentFormat.Raw: + //if (message.Properties.TryGetValue(JavascriptCallbackResponseMessageProperty.Name, out javascriptResponseMessageProperty) && + // javascriptResponseMessageProperty != null && + // !String.IsNullOrEmpty(javascriptResponseMessageProperty.CallbackFunctionName)) + //{ + // throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.JavascriptCallbackNotsupported), message); + //} + return RawMessageEncoder.WriteMessage(message, maxMessageSize, bufferManager, messageOffset); + default: + throw Fx.AssertAndThrow("This should never get hit because GetFormatForContentType shouldn't return a WebContentFormat other than Json, Xml, and Raw"); + } + } + + public override async ValueTask WriteMessageAsync(Message message, Stream stream) + { + if (message == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(message))); + } + + if (stream == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("stream"), message); + } + + ThrowIfMismatchedMessageVersion(message); + + WebContentFormat messageFormat = ExtractFormatFromMessage(message); + //JavascriptCallbackResponseMessageProperty javascriptResponseMessageProperty; + switch (messageFormat) + { + case WebContentFormat.Json: + await JsonMessageEncoder.WriteMessageAsync(message, stream); + break; + case WebContentFormat.Xml: + //if (message.Properties.TryGetValue(JavascriptCallbackResponseMessageProperty.Name, out javascriptResponseMessageProperty) && + // javascriptResponseMessageProperty != null && + // !string.IsNullOrEmpty(javascriptResponseMessageProperty.CallbackFunctionName)) + //{ + // throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.JavascriptCallbackNotsupported), message); + //} + await TextMessageEncoder.WriteMessageAsync(message, stream); + break; + case WebContentFormat.Raw: + //if (message.Properties.TryGetValue(JavascriptCallbackResponseMessageProperty.Name, out javascriptResponseMessageProperty) && + // javascriptResponseMessageProperty != null && + // !string.IsNullOrEmpty(javascriptResponseMessageProperty.CallbackFunctionName)) + //{ + // throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.JavascriptCallbackNotsupported), message); + //} + await RawMessageEncoder.WriteMessageAsync(message, stream); + break; + default: + throw Fx.AssertAndThrow("This should never get hit because GetFormatForContentType shouldn't return a WebContentFormat other than Json, Xml, and Raw"); + } + } + + internal override bool IsCharSetSupported(string charSet) => TextEncoderDefaults.TryGetEncoding(charSet, out _); + + public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType) + { + return ReadMessageAsync(stream, maxSizeOfHeaders, contentType).AsTask().GetAwaiter().GetResult(); + } + + public override void WriteMessage(Message message, Stream stream) + { + WriteMessageAsync(message, stream).AsTask().GetAwaiter().GetResult(); + } + + private WebContentFormat ExtractFormatFromMessage(Message message) + { + message.Properties.TryGetValue(WebBodyFormatMessageProperty.Name, out object messageFormatProperty); + if (messageFormatProperty == null) + { + return WebContentFormat.Xml; + } + + if ((!(messageFormatProperty is WebBodyFormatMessageProperty typedMessageFormatProperty)) || + (typedMessageFormatProperty.Format == WebContentFormat.Default)) + { + return WebContentFormat.Xml; + } + + return typedMessageFormatProperty.Format; + } + + private WebContentFormat GetFormatForContentType(string contentType) + { + if (TryGetContentTypeMapping(contentType, out WebContentFormat messageFormat) && + (messageFormat != WebContentFormat.Default)) + { + //if (DiagnosticUtility.ShouldTraceInformation) + //{ + // if (string.IsNullOrEmpty(contentType)) + // { + // contentType = ""; + // } + // TraceUtility.TraceEvent(TraceEventType.Information, + // TraceCode.RequestFormatSelectedFromContentTypeMapper, + // SR.GetString(SR.TraceCodeRequestFormatSelectedFromContentTypeMapper, messageFormat.ToString(), contentType)); + //} + return messageFormat; + } + + // Don't pass on null content types to IsContentTypeSupported methods -- they might throw. + // If null content type isn't already mapped, return the default format of Raw. + + if (contentType == null) + { + messageFormat = WebContentFormat.Raw; + } + else if (JsonMessageEncoder.IsContentTypeSupported(contentType)) + { + messageFormat = WebContentFormat.Json; + } + else if (TextMessageEncoder.IsContentTypeSupported(contentType)) + { + messageFormat = WebContentFormat.Xml; + } + else + { + messageFormat = WebContentFormat.Raw; + } + + //if (DiagnosticUtility.ShouldTraceInformation) + //{ + // TraceUtility.TraceEvent(TraceEventType.Information, + // TraceCode.RequestFormatSelectedByEncoderDefaults, + // SR.GetString(SR.TraceCodeRequestFormatSelectedByEncoderDefaults, messageFormat.ToString(), contentType)); + //} + + return messageFormat; + } + + private bool TryGetContentTypeMapping(string contentType, out WebContentFormat format) + { + if (_contentTypeMapper == null) + { + format = WebContentFormat.Default; + return false; + } + + try + { + format = _contentTypeMapper.GetMessageFormatForContentType(contentType); + if (!WebContentFormatHelper.IsDefined(format)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.Format(SR.UnknownWebEncodingFormat, contentType, format))); + } + return true; + } + catch (Exception e) + { + if (Fx.IsFatal(e)) + { + throw; + } + + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException( + SR.Format(SR.ErrorEncounteredInContentTypeMapper), e)); + } + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebMessageEncodingBindingElement.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebMessageEncodingBindingElement.cs new file mode 100644 index 00000000000..b074149b963 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Channels/WebMessageEncodingBindingElement.cs @@ -0,0 +1,185 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Text; +using System.Xml; + +namespace System.ServiceModel.Channels +{ + public sealed class WebMessageEncodingBindingElement : MessageEncodingBindingElement//, IWsdlExportExtension + { + private int _maxReadPoolSize; + private int _maxWritePoolSize; + private Encoding _writeEncoding; + + public WebMessageEncodingBindingElement() : this(TextEncoderDefaults.Encoding) + { + } + + public WebMessageEncodingBindingElement(Encoding writeEncoding) + { + if (writeEncoding == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(writeEncoding)); + } + + TextEncoderDefaults.ValidateEncoding(writeEncoding); + _maxReadPoolSize = EncoderDefaults.MaxReadPoolSize; + _maxWritePoolSize = EncoderDefaults.MaxWritePoolSize; + ReaderQuotas = new XmlDictionaryReaderQuotas(); + EncoderDefaults.ReaderQuotas.CopyTo(ReaderQuotas); + _writeEncoding = writeEncoding; + } + + private WebMessageEncodingBindingElement(WebMessageEncodingBindingElement elementToBeCloned) + : base(elementToBeCloned) + { + _maxReadPoolSize = elementToBeCloned._maxReadPoolSize; + _maxWritePoolSize = elementToBeCloned._maxWritePoolSize; + ReaderQuotas = new XmlDictionaryReaderQuotas(); + elementToBeCloned.ReaderQuotas.CopyTo(ReaderQuotas); + _writeEncoding = elementToBeCloned._writeEncoding; + ContentTypeMapper = elementToBeCloned.ContentTypeMapper; + CrossDomainScriptAccessEnabled = elementToBeCloned.CrossDomainScriptAccessEnabled; + } + + public WebContentTypeMapper ContentTypeMapper { get; set; } + + public int MaxReadPoolSize + { + get + { + return _maxReadPoolSize; + } + set + { + if (value <= 0) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value), value, + SR.Format(SR.ValueMustBePositive))); + } + + _maxReadPoolSize = value; + } + } + + public int MaxWritePoolSize + { + get + { + return _maxWritePoolSize; + } + set + { + if (value <= 0) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value), value, + SR.Format(SR.ValueMustBePositive))); + } + + _maxWritePoolSize = value; + } + } + + public override MessageVersion MessageVersion + { + get + { + return MessageVersion.None; + } + set + { + if (value == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(value)); + } + + if (value != MessageVersion.None) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(nameof(value), SR.Format(SR.JsonOnlySupportsMessageVersionNone)); + } + } + } + + public XmlDictionaryReaderQuotas ReaderQuotas { get; } + + public Encoding WriteEncoding + { + get + { + return _writeEncoding; + } + set + { + if (value == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(value)); + } + + TextEncoderDefaults.ValidateEncoding(value); + _writeEncoding = value; + } + } + + public bool CrossDomainScriptAccessEnabled + { + get; + set; + } + + public override BindingElement Clone() + { + return new WebMessageEncodingBindingElement(this); + } + + public override IChannelFactory BuildChannelFactory(BindingContext context) + { + return InternalBuildChannelFactory(context); + } + + public override bool CanBuildChannelFactory(BindingContext context) + { + return InternalCanBuildChannelFactory(context); + } + + public override MessageEncoderFactory CreateMessageEncoderFactory() + { + return new WebMessageEncoderFactory(WriteEncoding, MaxReadPoolSize, MaxWritePoolSize, ReaderQuotas, ContentTypeMapper, CrossDomainScriptAccessEnabled); + } + + public override T GetProperty(BindingContext context) + { + if (context == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(context)); + } + if (typeof(T) == typeof(XmlDictionaryReaderQuotas)) + { + return (T)(object)ReaderQuotas; + } + else + { + return base.GetProperty(context); + } + } + + //void IWsdlExportExtension.ExportContract(WsdlExporter exporter, WsdlContractConversionContext context) + //{ + //} + + //void IWsdlExportExtension.ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context) + //{ + // if (context == null) + // { + // throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("context"); + // } + + // SoapHelper.SetSoapVersion(context, exporter, this.MessageVersion.Envelope); + //} + + internal override bool CheckEncodingVersion(EnvelopeVersion version) => MessageVersion.Envelope == version; + + internal override bool IsMatch(BindingElement b) => false; + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/DataContractHelpers.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/DataContractHelpers.cs new file mode 100644 index 00000000000..88c5497c50d --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/DataContractHelpers.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace System.ServiceModel +{ + internal static class DataContractHelpers + { + private static readonly Type s_typeOfIQueryable = typeof(IQueryable); + private static readonly Type s_typeOfIQueryableGeneric = typeof(IQueryable<>); + private static readonly Type s_typeOfIEnumerable = typeof(IEnumerable); + private static readonly Type s_typeOfIEnumerableGeneric = typeof(IEnumerable<>); + + internal static Type GetSubstituteDataContractType(Type type, out bool isQueryable) + { + if (type == s_typeOfIQueryable) + { + isQueryable = true; + return s_typeOfIEnumerable; + } + + if (type.GetTypeInfo().IsGenericType && + type.GetGenericTypeDefinition() == s_typeOfIQueryableGeneric) + { + isQueryable = true; + return s_typeOfIEnumerableGeneric.MakeGenericType(type.GetGenericArguments()); + } + + isQueryable = false; + return type; + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Description/DataContractJsonSerializerOperationBehavior.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Description/DataContractJsonSerializerOperationBehavior.cs new file mode 100644 index 00000000000..f4ba8b1c787 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Description/DataContractJsonSerializerOperationBehavior.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; +using System.Xml; + +namespace System.ServiceModel.Description +{ + internal class DataContractJsonSerializerOperationBehavior : DataContractSerializerOperationBehavior + { + private readonly bool _alwaysEmitTypeInformation; + + public DataContractJsonSerializerOperationBehavior(OperationDescription description, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool alwaysEmitTypeInformation) + : base(description) + { + MaxItemsInObjectGraph = maxItemsInObjectGraph; + IgnoreExtensionDataObject = ignoreExtensionDataObject; + _alwaysEmitTypeInformation = alwaysEmitTypeInformation; + } + + public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns, IList knownTypes) + { + return new DataContractJsonSerializer(type, new DataContractJsonSerializerSettings + { + RootName = name, + KnownTypes = knownTypes, + MaxItemsInObjectGraph = MaxItemsInObjectGraph, + IgnoreExtensionDataObject = IgnoreExtensionDataObject, + EmitTypeInformation = _alwaysEmitTypeInformation ? EmitTypeInformation.Always : EmitTypeInformation.AsNeeded + }); + } + + public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name, XmlDictionaryString ns, IList knownTypes) + { + return new DataContractJsonSerializer(type, new DataContractJsonSerializerSettings + { + RootName = name.Value, + KnownTypes = knownTypes, + MaxItemsInObjectGraph = MaxItemsInObjectGraph, + IgnoreExtensionDataObject = IgnoreExtensionDataObject, + EmitTypeInformation = _alwaysEmitTypeInformation ? EmitTypeInformation.Always : EmitTypeInformation.AsNeeded + }); + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Description/WebHttpBehavior.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Description/WebHttpBehavior.cs new file mode 100644 index 00000000000..68f78f24b88 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Description/WebHttpBehavior.cs @@ -0,0 +1,1082 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Reflection; +using System.ServiceModel.Channels; +using System.Collections.Generic; +using System.ServiceModel.Dispatcher; +using System.ServiceModel.Web; + +namespace System.ServiceModel.Description +{ + public class WebHttpBehavior : IEndpointBehavior + { + internal const string GET = "GET"; + internal const string POST = "POST"; + internal const string WildcardAction = "*"; + internal const string WildcardMethod = "*"; + internal static readonly string s_defaultStreamContentType = "application/octet-stream"; + internal static readonly string s_defaultCallbackParameterName = "callback"; + private WebMessageBodyStyle _defaultBodyStyle; + private WebMessageFormat _defaultOutgoingReplyFormat; + private WebMessageFormat _defaultOutgoingRequestFormat; + private string _contractNamespace; + private readonly UnwrappedTypesXmlSerializerManager _xmlSerializerManager; + + public WebHttpBehavior() + : this(null) + { + } + + public WebHttpBehavior(IServiceProvider serviceProvider) + { + _defaultOutgoingRequestFormat = WebMessageFormat.Xml; + _defaultOutgoingReplyFormat = WebMessageFormat.Xml; + _defaultBodyStyle = WebMessageBodyStyle.Bare; + _xmlSerializerManager = new UnwrappedTypesXmlSerializerManager(); + + ServiceProvider = serviceProvider; + } + + internal IServiceProvider ServiceProvider { get; } + + internal delegate void Effect(); + + public virtual WebMessageBodyStyle DefaultBodyStyle + { + get { return _defaultBodyStyle; } + set + { + if (!WebMessageBodyStyleHelper.IsDefined(value)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value))); + } + + _defaultBodyStyle = value; + } + } + + public virtual WebMessageFormat DefaultOutgoingRequestFormat + { + get + { + return _defaultOutgoingRequestFormat; + } + set + { + if (!WebMessageFormatHelper.IsDefined(value)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value))); + } + + _defaultOutgoingRequestFormat = value; + } + } + + public virtual WebMessageFormat DefaultOutgoingResponseFormat + { + get + { + return _defaultOutgoingReplyFormat; + } + set + { + if (!WebMessageFormatHelper.IsDefined(value)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value))); + } + + _defaultOutgoingReplyFormat = value; + } + } + + public virtual bool HelpEnabled { get; set; } + + public virtual bool AutomaticFormatSelectionEnabled { get; set; } + + public virtual bool FaultExceptionEnabled { get; set; } + + internal Uri HelpUri { get; set; } + + public virtual void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) + { + // do nothing + } + + public virtual void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) + { + if (endpoint == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(endpoint)); + } + + if (clientRuntime == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(clientRuntime)); + } + + WebMessageEncodingBindingElement webEncodingBindingElement = endpoint.Binding.CreateBindingElements().Find(); + if (webEncodingBindingElement != null && webEncodingBindingElement.CrossDomainScriptAccessEnabled) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.CrossDomainJavascriptNotsupported)); + } + + _contractNamespace = endpoint.Contract.Namespace; + + foreach (OperationDescription od in endpoint.Contract.Operations) + { + if (clientRuntime.Operations.Contains(od.Name)) + { + ClientOperation cop = clientRuntime.Operations[od.Name]; + IClientMessageFormatter requestClient = GetRequestClientFormatter(od, endpoint); + IClientMessageFormatter replyClient = GetReplyClientFormatter(od, endpoint); + cop.Formatter = new CompositeClientFormatter(requestClient, replyClient); + cop.SerializeRequest = true; + cop.DeserializeReply = od.Messages.Count > 1 && !IsUntypedMessage(od.Messages[1]); + } + } + AddClientErrorInspector(endpoint, clientRuntime); + } + + public virtual void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) + { + // dotnet/wcf is a client-only library. The dispatch-side wiring (UriTemplateDispatchFormatter, + // WebHttpDispatchOperationSelector, WebErrorHandler, FormatSelectingMessageInspector, + // HelpPage, HttpUnhandledOperationInvoker, MultiplexingDispatchMessageFormatter, + // CompositeDispatchFormatter, WebFaultFormatter, PrefixEndpointAddressMessageFilter, + // MatchAllMessageFilter, WebHttpServiceModelCompat) is not part of this port. Use + // CoreWCF.WebHttp on the server side. + if (endpoint == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(endpoint)); + } + + if (endpointDispatcher == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(endpointDispatcher)); + } + + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + new NotSupportedException(SR.WebHttpServerSideOperationSelectorNotSupported)); + } + + public virtual void Validate(ServiceEndpoint endpoint) + { + if (endpoint == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(endpoint)); + } + + ValidateNoMessageHeadersPresent(endpoint); + ValidateBinding(endpoint); + ValidateContract(endpoint); + } + + private void ValidateNoMessageHeadersPresent(ServiceEndpoint endpoint) + { + if (endpoint == null || endpoint.Address == null) + { + return; + } + + EndpointAddress address = endpoint.Address; + if (address.Headers.Count > 0) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.WebHttpServiceEndpointCannotHaveMessageHeaders, address))); + } + } + + protected virtual void ValidateBinding(ServiceEndpoint endpoint) + { + ValidateIsWebHttpBinding(endpoint, GetType().ToString()); + } + + internal static string GetWebMethod(OperationDescription od) + { + WebGetAttribute wga = ((KeyedByTypeCollection)od.OperationBehaviors).Find(); + WebInvokeAttribute wia = ((KeyedByTypeCollection)od.OperationBehaviors).Find(); + EnsureOk(wga, wia, od); + if (wga != null) + { + return GET; + } + else if (wia != null) + { + return wia.Method ?? POST; + } + else + { + return POST; + } + } + + internal static string GetWebUriTemplate(OperationDescription od) + { + // return exactly what is on the attribute + WebGetAttribute wga = ((KeyedByTypeCollection)od.OperationBehaviors).Find(); + WebInvokeAttribute wia = ((KeyedByTypeCollection)od.OperationBehaviors).Find(); + EnsureOk(wga, wia, od); + if (wga != null) + { + return wga.UriTemplate; + } + else if (wia != null) + { + return wia.UriTemplate; + } + else + { + return null; + } + } + + internal static string GetDescription(OperationDescription od) + { + object[] attributes = null; + if (od.SyncMethod != null) + { + attributes = od.SyncMethod.GetCustomAttributes(typeof(DescriptionAttribute), true); + } + else if (od.BeginMethod != null) + { + attributes = od.BeginMethod.GetCustomAttributes(typeof(DescriptionAttribute), true); + } + else if (od.TaskMethod != null) + { + attributes = od.TaskMethod.GetCustomAttributes(typeof(DescriptionAttribute), true); + } + + if (attributes != null && attributes.Length > 0) + { + return ((DescriptionAttribute)attributes[0]).Description; + } + else + { + return string.Empty; + } + } + + internal static bool IsTypedMessage(MessageDescription message) => message != null && message.MessageType != null; + + internal static bool IsUntypedMessage(MessageDescription message) + { + if (message == null) + { + return false; + } + + return (message.Body.ReturnValue != null && message.Body.Parts.Count == 0 && message.Body.ReturnValue.Type == typeof(Message)) || + (message.Body.ReturnValue == null && message.Body.Parts.Count == 1 && message.Body.Parts[0].Type == typeof(Message)); + } + + internal static MessageDescription MakeDummyMessageDescription(MessageDirection direction) + { + MessageDescription messageDescription = new MessageDescription("urn:dummyAction", direction); + return messageDescription; + } + + internal static bool SupportsJsonFormat(OperationDescription od) + { + // if the type is XmlSerializable, then we cannot create a json serializer for it + DataContractSerializerOperationBehavior dcsob = ((KeyedByTypeCollection)od.OperationBehaviors).Find(); + return (dcsob != null); + } + + internal static void ValidateIsWebHttpBinding(ServiceEndpoint serviceEndpoint, string behaviorName) + { + Binding binding = serviceEndpoint.Binding; + if (binding.Scheme != "http" && binding.Scheme != "https") + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.WCFBindingCannotBeUsedWithUriOperationSelectorBehaviorBadScheme, + serviceEndpoint.Contract.Name, behaviorName))); + } + + if (binding.MessageVersion != MessageVersion.None) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.WCFBindingCannotBeUsedWithUriOperationSelectorBehaviorBadMessageVersion, + serviceEndpoint.Address.Uri.AbsoluteUri, behaviorName))); + } + + TransportBindingElement transportBindingElement = binding.CreateBindingElements().Find(); + if (transportBindingElement != null && !transportBindingElement.ManualAddressing) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.ManualAddressingCannotBeFalseWithTransportBindingElement, + serviceEndpoint.Address.Uri.AbsoluteUri, behaviorName, transportBindingElement.GetType().Name))); + } + } + + internal WebMessageBodyStyle GetBodyStyle(OperationDescription od) + { + WebGetAttribute wga = ((KeyedByTypeCollection)od.OperationBehaviors).Find(); + WebInvokeAttribute wia = ((KeyedByTypeCollection)od.OperationBehaviors).Find(); + EnsureOk(wga, wia, od); + if (wga != null) + { + return wga.GetBodyStyleOrDefault(DefaultBodyStyle); + } + else if (wia != null) + { + return wia.GetBodyStyleOrDefault(DefaultBodyStyle); + } + else + { + return DefaultBodyStyle; + } + } + + protected virtual void AddServerErrorHandlers(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) + { + // Server-side only. WebErrorHandler is not ported (use CoreWCF.WebHttp on the server). + } + + // GetOperationSelector removed - server-side only (WebHttpDispatchOperationSelector is not ported). + + protected virtual QueryStringConverter GetQueryStringConverter(OperationDescription operationDescription) => new QueryStringConverter(); + + internal virtual bool UseBareReplyFormatter(WebMessageBodyStyle style, OperationDescription operationDescription, WebMessageFormat responseFormat, out Type parameterType) + { + parameterType = null; + + return IsBareResponse(style) && TryGetNonMessageParameterType(operationDescription.Messages[1], operationDescription, false, out parameterType); + } + + internal virtual IDispatchMessageFormatter GetReplyDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint) + { + // Server-side only. The original implementation builds a MultiplexingDispatchMessageFormatter + // composed of dispatch-side helpers that are not ported (ContentTypeSettingDispatchMessageFormatter, + // MultiplexingDispatchMessageFormatter, MessagePassthroughFormatter). + return null; + } + + // ---- Client-side formatters (ported from .NET Framework System.ServiceModel.Web reference source) ---- + + protected virtual IClientMessageFormatter GetReplyClientFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint) + { + if (operationDescription.Messages.Count < 2) + { + return null; + } + ValidateBodyParameters(operationDescription, false); + Type type; + if (TryGetStreamParameterType(operationDescription.Messages[1], operationDescription, false, out type)) + { + return new HttpStreamFormatter(operationDescription); + } + if (IsUntypedMessage(operationDescription.Messages[1])) + { + return new MessagePassthroughFormatter(); + } + WebMessageBodyStyle style = GetBodyStyle(operationDescription); + Type parameterType; + WebMessageFormat responseFormat = GetResponseFormat(operationDescription); + if (UseBareReplyFormatter(style, operationDescription, responseFormat, out parameterType)) + { + return SingleBodyParameterMessageFormatter.CreateXmlAndJsonClientFormatter(operationDescription, parameterType, false, _xmlSerializerManager, responseFormat == WebMessageFormat.Json); + } + else + { + MessageDescription temp = operationDescription.Messages[0]; + operationDescription.Messages[0] = MakeDummyMessageDescription(MessageDirection.Input); + IClientMessageFormatter result = GetDefaultXmlAndJsonClientFormatter(operationDescription, !IsBareResponse(style)); + operationDescription.Messages[0] = temp; + return result; + } + } + + protected virtual IClientMessageFormatter GetRequestClientFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint) + { + WebMessageFormat requestFormat = GetRequestFormat(operationDescription); + bool useJson = (requestFormat == WebMessageFormat.Json); + WebMessageEncodingBindingElement webEncoding = useJson + ? endpoint.Binding.CreateBindingElements().Find() + : null; + IClientMessageFormatter innerFormatter = null; + + if (endpoint.Address == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.EndpointAddressCannotBeNull))); + } + + // Throw-away formatter just to get path/query mapping counts before the message description is mutated below. + UriTemplateClientFormatter throwAway = new UriTemplateClientFormatter(operationDescription, null, GetQueryStringConverter(operationDescription), endpoint.Address.Uri, false, endpoint.Contract.Name); + int numUriVariables = throwAway.pathMapping.Count + throwAway.queryMapping.Count; + bool isStream = false; + + HideReplyMessage(operationDescription, delegate () + { + WebMessageBodyStyle style = GetBodyStyle(operationDescription); + bool isUntypedWhenUriParamsNotConsidered = false; + Effect doBodyFormatter = delegate () + { + if (numUriVariables != 0) + { + EnsureNotUntypedMessageNorMessageContract(operationDescription); + } + ValidateBodyParameters(operationDescription, true); + IClientMessageFormatter baseFormatter; + Type parameterType; + if (TryGetStreamParameterType(operationDescription.Messages[0], operationDescription, true, out parameterType)) + { + isStream = true; + baseFormatter = new HttpStreamFormatter(operationDescription); + } + else if (UseBareRequestFormatter(style, operationDescription, out parameterType)) + { + baseFormatter = SingleBodyParameterMessageFormatter.CreateClientFormatter(operationDescription, parameterType, true, useJson, _xmlSerializerManager); + } + else + { + baseFormatter = GetDefaultClientFormatter(operationDescription, useJson, !IsBareRequest(style)); + } + innerFormatter = baseFormatter; + isUntypedWhenUriParamsNotConsidered = IsUntypedMessage(operationDescription.Messages[0]); + }; + + if (numUriVariables == 0) + { + if (IsUntypedMessage(operationDescription.Messages[0])) + { + ValidateBodyParameters(operationDescription, true); + innerFormatter = new MessagePassthroughFormatter(); + isUntypedWhenUriParamsNotConsidered = true; + } + else if (IsTypedMessage(operationDescription.Messages[0])) + { + ValidateBodyParameters(operationDescription, true); + innerFormatter = GetDefaultClientFormatter(operationDescription, useJson, !IsBareRequest(style)); + } + else + { + doBodyFormatter(); + } + } + else + { + HideRequestUriTemplateParameters(operationDescription, throwAway.pathMapping, throwAway.queryMapping, delegate () + { + CloneMessageDescriptionsBeforeActing(operationDescription, delegate () + { + doBodyFormatter(); + }); + }); + } + innerFormatter = new UriTemplateClientFormatter(operationDescription, innerFormatter, GetQueryStringConverter(operationDescription), endpoint.Address.Uri, isUntypedWhenUriParamsNotConsidered, endpoint.Contract.Name); + }); + + string defaultContentType = GetDefaultContentType(isStream, useJson, webEncoding); + if (!string.IsNullOrEmpty(defaultContentType)) + { + innerFormatter = new ContentTypeSettingClientMessageFormatter(defaultContentType, innerFormatter); + } + return innerFormatter; + } + + internal IClientMessageFormatter GetDefaultClientFormatter(OperationDescription od, bool useJson, bool isWrapped) + { + DataContractSerializerOperationBehavior dcsob = ((KeyedByTypeCollection)od.OperationBehaviors).Find(); + if (useJson) + { + if (dcsob == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.JsonFormatRequiresDataContract, od.Name, od.DeclaringContract.Name, od.DeclaringContract.Namespace))); + } + return CreateDataContractJsonSerializerOperationFormatter(od, dcsob, isWrapped); + } + else + { + ClientRuntime clientRuntime = new ClientRuntime("name", ""); + ClientOperation cop = new ClientOperation(clientRuntime, "dummyClient", "urn:dummy"); + cop.Formatter = null; + + if (dcsob != null) + { + (dcsob as IOperationBehavior).ApplyClientBehavior(od, cop); + return cop.Formatter; + } + XmlSerializerOperationBehavior xsob = ((KeyedByTypeCollection)od.OperationBehaviors).Find(); + if (xsob != null) + { + xsob = new XmlSerializerOperationBehavior(od, xsob.XmlSerializerFormatAttribute); + (xsob as IOperationBehavior).ApplyClientBehavior(od, cop); + return cop.Formatter; + } + } + return null; + } + + private IClientMessageFormatter GetDefaultXmlAndJsonClientFormatter(OperationDescription od, bool isWrapped) + { + IClientMessageFormatter xmlFormatter = GetDefaultClientFormatter(od, false, isWrapped); + if (!SupportsJsonFormat(od)) + { + return xmlFormatter; + } + // The .NET Framework version wraps both formatters in a DemultiplexingClientMessageFormatter + // that switches on the response Content-Type. The client-only port returns the XML formatter + // directly; the caller's [WebGet]/[WebInvoke] ResponseFormat selects between Xml and Json + // formats deterministically at description time. + return xmlFormatter; + } + + protected virtual void AddClientErrorInspector(ServiceEndpoint endpoint, ClientRuntime clientRuntime) + { + if (!FaultExceptionEnabled) + { + clientRuntime.ClientMessageInspectors.Add(new WebFaultClientMessageInspector()); + } + } + + private string GetDefaultContentType(bool isStream, bool useJson, WebMessageEncodingBindingElement webEncoding) + { + if (isStream) + { + return s_defaultStreamContentType; + } + else if (useJson) + { + return JsonMessageEncoderFactory.GetContentType(webEncoding); + } + else + { + return null; + } + } + + internal virtual IDispatchMessageFormatter GetRequestDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint) + { + // Server-side only. The original implementation builds a UriTemplateDispatchFormatter + // composed with body formatters, then wraps the result in another UriTemplateDispatchFormatter. + // UriTemplateDispatchFormatter is not ported (server-side dispatch). + return null; + } + + private static void CloneMessageDescriptionsBeforeActing(OperationDescription operationDescription, Effect effect) + { + MessageDescription originalRequest = operationDescription.Messages[0]; + bool thereIsAReply = operationDescription.Messages.Count > 1; + MessageDescription originalReply = thereIsAReply ? operationDescription.Messages[1] : null; + operationDescription.Messages[0] = originalRequest.Clone(); + if (thereIsAReply) + { + operationDescription.Messages[1] = originalReply.Clone(); + } + + effect(); + operationDescription.Messages[0] = originalRequest; + if (thereIsAReply) + { + operationDescription.Messages[1] = originalReply; + } + } + + internal virtual bool UseBareRequestFormatter(WebMessageBodyStyle style, OperationDescription operationDescription, out Type parameterType) + { + parameterType = null; + + return IsBareRequest(style) && TryGetNonMessageParameterType(operationDescription.Messages[0], operationDescription, true, out parameterType); + } + + private static Collection CloneParts(MessageDescription md) + { + MessagePartDescriptionCollection bodyParameters = md.Body.Parts; + Collection bodyParametersClone = new Collection(); + for (int i = 0; i < bodyParameters.Count; ++i) + { + MessagePartDescription copy = bodyParameters[i].Clone(); + bodyParametersClone.Add(copy); + } + + return bodyParametersClone; + } + + private static void EnsureNotUntypedMessageNorMessageContract(OperationDescription operationDescription) + { + // Called when there are UriTemplate parameters. UT does not compose with Message + // or MessageContract because the SOAP and REST programming models must be uniform here. + bool isUnadornedWebGet = false; + if (GetWebMethod(operationDescription) == GET && GetWebUriTemplate(operationDescription) == null) + { + isUnadornedWebGet = true; + } + + if (IsTypedMessage(operationDescription.Messages[0])) + { + if (isUnadornedWebGet) + { + // WebGet will give you UriTemplate parameters by default. + // We need a special error message for this case to prevent confusion. + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.GETCannotHaveMCParameter, operationDescription.Name, operationDescription.DeclaringContract.Name, operationDescription.Messages[0].MessageType.Name))); + } + else + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format( + SR.UTParamsDoNotComposeWithMessageContract, operationDescription.Name, operationDescription.DeclaringContract.Name))); + } + } + + if (IsUntypedMessage(operationDescription.Messages[0])) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format( + SR.UTParamsDoNotComposeWithMessage, operationDescription.Name, operationDescription.DeclaringContract.Name))); + } + } + + private static void EnsureOk(WebGetAttribute wga, WebInvokeAttribute wia, OperationDescription od) + { + if (wga != null && wia != null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.MultipleWebAttributes, od.Name, od.DeclaringContract.Name))); + } + } + + private static void HideReplyMessage(OperationDescription operationDescription, Effect effect) + { + MessageDescription temp = null; + if (operationDescription.Messages.Count > 1) + { + temp = operationDescription.Messages[1]; + operationDescription.Messages[1] = MakeDummyMessageDescription(MessageDirection.Output); + } + + effect(); + if (operationDescription.Messages.Count > 1) + { + operationDescription.Messages[1] = temp; + } + } + + // HideRequestUriTemplateParameters(OperationDescription, UriTemplateDispatchFormatter, Effect) + // removed - server-side only (UriTemplateDispatchFormatter is not ported). + + private static void HideRequestUriTemplateParameters(OperationDescription operationDescription, Dictionary pathMapping, Dictionary> queryMapping, Effect effect) + { + // mutate description to hide UriTemplate parameters + Collection originalParts = CloneParts(operationDescription.Messages[0]); + Collection parts = CloneParts(operationDescription.Messages[0]); + operationDescription.Messages[0].Body.Parts.Clear(); + int newIndex = 0; + for (int i = 0; i < parts.Count; ++i) + { + if (!pathMapping.ContainsKey(i) && !queryMapping.ContainsKey(i)) + { + operationDescription.Messages[0].Body.Parts.Add(parts[i]); + parts[i].Index = newIndex++; + } + } + + effect(); + // unmutate description + operationDescription.Messages[0].Body.Parts.Clear(); + for (int i = 0; i < originalParts.Count; ++i) + { + operationDescription.Messages[0].Body.Parts.Add(originalParts[i]); + } + } + + private static bool IsBareRequest(WebMessageBodyStyle style) => style == WebMessageBodyStyle.Bare || style == WebMessageBodyStyle.WrappedResponse; + + private static bool IsBareResponse(WebMessageBodyStyle style) => style == WebMessageBodyStyle.Bare || style == WebMessageBodyStyle.WrappedRequest; + + internal static bool TryGetNonMessageParameterType(MessageDescription message, OperationDescription declaringOperation, bool isRequest, out Type type) + { + type = null; + if (message == null) + { + return true; + } + + if (IsTypedMessage(message) || IsUntypedMessage(message)) + { + return false; + } + + if (isRequest) + { + if (message.Body.Parts.Count > 1) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.AtMostOneRequestBodyParameterAllowedForUnwrappedMessages, declaringOperation.Name, declaringOperation.DeclaringContract.Name))); + } + + if (message.Body.Parts.Count == 1 && message.Body.Parts[0].Type != typeof(void)) + { + type = message.Body.Parts[0].Type; + } + + return true; + } + else + { + if (message.Body.Parts.Count > 0) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.OnlyReturnValueBodyParameterAllowedForUnwrappedMessages, declaringOperation.Name, declaringOperation.DeclaringContract.Name))); + } + + if (message.Body.ReturnValue != null && message.Body.ReturnValue.Type != typeof(void)) + { + type = message.Body.ReturnValue.Type; + } + + return true; + } + } + + private static bool TryGetStreamParameterType(MessageDescription message, OperationDescription declaringOperation, bool isRequest, out Type type) + { + type = null; + if (message == null || IsTypedMessage(message) || IsUntypedMessage(message)) + { + return false; + } + + if (isRequest) + { + bool hasStream = false; + for (int i = 0; i < message.Body.Parts.Count; ++i) + { + if (typeof(Stream) == message.Body.Parts[i].Type) + { + type = message.Body.Parts[i].Type; + hasStream = true; + break; + } + + } + + if (hasStream && message.Body.Parts.Count > 1) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.Format(SR.AtMostOneRequestBodyParameterAllowedForStream, declaringOperation.Name, declaringOperation.DeclaringContract.Name))); + } + + return hasStream; + } + else + { + // validate that the stream is not an out or ref param + for (int i = 0; i < message.Body.Parts.Count; ++i) + { + if (typeof(Stream) == message.Body.Parts[i].Type) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.Format(SR.NoOutOrRefStreamParametersAllowed, message.Body.Parts[i].Name, declaringOperation.Name, declaringOperation.DeclaringContract.Name))); + } + } + + if (message.Body.ReturnValue != null && typeof(Stream) == message.Body.ReturnValue.Type) + { + // validate that there are no out or ref params + if (message.Body.Parts.Count > 0) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.Format(SR.NoOutOrRefParametersAllowedWithStreamResult, declaringOperation.Name, declaringOperation.DeclaringContract.Name))); + } + type = message.Body.ReturnValue.Type; + return true; + } + + else + { + return false; + } + } + } + + private static void ValidateAtMostOneStreamParameter(OperationDescription operation, bool request) + { + Type dummy; + if (request) + { + TryGetStreamParameterType(operation.Messages[0], operation, true, out dummy); + } + else + { + if (operation.Messages.Count > 1) + { + TryGetStreamParameterType(operation.Messages[1], operation, false, out dummy); + } + } + } + + private IDispatchMessageFormatter GetDefaultDispatchFormatter(OperationDescription od, bool useJson, bool isWrapped) + { + // Server-side only. Used by the stubbed GetReplyDispatchFormatter / GetRequestDispatchFormatter. + // The original constructs a dummy EndpointDispatcher (server-only 3-arg constructor) + // and invokes IOperationBehavior.ApplyDispatchBehavior to harvest the formatter - + // none of which is wired in the client-only port. + return null; + } + + internal virtual DataContractJsonSerializerOperationFormatter CreateDataContractJsonSerializerOperationFormatter(OperationDescription od, DataContractSerializerOperationBehavior dcsob, bool isWrapped) + { + //return new DataContractJsonSerializerOperationFormatter(od, dcsob.MaxItemsInObjectGraph, dcsob.IgnoreExtensionDataObject, isWrapped, false, JavascriptCallbackParameterName); + + OperationDescription clonedOperation = new OperationDescription(od.Name, od.DeclaringContract); + foreach (MessageDescription message in od.Messages) + { + MessageDescription clonedMessage = message.Clone(); + if (IsValidReturnValue(clonedMessage.Body.ReturnValue)) + { + if (clonedMessage.Body.Parts.Count == 0) + { + if (clonedMessage.Body.ReturnValue.Type == typeof(Stream)) + { + clonedMessage.Body.WrapperName = JsonGlobals.RootString; + clonedMessage.Body.WrapperNamespace = string.Empty; + } + } + } + else + { + if (clonedMessage.Body.Parts.Count == 1) + { + if (clonedMessage.Body.Parts[0].Type == typeof(Stream)) + { + clonedMessage.Body.WrapperName = JsonGlobals.RootString; + clonedMessage.Body.WrapperNamespace = string.Empty; + } + } + } + + clonedOperation.Messages.Add(clonedMessage); + } + + return new DataContractJsonSerializerOperationFormatter(clonedOperation, dcsob.MaxItemsInObjectGraph, dcsob.IgnoreExtensionDataObject, isWrapped, false, null); + } + + private static MessagePartDescription GetStreamPart(MessageDescription messageDescription) + { + if (IsValidReturnValue(messageDescription.Body.ReturnValue)) + { + if (messageDescription.Body.Parts.Count == 0) + { + if (messageDescription.Body.ReturnValue.Type == typeof(Stream)) + { + return messageDescription.Body.ReturnValue; + } + } + } + else + { + if (messageDescription.Body.Parts.Count == 1) + { + if (messageDescription.Body.Parts[0].Type == typeof(Stream)) + { + return messageDescription.Body.Parts[0]; + } + } + } + + return null; + } + + private static bool IsValidReturnValue(MessagePartDescription returnValue) => (returnValue != null) && (returnValue.Type != typeof(void)); + + // TODO: Can I remove this? + //IClientMessageFormatter GetDefaultXmlAndJsonClientFormatter(OperationDescription od, bool isWrapped) + //{ + // IClientMessageFormatter xmlFormatter = GetDefaultClientFormatter(od, false, isWrapped); + // if (!SupportsJsonFormat(od)) + // { + // return xmlFormatter; + // } + // IClientMessageFormatter jsonFormatter = GetDefaultClientFormatter(od, true, isWrapped); + // Dictionary map = new Dictionary(); + // map.Add(WebContentFormat.Xml, xmlFormatter); + // map.Add(WebContentFormat.Json, jsonFormatter); + // // In case there is no format property, the default formatter to use is XML + // return new DemultiplexingClientMessageFormatter(map, xmlFormatter); + //} + + private IDispatchMessageFormatter GetDefaultXmlAndJsonDispatchFormatter(OperationDescription od, bool isWrapped) + { + // Server-side only. Returns a DemultiplexingDispatchMessageFormatter which is not ported. + return null; + } + + internal WebMessageFormat GetRequestFormat(OperationDescription od) + { + WebGetAttribute wga = ((KeyedByTypeCollection)od.OperationBehaviors).Find(); + WebInvokeAttribute wia = ((KeyedByTypeCollection)od.OperationBehaviors).Find(); + EnsureOk(wga, wia, od); + if (wga != null) + { + return wga.IsRequestFormatSetExplicitly ? wga.RequestFormat : this.DefaultOutgoingRequestFormat; + } + else if (wia != null) + { + return wia.IsRequestFormatSetExplicitly ? wia.RequestFormat : this.DefaultOutgoingRequestFormat; + } + else + { + return DefaultOutgoingRequestFormat; + } + } + + internal WebMessageFormat GetResponseFormat(OperationDescription od) + { + WebGetAttribute wga = ((KeyedByTypeCollection)od.OperationBehaviors).Find(); + WebInvokeAttribute wia = ((KeyedByTypeCollection)od.OperationBehaviors).Find(); + EnsureOk(wga, wia, od); + if (wga != null) + { + return wga.IsResponseFormatSetExplicitly ? wga.ResponseFormat : this.DefaultOutgoingResponseFormat; + } + else if (wia != null) + { + return wia.IsResponseFormatSetExplicitly ? wia.ResponseFormat : this.DefaultOutgoingResponseFormat; + } + else + { + return DefaultOutgoingResponseFormat; + } + } + + private void ValidateBodyParameters(OperationDescription operation, bool request) + { + string method = GetWebMethod(operation); + if (request) + { + ValidateGETHasNoBody(operation, method); + } + + // validate that if bare is chosen for request/response, then at most 1 parameter is possible + ValidateBodyStyle(operation, request); + // validate if the request or response body is a stream, no other body parameters + // can be specified + ValidateAtMostOneStreamParameter(operation, request); + } + + private void ValidateBodyStyle(OperationDescription operation, bool request) + { + WebMessageBodyStyle style = GetBodyStyle(operation); + Type dummy; + if (request && IsBareRequest(style)) + { + TryGetNonMessageParameterType(operation.Messages[0], operation, true, out dummy); + } + + if (!request && operation.Messages.Count > 1 && IsBareResponse(style)) + { + TryGetNonMessageParameterType(operation.Messages[1], operation, false, out dummy); + } + } + + private void ValidateGETHasNoBody(OperationDescription operation, string method) + { + if (method == GET) + { + if (!IsUntypedMessage(operation.Messages[0]) && operation.Messages[0].Body.Parts.Count != 0) + { + if (!IsTypedMessage(operation.Messages[0])) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.GETCannotHaveBody, operation.Name, operation.DeclaringContract.Name, operation.Messages[0].Body.Parts[0].Name))); + } + else + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.GETCannotHaveMCParameter, operation.Name, operation.DeclaringContract.Name, operation.Messages[0].MessageType.Name))); + } + } + } + } + + private void ValidateContract(ServiceEndpoint endpoint) + { + foreach (OperationDescription od in endpoint.Contract.Operations) + { + ValidateNoOperationHasEncodedXmlSerializer(od); + ValidateNoMessageContractHeaders(od.Messages[0], od.Name, endpoint.Contract.Name); + ValidateNoBareMessageContractWithMultipleParts(od.Messages[0], od.Name, endpoint.Contract.Name); + ValidateNoMessageContractWithStream(od.Messages[0], od.Name, endpoint.Contract.Name); + if (od.Messages.Count > 1) + { + ValidateNoMessageContractHeaders(od.Messages[1], od.Name, endpoint.Contract.Name); + ValidateNoBareMessageContractWithMultipleParts(od.Messages[1], od.Name, endpoint.Contract.Name); + ValidateNoMessageContractWithStream(od.Messages[1], od.Name, endpoint.Contract.Name); + } + } + } + + internal static bool IsXmlSerializerFaultFormat(OperationDescription operationDescription) + { + XmlSerializerOperationBehavior xsob = ((KeyedByTypeCollection)operationDescription.OperationBehaviors).Find(); + + return (xsob != null && xsob.XmlSerializerFormatAttribute.SupportFaults); + } + + private void ValidateNoMessageContractWithStream(MessageDescription md, string opName, string contractName) + { + if (IsTypedMessage(md)) + { + foreach (MessagePartDescription description in md.Body.Parts) + { + if (description.Type == typeof(Stream)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + new InvalidOperationException(SR.Format(SR.StreamBodyMemberNotSupported, GetType().ToString(), contractName, opName, md.MessageType.ToString(), description.Name))); + } + } + } + } + + private void ValidateNoOperationHasEncodedXmlSerializer(OperationDescription od) + { + XmlSerializerOperationBehavior xsob = ((KeyedByTypeCollection)od.OperationBehaviors).Find(); + if (xsob != null && (xsob.XmlSerializerFormatAttribute.Style == OperationFormatStyle.Rpc || xsob.XmlSerializerFormatAttribute.Use == OperationFormatUse.Encoded)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.RpcEncodedNotSupportedForNoneMessageVersion, od.Name, od.DeclaringContract.Name, od.DeclaringContract.Namespace))); + } + } + + private void ValidateNoBareMessageContractWithMultipleParts(MessageDescription md, string opName, string contractName) + { + if (IsTypedMessage(md) && md.Body.WrapperName == null) + { + if (md.Body.Parts.Count > 1) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.InvalidMessageContractWithoutWrapperName, opName, contractName, md.MessageType))); + } + + if (md.Body.Parts.Count == 1 && md.Body.Parts[0].Multiple) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.MCAtMostOneRequestBodyParameterAllowedForUnwrappedMessages, opName, contractName, md.MessageType))); + } + } + } + + private void ValidateNoMessageContractHeaders(MessageDescription md, string opName, string contractName) + { + if (md.Headers.Count != 0) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.InvalidMethodWithSOAPHeaders, opName, contractName))); + } + } + + internal class MessagePassthroughFormatter : IClientMessageFormatter, IDispatchMessageFormatter + { + public object DeserializeReply(Message message, object[] parameters) => message; + + public void DeserializeRequest(Message message, object[] parameters) + { + parameters[0] = message; + } + + public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result) => result as Message; + + public Message SerializeRequest(MessageVersion messageVersion, object[] parameters) => parameters[0] as Message; + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/CompositeClientFormatter.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/CompositeClientFormatter.cs new file mode 100644 index 00000000000..0d8ca358c97 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/CompositeClientFormatter.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.ServiceModel.Dispatcher +{ + using System.ServiceModel.Channels; + + internal class CompositeClientFormatter : IClientMessageFormatter + { + IClientMessageFormatter reply; + IClientMessageFormatter request; + + public CompositeClientFormatter(IClientMessageFormatter request, IClientMessageFormatter reply) + { + this.request = request; + this.reply = reply; + } + + public object DeserializeReply(Message message, object[] parameters) + { + return this.reply.DeserializeReply(message, parameters); + } + + public Message SerializeRequest(MessageVersion messageVersion, object[] parameters) + { + return this.request.SerializeRequest(messageVersion, parameters); + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/ContentTypeSettingClientMessageFormatter.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/ContentTypeSettingClientMessageFormatter.cs new file mode 100644 index 00000000000..d809f40c33f --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/ContentTypeSettingClientMessageFormatter.cs @@ -0,0 +1,78 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.ServiceModel.Dispatcher +{ + using System.Net; + using System.ServiceModel.Channels; + using System.ServiceModel.Web; + + internal class ContentTypeSettingClientMessageFormatter : IClientMessageFormatter + { + IClientMessageFormatter innerFormatter; + string outgoingContentType; + + public ContentTypeSettingClientMessageFormatter(string outgoingContentType, IClientMessageFormatter innerFormatter) + { + if (outgoingContentType == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(outgoingContentType)); + } + if (innerFormatter == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(innerFormatter)); + } + this.outgoingContentType = outgoingContentType; + this.innerFormatter = innerFormatter; + } + + public object DeserializeReply(Message message, object[] parameters) + { + return this.innerFormatter.DeserializeReply(message, parameters); + } + + public Message SerializeRequest(MessageVersion messageVersion, object[] parameters) + { + Message message = this.innerFormatter.SerializeRequest(messageVersion, parameters); + if (message != null) + { + AddRequestContentTypeProperty(message, this.outgoingContentType); + } + return message; + } + + static void AddRequestContentTypeProperty(Message message, string contentType) + { + if (message == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(message)); + } + if (contentType == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(contentType)); + } + // dotnet/wcf's WebOperationContext (client subset) does not expose OutgoingRequest + // (server-side OutgoingResponse is what we have). Fall through to the message-property + // path which is the canonical way to set request content-type on outgoing client messages. + { + object prop; + message.Properties.TryGetValue(HttpRequestMessageProperty.Name, out prop); + HttpRequestMessageProperty httpProperty; + if (prop != null) + { + httpProperty = (HttpRequestMessageProperty)prop; + } + else + { + httpProperty = new HttpRequestMessageProperty(); + message.Properties.Add(HttpRequestMessageProperty.Name, httpProperty); + } + if (string.IsNullOrEmpty(httpProperty.Headers[HttpRequestHeader.ContentType])) + { + httpProperty.Headers[HttpRequestHeader.ContentType] = contentType; + } + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/DataContractJsonSerializerOperationFormatter.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/DataContractJsonSerializerOperationFormatter.cs new file mode 100644 index 00000000000..6a36de0c74e --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/DataContractJsonSerializerOperationFormatter.cs @@ -0,0 +1,667 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Collections; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; +using System.Xml; +using System.ServiceModel.Channels; +using System.ServiceModel.Description; + +namespace System.ServiceModel.Dispatcher +{ + internal class DataContractJsonSerializerOperationFormatter : DataContractSerializerOperationFormatter + { + private readonly bool _isBareMessageContractReply; + private readonly bool _isBareMessageContractRequest; + // isWrapped is true when the user has explicitly chosen the response or request format to be Wrapped (allowed only in WebHttpBehavior) + private readonly bool _isWrapped; + + private static readonly DataContractFormatAttribute s_defaultDataContractFormatAttribute = new DataContractFormatAttribute(); + + public DataContractJsonSerializerOperationFormatter(OperationDescription description, int maxItemsInObjectGraph, bool ignoreExtensionDataObject, bool isWrapped, bool useAspNetAjaxJson, string callbackParameterName) + : base(description, s_defaultDataContractFormatAttribute, new DataContractJsonSerializerOperationBehavior(description, maxItemsInObjectGraph, ignoreExtensionDataObject, useAspNetAjaxJson)) + { + if (requestMessageInfo != null) + { + if (requestMessageInfo.WrapperName == null) + { + _isBareMessageContractRequest = true; + } + else + { + requestMessageInfo.WrapperName = JsonGlobals.RootDictionaryString; + requestMessageInfo.WrapperNamespace = XmlDictionaryString.Empty; + } + } + + if (replyMessageInfo != null) + { + if (replyMessageInfo.WrapperName == null) + { + _isBareMessageContractReply = true; + } + else + { + if (useAspNetAjaxJson) + { + replyMessageInfo.WrapperName = JsonGlobals.DDictionaryString; + } + else + { + replyMessageInfo.WrapperName = JsonGlobals.RootDictionaryString; + } + replyMessageInfo.WrapperNamespace = XmlDictionaryString.Empty; + } + } + + _isWrapped = isWrapped; + } + + internal static bool IsJsonLocalName(XmlDictionaryReader reader, string elementName) + { + if (reader.IsStartElement(JsonGlobals.ItemDictionaryString, JsonGlobals.ItemDictionaryString)) + { + if (reader.MoveToAttribute(JsonGlobals.ItemString)) + { + return (reader.Value == elementName); + } + } + + return false; + } + + internal static bool IsStartElement(XmlDictionaryReader reader, string elementName) + { + if (reader.IsStartElement(elementName)) + { + return true; + } + + return IsJsonLocalName(reader, elementName); + } + + internal static bool IsStartElement(XmlDictionaryReader reader, XmlDictionaryString elementName, XmlDictionaryString elementNamespace) + { + if (reader.IsStartElement(elementName, elementNamespace)) + { + return true; + } + + return IsJsonLocalName(reader, (elementName == null) ? null : elementName.Value); + } + + protected override void AddHeadersToMessage(Message message, MessageDescription messageDescription, object[] parameters, bool isRequest) + { + if (message != null) + { + message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.JsonProperty); + } + + base.AddHeadersToMessage(message, messageDescription, parameters, isRequest); + } + + protected override object DeserializeBody(XmlDictionaryReader reader, MessageVersion version, string action, MessageDescription messageDescription, object[] parameters, bool isRequest) + { + if (reader == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(reader))); + } + + if (parameters == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(parameters))); + } + + if (reader.EOF) + { + return null; + } + + if ((isRequest && _isBareMessageContractRequest) || (!isRequest && _isBareMessageContractReply)) + { + return DeserializeBareMessageContract(reader, parameters, isRequest); + } + + object returnValue = null; + + if (isRequest || _isWrapped) + { + ValidateTypeObjectAttribute(reader, isRequest); + returnValue = DeserializeBodyCore(reader, parameters, isRequest); + } + else + { + if (replyMessageInfo.ReturnPart != null) + { + PartInfo part = replyMessageInfo.ReturnPart; + DataContractJsonSerializer serializer = part.Serializer as DataContractJsonSerializer; + + serializer = RecreateDataContractJsonSerializer(serializer, part.ContractType, JsonGlobals.RootString); + VerifyIsStartElement(reader, JsonGlobals.RootString); + + if (serializer.IsStartObject(reader)) + { + try + { + returnValue = part.ReadObject(reader, serializer); + } + catch (InvalidOperationException e) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.SFxInvalidMessageBodyErrorDeserializingParameter, part.Description.Namespace, part.Description.Name), e)); + } + catch (InvalidDataContractException e) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException( + SR.Format(SR.SFxInvalidMessageBodyErrorDeserializingParameter, part.Description.Namespace, part.Description.Name), e)); + } + catch (FormatException e) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + OperationFormatter.CreateDeserializationFailedFault( + SR.Format(SR.SFxInvalidMessageBodyErrorDeserializingParameterMore, + part.Description.Namespace, part.Description.Name, e.Message), + e)); + } + catch (SerializationException e) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + OperationFormatter.CreateDeserializationFailedFault( + SR.Format(SR.SFxInvalidMessageBodyErrorDeserializingParameterMore, + part.Description.Namespace, part.Description.Name, e.Message), + e)); + } + } + } + else if (replyMessageInfo.BodyParts != null) + { + ValidateTypeObjectAttribute(reader, isRequest); + returnValue = DeserializeBodyCore(reader, parameters, isRequest); + } + + while (reader.IsStartElement()) + { + TraceAndSkipElement(reader); + } + } + + return returnValue; + } + + protected override void GetHeadersFromMessage(Message message, MessageDescription messageDescription, object[] parameters, bool isRequest) + { + if (message != null) + { + message.Properties.TryGetValue(WebBodyFormatMessageProperty.Name, out object prop); + WebBodyFormatMessageProperty formatProperty = (prop as WebBodyFormatMessageProperty); + if (formatProperty == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.MessageFormatPropertyNotFound2, OperationName))); + } + if (formatProperty.Format != WebContentFormat.Json) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.InvalidHttpMessageFormat3, OperationName, formatProperty.Format, WebContentFormat.Json))); + } + } + + base.GetHeadersFromMessage(message, messageDescription, parameters, isRequest); + } + + protected override void SerializeBody(XmlDictionaryWriter writer, MessageVersion version, string action, MessageDescription messageDescription, object returnValue, object[] parameters, bool isRequest) + { + if ((isRequest && _isBareMessageContractRequest) || (!isRequest && _isBareMessageContractReply)) + { + SerializeBareMessageContract(writer, parameters, isRequest); + } + else + { + if (isRequest || _isWrapped) + { + SerializeBody(writer, returnValue, parameters, isRequest); + } + else + { + if (replyMessageInfo.ReturnPart != null) + { + DataContractJsonSerializer serializer = replyMessageInfo.ReturnPart.Serializer as DataContractJsonSerializer; + serializer = RecreateDataContractJsonSerializer(serializer, replyMessageInfo.ReturnPart.ContractType, JsonGlobals.RootString); + + try + { + serializer.WriteObject(writer, returnValue); + } + catch (SerializationException sx) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException( + SR.Format(SR.SFxInvalidMessageBodyErrorSerializingParameter, replyMessageInfo.ReturnPart.Description.Namespace, replyMessageInfo.ReturnPart.Description.Name, sx.Message), sx)); + } + } + else if (replyMessageInfo.BodyParts != null) + { + SerializeBody(writer, returnValue, parameters, isRequest); + } + } + } + } + + private static DataContractJsonSerializer RecreateDataContractJsonSerializer(DataContractJsonSerializer serializer, Type type, string newRootName) + { + DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings + { + RootName = newRootName, + KnownTypes = serializer.KnownTypes, + MaxItemsInObjectGraph = serializer.MaxItemsInObjectGraph, + IgnoreExtensionDataObject = serializer.IgnoreExtensionDataObject, + EmitTypeInformation = serializer.EmitTypeInformation, + DateTimeFormat = serializer.DateTimeFormat, + UseSimpleDictionaryFormat = serializer.UseSimpleDictionaryFormat + }; + + return new DataContractJsonSerializer(type, settings); + } + + private object DeserializeBareMessageContract(XmlDictionaryReader reader, object[] parameters, bool isRequest) + { + MessageInfo messageInfo; + if (isRequest) + { + messageInfo = requestMessageInfo; + } + else + { + messageInfo = replyMessageInfo; + } + + if (messageInfo.BodyParts.Length > 0) + { + PartInfo part = messageInfo.BodyParts[0]; + DataContractJsonSerializer serializer = part.Serializer as DataContractJsonSerializer; + serializer = RecreateDataContractJsonSerializer(serializer, part.ContractType, JsonGlobals.RootString); + + while (reader.IsStartElement()) + { + if (serializer.IsStartObject(reader)) + { + try + { + parameters[part.Description.Index] = part.ReadObject(reader, serializer); + break; + } + catch (InvalidOperationException e) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.SFxInvalidMessageBodyErrorDeserializingParameter, part.Description.Namespace, part.Description.Name), e)); + } + catch (InvalidDataContractException e) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException( + SR.Format(SR.SFxInvalidMessageBodyErrorDeserializingParameter, part.Description.Namespace, part.Description.Name), e)); + } + catch (FormatException e) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + OperationFormatter.CreateDeserializationFailedFault( + SR.Format(SR.SFxInvalidMessageBodyErrorDeserializingParameterMore, + part.Description.Namespace, part.Description.Name, e.Message), + e)); + } + catch (SerializationException e) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + OperationFormatter.CreateDeserializationFailedFault( + SR.Format(SR.SFxInvalidMessageBodyErrorDeserializingParameterMore, + part.Description.Namespace, part.Description.Name, e.Message), + e)); + } + } + else + { + TraceAndSkipElement(reader); + } + } + while (reader.IsStartElement()) + { + TraceAndSkipElement(reader); + } + } + + return null; + } + + private object DeserializeBodyCore(XmlDictionaryReader reader, object[] parameters, bool isRequest) + { + MessageInfo messageInfo; + if (isRequest) + { + messageInfo = requestMessageInfo; + } + else + { + messageInfo = replyMessageInfo; + } + + if (messageInfo.WrapperName != null) + { + VerifyIsStartElement(reader, messageInfo.WrapperName, messageInfo.WrapperNamespace); + bool isEmptyElement = reader.IsEmptyElement; + reader.Read(); + if (isEmptyElement) + { + return null; + } + } + + object returnValue = null; + DeserializeParameters(reader, messageInfo.BodyParts, parameters, messageInfo.ReturnPart, ref returnValue); + if (messageInfo.WrapperName != null) + { + reader.ReadEndElement(); + } + + return returnValue; + } + + private object DeserializeParameter(XmlDictionaryReader reader, PartInfo part) + { + if (part.Description.Multiple) + { + ArrayList items = new ArrayList(); + while (part.Serializer.IsStartObject(reader)) + { + items.Add(DeserializeParameterPart(reader, part)); + } + + return items.ToArray(part.Description.Type); + } + + return DeserializeParameterPart(reader, part); + } + + private object DeserializeParameterPart(XmlDictionaryReader reader, PartInfo part) + { + object val; + try + { + val = part.ReadObject(reader); + } + catch (InvalidOperationException e) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.SFxInvalidMessageBodyErrorDeserializingParameter, part.Description.Namespace, part.Description.Name), e)); + } + catch (InvalidDataContractException e) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidDataContractException( + SR.Format(SR.SFxInvalidMessageBodyErrorDeserializingParameter, part.Description.Namespace, part.Description.Name), e)); + } + catch (FormatException e) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + OperationFormatter.CreateDeserializationFailedFault( + SR.Format(SR.SFxInvalidMessageBodyErrorDeserializingParameterMore, + part.Description.Namespace, part.Description.Name, e.Message), + e)); + } + catch (SerializationException e) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + OperationFormatter.CreateDeserializationFailedFault( + SR.Format(SR.SFxInvalidMessageBodyErrorDeserializingParameterMore, + part.Description.Namespace, part.Description.Name, e.Message), + e)); + } + + return val; + } + + private void DeserializeParameters(XmlDictionaryReader reader, PartInfo[] parts, object[] parameters, PartInfo returnInfo, ref object returnValue) + { + bool[] setParameters = new bool[parameters.Length]; + bool hasReadReturnValue = false; + int currentIndex = 0; + + while (reader.IsStartElement()) + { + bool hasReadParameter = false; + + for (int i = 0, index = currentIndex; i < parts.Length; i++, index = (index + 1) % parts.Length) + { + PartInfo part = parts[index]; + if (part.Serializer.IsStartObject(reader)) + { + currentIndex = i; + parameters[part.Description.Index] = DeserializeParameter(reader, part); + setParameters[part.Description.Index] = true; + hasReadParameter = true; + } + } + + if (!hasReadParameter) + { + if ((returnInfo != null) && !hasReadReturnValue && returnInfo.Serializer.IsStartObject(reader)) + { + returnValue = DeserializeParameter(reader, returnInfo); + hasReadReturnValue = true; + } + else + { + TraceAndSkipElement(reader); + } + } + } + + for (int i = 0; i < parameters.Length; i++) + { + if (!setParameters[i]) + { + parameters[i] = null; + } + } + } + + private void SerializeBareMessageContract(XmlDictionaryWriter writer, object[] parameters, bool isRequest) + { + if (writer == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(writer))); + } + + if (parameters == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(parameters))); + } + + MessageInfo messageInfo; + if (isRequest) + { + messageInfo = requestMessageInfo; + } + else + { + messageInfo = replyMessageInfo; + } + + if (messageInfo.BodyParts.Length > 0) + { + PartInfo part = messageInfo.BodyParts[0]; + DataContractJsonSerializer serializer = part.Serializer as DataContractJsonSerializer; + serializer = RecreateDataContractJsonSerializer(serializer, part.ContractType, JsonGlobals.RootString); + + object graph = parameters[part.Description.Index]; + try + { + serializer.WriteObject(writer, graph); + } + catch (SerializationException sx) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException( + SR.Format(SR.SFxInvalidMessageBodyErrorSerializingParameter, part.Description.Namespace, part.Description.Name, sx.Message), sx)); + } + } + } + + private void SerializeBody(XmlDictionaryWriter writer, object returnValue, object[] parameters, bool isRequest) + { + if (writer == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(writer))); + } + + if (parameters == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException(nameof(parameters))); + } + + MessageInfo messageInfo; + if (isRequest) + { + messageInfo = requestMessageInfo; + } + else + { + messageInfo = replyMessageInfo; + } + + if (messageInfo.WrapperName != null) + { + writer.WriteStartElement(messageInfo.WrapperName, messageInfo.WrapperNamespace); + writer.WriteAttributeString(JsonGlobals.TypeString, JsonGlobals.ObjectString); + } + + if (messageInfo.ReturnPart != null) + { + SerializeParameter(writer, messageInfo.ReturnPart, returnValue); + } + + SerializeParameters(writer, messageInfo.BodyParts, parameters); + + if (messageInfo.WrapperName != null) + { + writer.WriteEndElement(); + } + } + + private void SerializeParameter(XmlDictionaryWriter writer, PartInfo part, object graph) + { + if (part.Description.Multiple) + { + if (graph != null) + { + foreach (object item in (IEnumerable)graph) + { + SerializeParameterPart(writer, part, item); + } + } + } + else + { + SerializeParameterPart(writer, part, graph); + } + } + + private void SerializeParameterPart(XmlDictionaryWriter writer, PartInfo part, object graph) + { + try + { + part.Serializer.WriteObject(writer, graph); + } + catch (SerializationException sx) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException( + SR.Format(SR.SFxInvalidMessageBodyErrorSerializingParameter, part.Description.Namespace, part.Description.Name, sx.Message), sx)); + } + } + + private void SerializeParameters(XmlDictionaryWriter writer, PartInfo[] parts, object[] parameters) + { + for (int i = 0; i < parts.Length; i++) + { + PartInfo part = parts[i]; + object graph = parameters[part.Description.Index]; + SerializeParameter(writer, part, graph); + } + } + + private void ValidateTypeObjectAttribute(XmlDictionaryReader reader, bool isRequest) + { + MessageInfo messageInfo = isRequest ? requestMessageInfo : replyMessageInfo; + if (messageInfo.WrapperName != null) + { + if (!IsStartElement(reader, messageInfo.WrapperName, messageInfo.WrapperNamespace)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.Format(SR.SFxInvalidMessageBody, messageInfo.WrapperName, messageInfo.WrapperNamespace, reader.NodeType, reader.Name, reader.NamespaceURI))); + } + + string typeAttribute = reader.GetAttribute(JsonGlobals.TypeString); + if (!typeAttribute.Equals(JsonGlobals.ObjectString, StringComparison.Ordinal)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + new SerializationException(SR.Format(SR.JsonFormatterExpectedAttributeObject, typeAttribute))); + } + } + } + + private void VerifyIsStartElement(XmlDictionaryReader reader, string elementName) + { + bool foundElement = false; + while (reader.IsStartElement()) + { + if (IsStartElement(reader, elementName)) + { + foundElement = true; + break; + } + else + { + TraceAndSkipElement(reader); + } + } + + if (!foundElement) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.Format(SR.SFxInvalidMessageBody, elementName, string.Empty, reader.NodeType, reader.Name, reader.NamespaceURI))); + } + } + + private void VerifyIsStartElement(XmlDictionaryReader reader, XmlDictionaryString elementName, XmlDictionaryString elementNamespace) + { + bool foundElement = false; + while (reader.IsStartElement()) + { + if (IsStartElement(reader, elementName, elementNamespace)) + { + foundElement = true; + break; + } + else + { + TraceAndSkipElement(reader); + } + } + + if (!foundElement) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.Format(SR.SFxInvalidMessageBody, elementName, elementNamespace, reader.NodeType, reader.Name, reader.NamespaceURI))); + } + } + + private void WriteVoidReturn(XmlDictionaryWriter writer) + { + writer.WriteStartElement(JsonGlobals.DString); + writer.WriteAttributeString(JsonGlobals.TypeString, JsonGlobals.NullString); + writer.WriteEndElement(); + } + + + private static void TraceAndSkipElement(XmlReader xmlReader) + { + //if (DiagnosticUtility.ShouldTraceVerbose) + //{ + // TraceUtility.TraceEvent(TraceEventType.Verbose, TraceCode.ElementIgnored, SR.SFxTraceCodeElementIgnored, new StringTraceRecord("Element", xmlReader.NamespaceURI + ":" + xmlReader.LocalName)); + //} + xmlReader.Skip(); + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/HttpStreamFormatter.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/HttpStreamFormatter.cs new file mode 100644 index 00000000000..05efc4e4c7e --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/HttpStreamFormatter.cs @@ -0,0 +1,111 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.IO; +using System.ServiceModel.Channels; +using System.ServiceModel.Description; + +namespace System.ServiceModel.Dispatcher +{ + internal class HttpStreamFormatter : IDispatchMessageFormatter, IClientMessageFormatter + { + private readonly string _contractName; + private readonly string _contractNs; + private readonly string _operationName; + + public HttpStreamFormatter(OperationDescription operation) + { + if (operation == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(operation)); + } + + _operationName = operation.Name; + _contractName = operation.DeclaringContract.Name; + _contractNs = operation.DeclaringContract.Namespace; + } + + public void DeserializeRequest(Message message, object[] parameters) + { + parameters[0] = GetStreamFromMessage(message, true); + } + + public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result) + { + Message message = CreateMessageFromStream(result); + if (result == null) + { + SingleBodyParameterMessageFormatter.SuppressReplyEntityBody(message); + } + + return message; + } + + public object DeserializeReply(Message message, object[] parameters) + { + return GetStreamFromMessage(message, false); + } + + public Message SerializeRequest(MessageVersion messageVersion, object[] parameters) + { + Message message = CreateMessageFromStream(parameters[0]); + if (parameters[0] == null) + { + SingleBodyParameterMessageFormatter.SuppressRequestEntityBody(message); + } + return message; + } + + internal static bool IsEmptyMessage(Message message) => message.IsEmpty; + + private Message CreateMessageFromStream(object data) + { + Message result; + if (data == null) + { + result = Message.CreateMessage(MessageVersion.None, (string)null); + } + else + { + if (!(data is Stream streamData)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.Format(SR.ParameterIsNotStreamType, data.GetType(), _operationName, _contractName, _contractNs))); + } + + // ByteStreamMessage / raw octet-stream pass-through is not supported in this client port. + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + new NotSupportedException(SR.WebHttpRawContentNotSupported)); + } + + return result; + } + + private Stream GetStreamFromMessage(Message message, bool isRequest) + { + message.Properties.TryGetValue(WebBodyFormatMessageProperty.Name, out object prop); + WebBodyFormatMessageProperty formatProperty = (prop as WebBodyFormatMessageProperty); + if (formatProperty == null) + { + // GET and DELETE do not go through the encoder + if (IsEmptyMessage(message)) + { + return new MemoryStream(); + } + else + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.Format(SR.MessageFormatPropertyNotFound, _operationName, _contractName, _contractNs))); + } + } + + if (formatProperty.Format != WebContentFormat.Raw) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.Format(SR.InvalidHttpMessageFormat, _operationName, _contractName, _contractNs, formatProperty.Format, WebContentFormat.Raw))); + } + + // MessageBodyStream is server-side only; not ported. + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + new NotSupportedException(SR.WebHttpRawContentNotSupported)); + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/JsonFormatMapping.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/JsonFormatMapping.cs new file mode 100644 index 00000000000..e45f6d17e6a --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/JsonFormatMapping.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System.Collections.Generic; +using System.Text; +using System.Xml; +using System.ServiceModel.Channels; +using System.ServiceModel.Web; + +namespace System.ServiceModel.Dispatcher +{ + internal class JsonFormatMapping : MultiplexingFormatMapping + { + public static readonly WebContentFormat WebContentFormat = WebContentFormat.Json; + + private static readonly string s_defaultMediaType = JsonGlobals.ApplicationJsonMediaType; + private static readonly Dictionary s_encoders = new Dictionary(); + private static readonly object s_thisLock = new object(); + + public JsonFormatMapping(Encoding writeEncoding, WebContentTypeMapper contentTypeMapper) + : base(writeEncoding, contentTypeMapper) + { } + + public override WebContentFormat ContentFormat => WebContentFormat; + + public override WebMessageFormat MessageFormat => WebMessageFormat.Json; + + public override string DefaultMediaType => s_defaultMediaType; + + protected override MessageEncoder Encoder + { + get + { + lock (s_thisLock) + { + if (!s_encoders.ContainsKey(writeEncoding)) + { + s_encoders[writeEncoding] = new JsonMessageEncoderFactory(writeEncoding, 0, 0, new XmlDictionaryReaderQuotas(), false).Encoder; + } + } + + return s_encoders[writeEncoding]; + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/MultiplexingFormatMapping.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/MultiplexingFormatMapping.cs new file mode 100644 index 00000000000..24daf280896 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/MultiplexingFormatMapping.cs @@ -0,0 +1,86 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Net.Mime; +using System.Text; +using System.ServiceModel.Channels; +using System.ServiceModel.Web; + +namespace System.ServiceModel.Dispatcher +{ + internal abstract class MultiplexingFormatMapping + { + protected Encoding writeEncoding; + protected string writeCharset; + protected WebContentTypeMapper contentTypeMapper; + + public abstract WebMessageFormat MessageFormat { get; } + public abstract WebContentFormat ContentFormat { get; } + public abstract string DefaultMediaType { get; } + protected abstract MessageEncoder Encoder { get; } + + private ContentType _defaultContentType; + + public ContentType DefaultContentType + { + get + { + if (_defaultContentType == null) + { + _defaultContentType = new ContentType(DefaultMediaType) { CharSet = writeCharset }; + } + + return _defaultContentType; + } + } + + public MultiplexingFormatMapping(Encoding writeEncoding, WebContentTypeMapper contentTypeMapper) + { + if (writeEncoding == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(writeEncoding)); + } + + this.writeEncoding = writeEncoding; + writeCharset = TextEncoderDefaults.EncodingToCharSet(writeEncoding); + this.contentTypeMapper = contentTypeMapper; + } + + public bool CanFormatResponse(ContentType acceptHeaderElement, bool matchCharset, out ContentType contentType) + { + if (acceptHeaderElement == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(acceptHeaderElement)); + } + + // Scrub the content type so that it is only mediaType and the charset + string charset = acceptHeaderElement.CharSet; + contentType = new ContentType(acceptHeaderElement.MediaType); + contentType.CharSet = DefaultContentType.CharSet; + string contentTypeStr = contentType.ToString(); + + if (matchCharset && + !string.IsNullOrEmpty(charset) && + !string.Equals(charset, DefaultContentType.CharSet, StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + if (contentTypeMapper != null && + contentTypeMapper.GetMessageFormatForContentType(contentType.MediaType) == ContentFormat) + { + return true; + } + + if (Encoder.IsContentTypeSupported(contentTypeStr) && + (charset == null || contentType.CharSet == DefaultContentType.CharSet)) + { + return true; + } + + contentType = null; + return false; + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/NameValueCache.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/NameValueCache.cs new file mode 100644 index 00000000000..a9f9b67a066 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/NameValueCache.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System.Collections; + +namespace System.ServiceModel.Dispatcher +{ + internal class NameValueCache + { + // The NameValueCache implements a structure that uses a dictionary to map objects to + // indices of an array of cache entries. This allows us to store the cache entries in + // the order in which they were added to the cache, and yet still lookup any cache entry. + // The eviction policy of the cache is to evict the least-recently-added cache entry. + // Using a pointer to the next available cache entry in the array, we can always be sure + // that the given entry is the oldest entry. + private readonly Hashtable _cache; + private readonly string[] _currentKeys; + private int _nextAvailableCacheIndex; + internal const int MaxNumberofEntriesInCache = 16; + + public NameValueCache() + : this(MaxNumberofEntriesInCache) + { + } + + public NameValueCache(int maxCacheEntries) + { + _cache = new Hashtable(); + _currentKeys = new string[maxCacheEntries]; + } + + public T Lookup(string key) + { + return (T)_cache[key]; + } + + public void AddOrUpdate(string key, T value) + { + lock (_cache) + { + if (!_cache.ContainsKey(key)) + { + if (!string.IsNullOrEmpty(_currentKeys[_nextAvailableCacheIndex])) + { + _cache.Remove(_currentKeys[_nextAvailableCacheIndex]); + } + + _currentKeys[_nextAvailableCacheIndex] = key; + _nextAvailableCacheIndex = ++_nextAvailableCacheIndex % _currentKeys.Length; + } + + _cache[key] = value; + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/QueryStringConverter.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/QueryStringConverter.cs new file mode 100644 index 00000000000..071c2140655 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/QueryStringConverter.cs @@ -0,0 +1,330 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Collections; +using System.ComponentModel; +using System.Diagnostics; +using System.Globalization; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Xml; +using System.Runtime; + +namespace System.ServiceModel.Dispatcher +{ + public class QueryStringConverter + { + private readonly Hashtable _defaultSupportedQueryStringTypes; + + // the cache does not have a quota since it is per endpoint and is + // bounded by the number of types in the contract at the endpoint + private readonly Hashtable _typeConverterCache; + + public QueryStringConverter() + { + _defaultSupportedQueryStringTypes = new Hashtable(); + _defaultSupportedQueryStringTypes.Add(typeof(byte), null); + _defaultSupportedQueryStringTypes.Add(typeof(sbyte), null); + _defaultSupportedQueryStringTypes.Add(typeof(short), null); + _defaultSupportedQueryStringTypes.Add(typeof(int), null); + _defaultSupportedQueryStringTypes.Add(typeof(long), null); + _defaultSupportedQueryStringTypes.Add(typeof(ushort), null); + _defaultSupportedQueryStringTypes.Add(typeof(uint), null); + _defaultSupportedQueryStringTypes.Add(typeof(ulong), null); + _defaultSupportedQueryStringTypes.Add(typeof(float), null); + _defaultSupportedQueryStringTypes.Add(typeof(double), null); + _defaultSupportedQueryStringTypes.Add(typeof(bool), null); + _defaultSupportedQueryStringTypes.Add(typeof(char), null); + _defaultSupportedQueryStringTypes.Add(typeof(decimal), null); + _defaultSupportedQueryStringTypes.Add(typeof(string), null); + _defaultSupportedQueryStringTypes.Add(typeof(object), null); + _defaultSupportedQueryStringTypes.Add(typeof(DateTime), null); + _defaultSupportedQueryStringTypes.Add(typeof(TimeSpan), null); + _defaultSupportedQueryStringTypes.Add(typeof(byte[]), null); + _defaultSupportedQueryStringTypes.Add(typeof(Guid), null); + _defaultSupportedQueryStringTypes.Add(typeof(Uri), null); + _defaultSupportedQueryStringTypes.Add(typeof(DateTimeOffset), null); + _typeConverterCache = new Hashtable(); + } + + public virtual bool CanConvert(Type type) + { + if (_defaultSupportedQueryStringTypes.ContainsKey(type)) + { + return true; + } + + // otherwise check if its an enum + if (typeof(Enum).IsAssignableFrom(type)) + { + return true; + } + + // check if there's a typeconverter defined on the type + return (GetStringConverter(type) != null); + } + + public virtual object ConvertStringToValue(string parameter, Type parameterType) + { + if (parameterType == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(parameterType)); + } + + switch (Type.GetTypeCode(parameterType)) + { + case TypeCode.Byte: + return parameter == null ? default : XmlConvert.ToByte(parameter); + case TypeCode.SByte: + return parameter == null ? default : XmlConvert.ToSByte(parameter); + case TypeCode.Int16: + return parameter == null ? default : XmlConvert.ToInt16(parameter); + case TypeCode.Int32: + { + if (typeof(Enum).IsAssignableFrom(parameterType)) + { + return Enum.Parse(parameterType, parameter, true); + } + else + { + return parameter == null ? default : XmlConvert.ToInt32(parameter); + } + } + case TypeCode.Int64: + return parameter == null ? default : XmlConvert.ToInt64(parameter); + case TypeCode.UInt16: + return parameter == null ? default : XmlConvert.ToUInt16(parameter); + case TypeCode.UInt32: + return parameter == null ? default : XmlConvert.ToUInt32(parameter); + case TypeCode.UInt64: + return parameter == null ? default : XmlConvert.ToUInt64(parameter); + case TypeCode.Single: + return parameter == null ? default : XmlConvert.ToSingle(parameter); + case TypeCode.Double: + return parameter == null ? default : XmlConvert.ToDouble(parameter); + case TypeCode.Char: + return parameter == null ? default : XmlConvert.ToChar(parameter); + case TypeCode.Decimal: + return parameter == null ? default : XmlConvert.ToDecimal(parameter); + case TypeCode.Boolean: + return parameter == null ? default : Convert.ToBoolean(parameter, CultureInfo.InvariantCulture); + case TypeCode.String: + return parameter; + case TypeCode.DateTime: + return parameter == null ? default : DateTime.Parse(parameter, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind); + default: + { + if (parameterType == typeof(TimeSpan)) + { + // support the XML as well as default way of representing timespans + TimeSpan result; + if (!TimeSpan.TryParse(parameter, out result)) + { + result = parameter == null ? default : XmlConvert.ToTimeSpan(parameter); + } + return result; + } + else if (parameterType == typeof(Guid)) + { + return parameter == null ? default : XmlConvert.ToGuid(parameter); + } + else if (parameterType == typeof(DateTimeOffset)) + { + return (parameter == null) ? default : DateTimeOffset.Parse(parameter, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind | DateTimeStyles.AllowWhiteSpaces); + } + else if (parameterType == typeof(byte[])) + { + return (!string.IsNullOrEmpty(parameter)) ? Convert.FromBase64String(parameter) : new byte[] { }; + } + else if (parameterType == typeof(Uri)) + { + return (!string.IsNullOrEmpty(parameter)) ? new Uri(parameter, UriKind.RelativeOrAbsolute) : null; + } + else if (parameterType == typeof(object)) + { + return parameter; + } + else + { + TypeConverter stringConverter = GetStringConverter(parameterType); + if (stringConverter == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException( + SR.Format( + SR.TypeNotSupportedByQueryStringConverter, + parameterType.ToString(), GetType().Name))); + } + + return stringConverter.ConvertFromInvariantString(parameter); + } + } + } + } + + public virtual string ConvertValueToString(object parameter, Type parameterType) + { + if (parameterType == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(parameterType)); + } + + if (parameterType.IsValueType && parameter == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(parameter)); + } + + switch (Type.GetTypeCode(parameterType)) + { + case TypeCode.Byte: + return XmlConvert.ToString((byte)parameter); + case TypeCode.SByte: + return XmlConvert.ToString((sbyte)parameter); + case TypeCode.Int16: + return XmlConvert.ToString((short)parameter); + case TypeCode.Int32: + { + if (typeof(Enum).IsAssignableFrom(parameterType)) + { + return Enum.Format(parameterType, parameter, "G"); + } + else + { + return XmlConvert.ToString((int)parameter); + } + } + case TypeCode.Int64: + return XmlConvert.ToString((long)parameter); + case TypeCode.UInt16: + return XmlConvert.ToString((ushort)parameter); + case TypeCode.UInt32: + return XmlConvert.ToString((uint)parameter); + case TypeCode.UInt64: + return XmlConvert.ToString((ulong)parameter); + case TypeCode.Single: + return XmlConvert.ToString((float)parameter); + case TypeCode.Double: + return XmlConvert.ToString((double)parameter); + case TypeCode.Char: + return XmlConvert.ToString((char)parameter); + case TypeCode.Decimal: + return XmlConvert.ToString((decimal)parameter); + case TypeCode.Boolean: + return XmlConvert.ToString((bool)parameter); + case TypeCode.String: + return (string)parameter; + case TypeCode.DateTime: + return XmlConvert.ToString((DateTime)parameter, XmlDateTimeSerializationMode.RoundtripKind); + default: + { + if (parameterType == typeof(TimeSpan)) + { + return XmlConvert.ToString((TimeSpan)parameter); + } + else if (parameterType == typeof(Guid)) + { + return XmlConvert.ToString((Guid)parameter); + } + else if (parameterType == typeof(DateTimeOffset)) + { + return XmlConvert.ToString((DateTimeOffset)parameter); + } + else if (parameterType == typeof(byte[])) + { + return (parameter != null) ? Convert.ToBase64String((byte[])parameter, Base64FormattingOptions.None) : null; + } + else if (parameterType == typeof(Uri) || parameterType == typeof(object)) + { + // URI or object + return (parameter != null) ? Convert.ToString(parameter, CultureInfo.InvariantCulture) : null; + } + else + { + TypeConverter stringConverter = GetStringConverter(parameterType); + if (stringConverter == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException( + SR.Format( + SR.TypeNotSupportedByQueryStringConverter, + parameterType.ToString(), GetType().Name))); + } + else + { + return stringConverter.ConvertToInvariantString(parameter); + } + } + } + } + } + + // hash table is safe for multiple readers single writer + private TypeConverter GetStringConverter(Type parameterType) + { + if (_typeConverterCache.ContainsKey(parameterType)) + { + return (TypeConverter)_typeConverterCache[parameterType]; + } + + if (parameterType.GetCustomAttributes(typeof(TypeConverterAttribute), true) is TypeConverterAttribute[] typeConverterAttrs) + { + foreach (TypeConverterAttribute converterAttr in typeConverterAttrs) + { + Type converterType = Type.GetType(converterAttr.ConverterTypeName, false, true); + if (converterType != null) + { + TypeConverter converter = null; + Exception handledException = null; + try + { + converter = (TypeConverter)Activator.CreateInstance(converterType); + } + catch (TargetInvocationException e) + { + handledException = e; + } + catch (MemberAccessException e) + { + handledException = e; + } + catch (TypeLoadException e) + { + handledException = e; + } + catch (COMException e) + { + handledException = e; + } + catch (InvalidComObjectException e) + { + handledException = e; + } + finally + { + if (handledException != null) + { + if (Fx.IsFatal(handledException)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(handledException); + } + DiagnosticUtility.TraceHandledException(handledException, TraceEventType.Warning); + } + } + + if (converter == null) + { + continue; + } + + if (converter.CanConvertTo(typeof(string)) && converter.CanConvertFrom(typeof(string))) + { + _typeConverterCache.Add(parameterType, converter); + return converter; + } + } + } + } + + return null; + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/SingleBodyParameterDataContractMessageFormatter.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/SingleBodyParameterDataContractMessageFormatter.cs new file mode 100644 index 00000000000..85dc415b741 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/SingleBodyParameterDataContractMessageFormatter.cs @@ -0,0 +1,244 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Runtime.Serialization.Json; +using System.ServiceModel.Channels; +using System.ServiceModel.Description; + +namespace System.ServiceModel.Dispatcher +{ + internal class SingleBodyParameterDataContractMessageFormatter : SingleBodyParameterMessageFormatter + { + private static readonly Type s_typeOfNullable = typeof(Nullable<>); + private static readonly Type[] s_collectionDataContractInterfaces = new Type[] { typeof(IEnumerable), typeof(IList), typeof(ICollection), typeof(IDictionary) }; + private static readonly Type[] s_genericCollectionDataContractInterfaces = new Type[] { typeof(IEnumerable<>), typeof(IList<>), typeof(ICollection<>), typeof(IDictionary<,>) }; + private XmlObjectSerializer _cachedOutputSerializer; + private Type _cachedOutputSerializerType; + private readonly bool _ignoreExtensionData; + private XmlObjectSerializer[] _inputSerializers; + private readonly IList _knownTypes; + private readonly int _maxItemsInObjectGraph; + private readonly Type _parameterDataContractType; + private readonly object _thisLock; + private readonly bool _useJsonFormat; + private readonly bool _isParameterCollectionInterfaceDataContract; + private readonly bool _isQueryable; + + public SingleBodyParameterDataContractMessageFormatter(OperationDescription operation, Type parameterType, bool isRequestFormatter, bool useJsonFormat, DataContractSerializerOperationBehavior dcsob) + : base(operation, isRequestFormatter, "DataContractSerializer") + { + if (operation == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(operation)); + } + + if (parameterType == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(parameterType)); + } + + if (dcsob == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(dcsob)); + } + + _parameterDataContractType = DataContractHelpers.GetSubstituteDataContractType(parameterType, out _isQueryable); + _isParameterCollectionInterfaceDataContract = IsTypeCollectionInterface(_parameterDataContractType); + List tmp = new List(); + if (operation.KnownTypes != null) + { + foreach (Type knownType in operation.KnownTypes) + { + tmp.Add(knownType); + } + } + + Type nullableType = UnwrapNullableType(_parameterDataContractType); + if (nullableType != _parameterDataContractType) + { + tmp.Add(nullableType); + } + + _ignoreExtensionData = dcsob.IgnoreExtensionDataObject; + _maxItemsInObjectGraph = dcsob.MaxItemsInObjectGraph; + _knownTypes = tmp.AsReadOnly(); + ValidateType(_parameterDataContractType, _knownTypes); + + _useJsonFormat = useJsonFormat; + CreateInputSerializers(_parameterDataContractType); + + _thisLock = new object(); + } + + internal static Type UnwrapNullableType(Type type) + { + while (type.IsGenericType && type.GetGenericTypeDefinition() == s_typeOfNullable) + { + type = type.GetGenericArguments()[0]; + } + + return type; + } + + // The logic of this method should be kept the same as + // System.ServiceModel.Dispatcher.DataContractSerializerOperationFormatter.PartInfo.ReadObject + protected override object ReadObject(Message message) + { + object val = base.ReadObject(message); + if (_isQueryable && val != null) + { + return Queryable.AsQueryable((IEnumerable)val); + } + + return val; + } + + protected override void AttachMessageProperties(Message message, bool isRequest) + { + if (_useJsonFormat) + { + message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.JsonProperty); + } + } + + protected override XmlObjectSerializer[] GetInputSerializers() + { + return _inputSerializers; + } + + protected override XmlObjectSerializer GetOutputSerializer(Type type) + { + lock (_thisLock) + { + // if we already have a serializer for this type reuse it + if (_cachedOutputSerializerType != type) + { + Type typeForSerializer; + if (_isParameterCollectionInterfaceDataContract) + { + // if the parameterType is a collection interface, ensure the type implements it + if (!_parameterDataContractType.IsAssignableFrom(type)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.Format(SR.TypeIsNotParameterTypeAndIsNotPresentInKnownTypes, type, OperationName, ContractName, _parameterDataContractType))); + } + typeForSerializer = _parameterDataContractType; + } + else + { + typeForSerializer = GetTypeForSerializer(type, _parameterDataContractType, _knownTypes); + } + _cachedOutputSerializer = CreateSerializer(typeForSerializer); + _cachedOutputSerializerType = type; + } + + return _cachedOutputSerializer; + } + } + + private static bool IsTypeCollectionInterface(Type parameterType) + { + if (parameterType.IsGenericType && parameterType.IsInterface) + { + Type genericTypeDef = parameterType.GetGenericTypeDefinition(); + foreach (Type type in s_genericCollectionDataContractInterfaces) + { + if (genericTypeDef == type) + { + return true; + } + } + } + + foreach (Type type in s_collectionDataContractInterfaces) + { + if (parameterType == type) + { + return true; + } + } + + return false; + } + + protected override void ValidateMessageFormatProperty(Message message) + { + if (_useJsonFormat) + { + // useJsonFormat is always false in the green bits + message.Properties.TryGetValue(WebBodyFormatMessageProperty.Name, out object prop); + WebBodyFormatMessageProperty formatProperty = (prop as WebBodyFormatMessageProperty); + if (formatProperty == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.Format(SR.MessageFormatPropertyNotFound, OperationName, ContractName, ContractNs))); + } + if (formatProperty.Format != WebContentFormat.Json) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.Format(SR.InvalidHttpMessageFormat, OperationName, ContractName, ContractNs, formatProperty.Format, WebContentFormat.Json))); + } + } + else + { + base.ValidateMessageFormatProperty(message); + } + } + + private static void ValidateType(Type parameterType, IEnumerable knownTypes) + { + XsdDataContractExporter dataContractExporter = new XsdDataContractExporter(); + if (knownTypes != null) + { + ExportOptions options = new ExportOptions(); + + foreach (Type knownType in knownTypes) + { + options.KnownTypes.Add(knownType); + } + + dataContractExporter.Options = options; + } + + dataContractExporter.GetSchemaTypeName(parameterType); // throws if parameterType is not a valid data contract + } + + private void CreateInputSerializers(Type type) + { + List tmp = new List(); + tmp.Add(CreateSerializer(type)); + foreach (Type knownType in _knownTypes) + { + tmp.Add(CreateSerializer(knownType)); + } + + _inputSerializers = tmp.ToArray(); + } + + private XmlObjectSerializer CreateSerializer(Type type) + { + if (_useJsonFormat) + { + return new DataContractJsonSerializer(type, new DataContractJsonSerializerSettings + { + KnownTypes = _knownTypes, + MaxItemsInObjectGraph = _maxItemsInObjectGraph, + IgnoreExtensionDataObject = _ignoreExtensionData, + EmitTypeInformation = EmitTypeInformation.AsNeeded + }); + } + else + { + return new DataContractSerializer(type, new DataContractSerializerSettings + { + KnownTypes = _knownTypes, + MaxItemsInObjectGraph = _maxItemsInObjectGraph, + IgnoreExtensionDataObject = _ignoreExtensionData, + PreserveObjectReferences = false + }); + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/SingleBodyParameterMessageFormatter.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/SingleBodyParameterMessageFormatter.cs new file mode 100644 index 00000000000..0b21010e899 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/SingleBodyParameterMessageFormatter.cs @@ -0,0 +1,331 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Xml; +using System.ServiceModel.Channels; +using System.Collections.Generic; +using System.ServiceModel.Description; +using System.ServiceModel.Web; + +namespace System.ServiceModel.Dispatcher +{ + internal abstract class SingleBodyParameterMessageFormatter : IDispatchMessageFormatter, IClientMessageFormatter + { + private readonly bool _isRequestFormatter; + private readonly string _serializerType; + + protected SingleBodyParameterMessageFormatter(OperationDescription operation, bool isRequestFormatter, string serializerType) + { + if (operation == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(operation)); + } + + ContractName = operation.DeclaringContract.Name; + ContractNs = operation.DeclaringContract.Namespace; + OperationName = operation.Name; + _isRequestFormatter = isRequestFormatter; + _serializerType = serializerType; + } + + protected string ContractName { get; } + + protected string ContractNs { get; } + + protected string OperationName { get; } + + public static IDispatchMessageFormatter CreateXmlAndJsonDispatchFormatter(OperationDescription operation, Type type, bool isRequestFormatter, UnwrappedTypesXmlSerializerManager xmlSerializerManager, string callbackParameterName) + { + IDispatchMessageFormatter xmlFormatter = CreateDispatchFormatter(operation, type, isRequestFormatter, false, xmlSerializerManager, null); + if (!WebHttpBehavior.SupportsJsonFormat(operation)) + { + return xmlFormatter; + } + + IDispatchMessageFormatter jsonFormatter = CreateDispatchFormatter(operation, type, isRequestFormatter, true, xmlSerializerManager, callbackParameterName); + // DemultiplexingDispatchMessageFormatter is server-side only (not ported). + // For the client-only port, fall back to the XML formatter as the single choice. + return xmlFormatter; + } + + public static IClientMessageFormatter CreateXmlAndJsonClientFormatter(OperationDescription operation, Type type, bool isRequestFormatter, UnwrappedTypesXmlSerializerManager xmlSerializerManager, bool preferJson = false) + { + // The .NET Framework implementation builds a DemultiplexingClientMessageFormatter + // here that picks XML or JSON based on the actual response Content-Type. That class + // has not yet been ported to dotnet/wcf, so for now we honour the static choice + // declared on the operation's [WebGet]/[WebInvoke] ResponseFormat attribute. + bool useJson = preferJson && WebHttpBehavior.SupportsJsonFormat(operation); + return CreateClientFormatter(operation, type, isRequestFormatter, useJson, xmlSerializerManager); + } + + public Message SerializeRequest(MessageVersion messageVersion, object[] parameters) + { + if (!_isRequestFormatter) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.FormatterCannotBeUsedForRequestMessages))); + } + Message message = Message.CreateMessage(messageVersion, (string)null, CreateBodyWriter(parameters[0])); + if (parameters[0] == null) + { + SuppressRequestEntityBody(message); + } + AttachMessageProperties(message, true); + return message; + } + + public object DeserializeReply(Message message, object[] parameters) + { + if (_isRequestFormatter) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.FormatterCannotBeUsedForReplyMessages))); + } + return ReadObject(message); + } + + internal static IClientMessageFormatter CreateClientFormatter(OperationDescription operation, Type type, bool isRequestFormatter, bool useJson, UnwrappedTypesXmlSerializerManager xmlSerializerManager) + { + if (type == null) + { + return new NullMessageFormatter(); + } + else if (useJson) + { + return CreateJsonFormatter(operation, type, isRequestFormatter); + } + else + { + return CreateXmlFormatter(operation, type, isRequestFormatter, xmlSerializerManager); + } + } + + internal static void SuppressRequestEntityBody(Message message) + { + object prop; + message.Properties.TryGetValue(HttpRequestMessageProperty.Name, out prop); + HttpRequestMessageProperty httpProperty = prop as HttpRequestMessageProperty; + if (httpProperty == null) + { + httpProperty = new HttpRequestMessageProperty(); + message.Properties[HttpRequestMessageProperty.Name] = httpProperty; + } + httpProperty.SuppressEntityBody = true; + } + + public void DeserializeRequest(Message message, object[] parameters) + { + if (!_isRequestFormatter) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.FormatterCannotBeUsedForRequestMessages))); + } + + parameters[0] = ReadObject(message); + } + + public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result) + { + if (_isRequestFormatter) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.FormatterCannotBeUsedForReplyMessages))); + } + + Message message = Message.CreateMessage(messageVersion, (string)null, CreateBodyWriter(result)); + if (result == null) + { + SuppressReplyEntityBody(message); + } + + AttachMessageProperties(message, false); + + return message; + } + + internal static IDispatchMessageFormatter CreateDispatchFormatter(OperationDescription operation, Type type, bool isRequestFormatter, bool useJson, UnwrappedTypesXmlSerializerManager xmlSerializerManager, string callbackParameterName) + { + if (type == null) + { + return new NullMessageFormatter(); + } + else if (useJson) + { + return CreateJsonFormatter(operation, type, isRequestFormatter); + } + else + { + return CreateXmlFormatter(operation, type, isRequestFormatter, xmlSerializerManager); + } + } + + internal static void SuppressReplyEntityBody(Message message) + { + WebOperationContext currentContext = WebOperationContext.Current; + if (currentContext != null) + { + OutgoingWebResponseContext responseContext = currentContext.OutgoingResponse; + if (responseContext != null) + { + responseContext.SuppressEntityBody = true; + } + } + // The else branch (raw HttpResponseMessageProperty.SuppressEntityBody) is server-side only. + // HttpResponseMessageProperty does not expose SuppressEntityBody in dotnet/wcf's client library. + } + + protected virtual void AttachMessageProperties(Message message, bool isRequest) + { + } + + protected abstract XmlObjectSerializer[] GetInputSerializers(); + + protected abstract XmlObjectSerializer GetOutputSerializer(Type type); + + protected virtual void ValidateMessageFormatProperty(Message message) + { + } + + protected Type GetTypeForSerializer(Type type, Type parameterType, IList knownTypes) + { + if (type == parameterType) + { + return type; + } + else if (knownTypes != null) + { + for (int i = 0; i < knownTypes.Count; ++i) + { + if (type == knownTypes[i]) + { + return type; + } + } + } + + return parameterType; + } + + public static SingleBodyParameterMessageFormatter CreateXmlFormatter(OperationDescription operation, Type type, bool isRequestFormatter, UnwrappedTypesXmlSerializerManager xmlSerializerManager) + { + DataContractSerializerOperationBehavior dcsob = ((KeyedByTypeCollection)operation.OperationBehaviors).Find(); + if (dcsob != null) + { + return new SingleBodyParameterDataContractMessageFormatter(operation, type, isRequestFormatter, false, dcsob); + } + + XmlSerializerOperationBehavior xsob = ((KeyedByTypeCollection)operation.OperationBehaviors).Find(); + if (xsob != null) + { + return new SingleBodyParameterXmlSerializerMessageFormatter(operation, type, isRequestFormatter, xsob, xmlSerializerManager); + } + + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.Format(SR.OnlyDataContractAndXmlSerializerTypesInUnWrappedMode, operation.Name))); + } + + public static SingleBodyParameterMessageFormatter CreateJsonFormatter(OperationDescription operation, Type type, bool isRequestFormatter) + { + DataContractSerializerOperationBehavior dcsob = ((KeyedByTypeCollection)operation.OperationBehaviors).Find(); + if (dcsob == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.JsonFormatRequiresDataContract, operation.Name, operation.DeclaringContract.Name, operation.DeclaringContract.Namespace))); + } + + return new SingleBodyParameterDataContractMessageFormatter(operation, type, isRequestFormatter, true, dcsob); + } + + private BodyWriter CreateBodyWriter(object body) + { + XmlObjectSerializer serializer; + if (body != null) + { + serializer = GetOutputSerializer(body.GetType()); + if (serializer == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.Format(SR.CannotSerializeType, body.GetType(), OperationName, ContractName, ContractNs, _serializerType))); + } + } + else + { + serializer = null; + } + + return new SingleParameterBodyWriter(body, serializer); + } + + protected virtual object ReadObject(Message message) + { + if (HttpStreamFormatter.IsEmptyMessage(message)) + { + return null; + } + + XmlObjectSerializer[] inputSerializers = GetInputSerializers(); + XmlDictionaryReader reader = message.GetReaderAtBodyContents(); + if (inputSerializers != null) + { + for (int i = 0; i < inputSerializers.Length; ++i) + { + if (inputSerializers[i].IsStartObject(reader)) + { + return inputSerializers[i].ReadObject(reader, false); + } + } + } + + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SerializationException(SR.Format(SR.CannotDeserializeBody, reader.LocalName, reader.NamespaceURI, OperationName, ContractName, ContractNs, _serializerType))); + } + + internal class NullMessageFormatter : IDispatchMessageFormatter, IClientMessageFormatter + { + public void DeserializeRequest(Message message, object[] parameters) + { + } + + public Message SerializeReply(MessageVersion messageVersion, object[] parameters, object result) + { + Message reply = Message.CreateMessage(messageVersion, (string)null); + SuppressReplyEntityBody(reply); + + return reply; + } + + public object DeserializeReply(Message message, object[] parameters) + { + return null; + } + + public Message SerializeRequest(MessageVersion messageVersion, object[] parameters) + { + Message request = Message.CreateMessage(messageVersion, (string)null); + SuppressRequestEntityBody(request); + return request; + } + } + + internal class SingleParameterBodyWriter : BodyWriter + { + private readonly object _body; + private readonly XmlObjectSerializer _serializer; + + public SingleParameterBodyWriter(object body, XmlObjectSerializer serializer) + : base(false) + { + if (body != null && serializer == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(serializer)); + } + + _body = body; + _serializer = serializer; + } + + protected override void OnWriteBodyContents(XmlDictionaryWriter writer) + { + if (_body != null) + { + _serializer.WriteObject(writer, _body); + } + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/SingleBodyParameterXmlSerializerMessageFormatter.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/SingleBodyParameterXmlSerializerMessageFormatter.cs new file mode 100644 index 00000000000..a62d897555d --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/SingleBodyParameterXmlSerializerMessageFormatter.cs @@ -0,0 +1,116 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.ServiceModel.Description; + +namespace System.ServiceModel.Dispatcher +{ + internal class SingleBodyParameterXmlSerializerMessageFormatter : SingleBodyParameterMessageFormatter + { + private XmlObjectSerializer _cachedOutputSerializer; + private Type _cachedOutputSerializerType; + private readonly List _knownTypes; + private readonly Type _parameterType; + private readonly UnwrappedTypesXmlSerializerManager _serializerManager; + private XmlObjectSerializer[] _serializers; + private readonly object _thisLock; + private UnwrappedTypesXmlSerializerManager.TypeSerializerPair[] _typeSerializerPairs; + + public SingleBodyParameterXmlSerializerMessageFormatter(OperationDescription operation, Type parameterType, bool isRequestFormatter, XmlSerializerOperationBehavior xsob, UnwrappedTypesXmlSerializerManager serializerManager) + : base(operation, isRequestFormatter, "XmlSerializer") + { + if (operation == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(operation)); + } + + if (xsob == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(xsob)); + } + + _serializerManager = serializerManager ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(serializerManager)); + _parameterType = parameterType ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(parameterType)); + List operationTypes = new List(); + operationTypes.Add(parameterType); + _knownTypes = new List(); + if (operation.KnownTypes != null) + { + foreach (Type knownType in operation.KnownTypes) + { + _knownTypes.Add(knownType); + operationTypes.Add(knownType); + } + } + + Type nullableType = SingleBodyParameterDataContractMessageFormatter.UnwrapNullableType(_parameterType); + if (nullableType != _parameterType) + { + _knownTypes.Add(nullableType); + operationTypes.Add(nullableType); + } + + _serializerManager.RegisterType(this, operationTypes); + _thisLock = new object(); + } + + protected override XmlObjectSerializer[] GetInputSerializers() + { + lock (_thisLock) + { + EnsureSerializers(); + return _serializers; + } + } + + protected override XmlObjectSerializer GetOutputSerializer(Type type) + { + lock (_thisLock) + { + if (_cachedOutputSerializerType != type) + { + Type typeForSerializer = GetTypeForSerializer(type, _parameterType, _knownTypes); + EnsureSerializers(); + bool foundSerializer = false; + if (_typeSerializerPairs != null) + { + for (int i = 0; i < _typeSerializerPairs.Length; ++i) + { + if (typeForSerializer == _typeSerializerPairs[i].Type) + { + _cachedOutputSerializer = _typeSerializerPairs[i].Serializer; + _cachedOutputSerializerType = type; + foundSerializer = true; + break; + } + } + } + + if (!foundSerializer) + { + return null; + } + } + + return _cachedOutputSerializer; + } + } + + // must be called under a lock + private void EnsureSerializers() + { + if (_typeSerializerPairs == null) + { + _typeSerializerPairs = _serializerManager.GetOperationSerializers(this); + _serializers = new XmlObjectSerializer[_typeSerializerPairs.Length]; + for (int i = 0; i < _typeSerializerPairs.Length; ++i) + { + _serializers[i] = _typeSerializerPairs[i].Serializer; + } + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/UnwrappedTypesXmlSerializerManager.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/UnwrappedTypesXmlSerializerManager.cs new file mode 100644 index 00000000000..9503d595782 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/UnwrappedTypesXmlSerializerManager.cs @@ -0,0 +1,159 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using System.Xml; +using System.Xml.Serialization; +using System.Runtime; + +namespace System.ServiceModel.Dispatcher +{ + internal class UnwrappedTypesXmlSerializerManager + { + private readonly Dictionary _allTypes; + private readonly XmlReflectionImporter _importer; + private readonly Dictionary> _operationTypes; + private bool _serializersCreated; + private readonly Dictionary _serializersMap; + private readonly object _thisLock; + + public UnwrappedTypesXmlSerializerManager() + { + _allTypes = new Dictionary(); + _serializersMap = new Dictionary(); + _operationTypes = new Dictionary>(); + _importer = new XmlReflectionImporter(); + _thisLock = new object(); + } + + public TypeSerializerPair[] GetOperationSerializers(object key) + { + if (key == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(key)); + } + + lock (_thisLock) + { + if (!_serializersCreated) + { + BuildSerializers(); + _serializersCreated = true; + } + + List serializers = new List(); + IList operationTypes = _operationTypes[key]; + for (int i = 0; i < operationTypes.Count; ++i) + { + TypeSerializerPair pair = new TypeSerializerPair + { + Type = operationTypes[i], + Serializer = new XmlSerializerXmlObjectSerializer(_serializersMap[operationTypes[i]]) + }; + serializers.Add(pair); + } + + return serializers.ToArray(); + } + } + + public void RegisterType(object key, IList types) + { + if (key == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(key)); + } + + if (types == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(types)); + } + + lock (_thisLock) + { + if (_serializersCreated) + { + Fx.Assert("An xml serializer type was added after the serializers were created"); + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format(SR.XmlSerializersCreatedBeforeRegistration))); + } + + for (int i = 0; i < types.Count; ++i) + { + if (!_allTypes.ContainsKey(types[i])) + { + _allTypes.Add(types[i], _importer.ImportTypeMapping(types[i])); + } + } + + _operationTypes.Add(key, types); + } + } + + private void BuildSerializers() + { + List types = new List(); + List mappings = new List(); + foreach (Type type in _allTypes.Keys) + { + XmlTypeMapping mapping = _allTypes[type]; + types.Add(type); + mappings.Add(mapping); + } + + XmlSerializer[] serializers = XmlSerializer.FromMappings(mappings.ToArray()); + for (int i = 0; i < types.Count; ++i) + { + _serializersMap.Add(types[i], serializers[i]); + } + } + + public struct TypeSerializerPair + { + public XmlObjectSerializer Serializer; + + public Type Type; + } + + internal class XmlSerializerXmlObjectSerializer : XmlObjectSerializer + { + private readonly XmlSerializer _serializer; + + public XmlSerializerXmlObjectSerializer(XmlSerializer serializer) + { + _serializer = serializer ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(serializer)); + } + + public override bool IsStartObject(XmlDictionaryReader reader) => _serializer.CanDeserialize(reader); + + public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName) => _serializer.Deserialize(reader); + + public override void WriteEndObject(XmlDictionaryWriter writer) + { + Fx.Assert("This method should never get hit"); + + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); + } + + public override void WriteObject(XmlDictionaryWriter writer, object graph) + { + _serializer.Serialize(writer, graph); + } + + public override void WriteObjectContent(XmlDictionaryWriter writer, object graph) + { + Fx.Assert("This method should never get hit"); + + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); + } + + public override void WriteStartObject(XmlDictionaryWriter writer, object graph) + { + Fx.Assert("This method should never get hit"); + + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/UriTemplateClientFormatter.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/UriTemplateClientFormatter.cs new file mode 100644 index 00000000000..f394e1d9889 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/UriTemplateClientFormatter.cs @@ -0,0 +1,227 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#pragma warning disable 1634, 1691 +namespace System.ServiceModel.Dispatcher +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Collections.Specialized; + using System.Globalization; + using System.Reflection; + using System.ServiceModel; + using System.ServiceModel.Channels; + using System.ServiceModel.Description; + using System.Text; + using System.Xml; + using System.ServiceModel.Web; + + internal class UriTemplateClientFormatter : IClientMessageFormatter + { + internal Dictionary pathMapping; + internal Dictionary> queryMapping; + Uri baseUri; + IClientMessageFormatter inner; + bool innerIsUntypedMessage; + bool isGet; + string method; + QueryStringConverter qsc; + int totalNumUTVars; + UriTemplate uriTemplate; + + public UriTemplateClientFormatter(OperationDescription operationDescription, IClientMessageFormatter inner, QueryStringConverter qsc, Uri baseUri, bool innerIsUntypedMessage, string contractName) + { + this.inner = inner; + this.qsc = qsc; + this.baseUri = baseUri; + this.innerIsUntypedMessage = innerIsUntypedMessage; + Populate(out this.pathMapping, + out this.queryMapping, + out this.totalNumUTVars, + out this.uriTemplate, + operationDescription, + qsc, + contractName); + this.method = WebHttpBehavior.GetWebMethod(operationDescription); + isGet = this.method == WebHttpBehavior.GET; + } + + public object DeserializeReply(Message message, object[] parameters) + { + // The URI template formatter is purely a request-side concern: it binds + // operation parameters into the outgoing URI. Reply deserialization is + // delegated to the inner formatter. + if (inner != null) + { + return inner.DeserializeReply(message, parameters); + } + return null; + } + + public Message SerializeRequest(MessageVersion messageVersion, object[] parameters) + { + object[] innerParameters = new object[parameters.Length - this.totalNumUTVars]; + NameValueCollection nvc = new NameValueCollection(); + int j = 0; + for (int i = 0; i < parameters.Length; ++i) + { + if (this.pathMapping.ContainsKey(i)) + { + nvc[this.pathMapping[i]] = parameters[i] as string; + } + else if (this.queryMapping.ContainsKey(i)) + { + if (parameters[i] != null) + { + nvc[this.queryMapping[i].Key] = this.qsc.ConvertValueToString(parameters[i], this.queryMapping[i].Value); + } + } + else + { + innerParameters[j] = parameters[i]; + ++j; + } + } + Message m = inner.SerializeRequest(messageVersion, innerParameters); + bool userSetTheToOnMessage = (this.innerIsUntypedMessage && m.Headers.To != null); + bool userSetTheToOnOutgoingHeaders = (OperationContext.Current != null && OperationContext.Current.OutgoingMessageHeaders.To != null); + if (!userSetTheToOnMessage && !userSetTheToOnOutgoingHeaders) + { + m.Headers.To = this.uriTemplate.BindByName(this.baseUri, nvc); + } + // dotnet/wcf's HttpRequestMessageProperty exposes SuppressEntityBody and Method + // (server-only HttpResponseMessageProperty does not). Set them here rather than + // routing through WebOperationContext (which is optional and may not be set up). + HttpRequestMessageProperty hrmp; + if (m.Properties.ContainsKey(HttpRequestMessageProperty.Name)) + { + hrmp = m.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty; + } + else + { + hrmp = new HttpRequestMessageProperty(); + m.Properties.Add(HttpRequestMessageProperty.Name, hrmp); + } + if (isGet) + { + hrmp.SuppressEntityBody = true; + } + if (this.method != WebHttpBehavior.WildcardMethod) + { + hrmp.Method = this.method; + } + return m; + } + + internal static string GetUTStringOrDefault(OperationDescription operationDescription) + { + string utString = WebHttpBehavior.GetWebUriTemplate(operationDescription); + if (utString == null && WebHttpBehavior.GetWebMethod(operationDescription) == WebHttpBehavior.GET) + { + utString = MakeDefaultGetUTString(operationDescription); + } + + if (utString == null) + { + utString = operationDescription.Name; // note: not + "/*", see 8988 and 9653 + } + + return utString; + } + + internal static void Populate(out Dictionary pathMapping, + out Dictionary> queryMapping, + out int totalNumUTVars, + out UriTemplate uriTemplate, + OperationDescription operationDescription, + QueryStringConverter qsc, + string contractName) + { + pathMapping = new Dictionary(); + queryMapping = new Dictionary>(); + string utString = GetUTStringOrDefault(operationDescription); + uriTemplate = new UriTemplate(utString); + List neededPathVars = new List(uriTemplate.PathSegmentVariableNames); + List neededQueryVars = new List(uriTemplate.QueryValueVariableNames); + Dictionary alreadyGotVars = new Dictionary(StringComparer.OrdinalIgnoreCase); + totalNumUTVars = neededPathVars.Count + neededQueryVars.Count; + for (int i = 0; i < operationDescription.Messages[0].Body.Parts.Count; ++i) + { + MessagePartDescription mpd = operationDescription.Messages[0].Body.Parts[i]; + string parameterName = XmlConvert.DecodeName(mpd.Name); + if (alreadyGotVars.ContainsKey(parameterName)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UriTemplateVarCaseDistinction, XmlConvert.DecodeName(operationDescription.Name), contractName, parameterName))); + } + + List neededPathCopy = new List(neededPathVars); + foreach (string pathVar in neededPathCopy) + { + if (string.Compare(parameterName, pathVar, StringComparison.OrdinalIgnoreCase) == 0) + { + if (mpd.Type != typeof(string)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UriTemplatePathVarMustBeString, XmlConvert.DecodeName(operationDescription.Name), contractName, parameterName))); + } + pathMapping.Add(i, parameterName); + alreadyGotVars.Add(parameterName, 0); + neededPathVars.Remove(pathVar); + } + } + + List neededQueryCopy = new List(neededQueryVars); + foreach (string queryVar in neededQueryCopy) + { + if (string.Compare(parameterName, queryVar, StringComparison.OrdinalIgnoreCase) == 0) + { + if (!qsc.CanConvert(mpd.Type)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UriTemplateQueryVarMustBeConvertible, XmlConvert.DecodeName(operationDescription.Name), contractName, parameterName, mpd.Type, qsc.GetType().Name))); + } + queryMapping.Add(i, new KeyValuePair(parameterName, mpd.Type)); + alreadyGotVars.Add(parameterName, 0); + neededQueryVars.Remove(queryVar); + } + } + } + + if (neededPathVars.Count != 0) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UriTemplateMissingVar, XmlConvert.DecodeName(operationDescription.Name), contractName, neededPathVars[0]))); + } + + if (neededQueryVars.Count != 0) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UriTemplateMissingVar, XmlConvert.DecodeName(operationDescription.Name), contractName, neededQueryVars[0]))); + } + } + + private static string MakeDefaultGetUTString(OperationDescription od) + { + StringBuilder sb = new StringBuilder(XmlConvert.DecodeName(od.Name)); + //sb.Append("/*"); // note: not + "/*", see 8988 and 9653 + if (!WebHttpBehavior.IsUntypedMessage(od.Messages[0])) + { + sb.Append("?"); + foreach (MessagePartDescription mpd in od.Messages[0].Body.Parts) + { + string parameterName = XmlConvert.DecodeName(mpd.Name); + sb.Append(parameterName); + sb.Append("={"); + sb.Append(parameterName); + sb.Append("}&"); + } + sb.Remove(sb.Length - 1, 1); + } + + return sb.ToString(); + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/WebFaultClientMessageInspector.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/WebFaultClientMessageInspector.cs new file mode 100644 index 00000000000..1d9b8b96503 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/WebFaultClientMessageInspector.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.ServiceModel.Dispatcher +{ + using System.Net; + using System.ServiceModel.Channels; + + // Mirrors the .NET Framework System.ServiceModel.Web WebFaultClientMessageInspector: + // if the server replied with HTTP 500, surface it as a CommunicationException on the + // client so the call site doesn't silently see an empty payload. + internal class WebFaultClientMessageInspector : IClientMessageInspector + { + public virtual void AfterReceiveReply(ref Message reply, object correlationState) + { + if (reply != null) + { + HttpResponseMessageProperty prop = reply.Properties[HttpResponseMessageProperty.Name] as HttpResponseMessageProperty; + if (prop != null && prop.StatusCode == HttpStatusCode.InternalServerError) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(prop.StatusDescription)); + } + } + } + + public object BeforeSendRequest(ref Message request, IClientChannel channel) + { + return null; + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/XmlFormatMapping.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/XmlFormatMapping.cs new file mode 100644 index 00000000000..b5173a564bb --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Dispatcher/XmlFormatMapping.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System.Collections.Generic; +using System.Text; +using System.ServiceModel.Channels; +using System.ServiceModel.Web; + +namespace System.ServiceModel.Dispatcher +{ + internal class XmlFormatMapping : MultiplexingFormatMapping + { + public static readonly WebContentFormat WebContentFormat = WebContentFormat.Xml; + + internal static readonly string s_defaultMediaType = "application/xml"; + private static readonly Dictionary s_encoders = new Dictionary(); + private static readonly object s_thisLock = new object(); + + public XmlFormatMapping(Encoding writeEncoding, WebContentTypeMapper contentTypeMapper) + : base(writeEncoding, contentTypeMapper) + { } + + public override WebContentFormat ContentFormat => WebContentFormat; + + public override WebMessageFormat MessageFormat => WebMessageFormat.Xml; + + public override string DefaultMediaType => s_defaultMediaType; + + protected override MessageEncoder Encoder + { + get + { + lock (s_thisLock) + { + if (!s_encoders.ContainsKey(writeEncoding)) + { + s_encoders[writeEncoding] = new TextMessageEncodingBindingElement(MessageVersion.None, writeEncoding).CreateMessageEncoderFactory().Encoder; + } + } + + return s_encoders[writeEncoding]; + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/HttpTransportHelpers.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/HttpTransportHelpers.cs new file mode 100644 index 00000000000..0b6b9272fcf --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/HttpTransportHelpers.cs @@ -0,0 +1,91 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Net; +using System.ServiceModel.Channels; +using System.Runtime; + +namespace System.ServiceModel +{ + internal static class HttpTransportHelpers + { + private const string DefaultRealm = ""; // HttpTransportDefaults.Realm is not exposed in dotnet/wcf; the .NET FX default is empty string. + + internal static void ConfigureTransportProtectionAndAuthentication(HttpsTransportBindingElement https, HttpTransportSecurity transportSecurity) + { + ConfigureAuthentication(https, transportSecurity); + https.RequireClientCertificate = (transportSecurity.ClientCredentialType == HttpClientCredentialType.Certificate); + } + + internal static void ConfigureTransportAuthentication(HttpTransportBindingElement http, HttpTransportSecurity transportSecurity) + { + if (transportSecurity.ClientCredentialType == HttpClientCredentialType.Certificate) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.CertificateUnsupportedForHttpTransportCredentialOnly)); + } + + ConfigureAuthentication(http, transportSecurity); + } + + internal static void DisableTransportAuthentication(HttpTransportBindingElement http) + { + DisableAuthentication(http); + } + + private static void ConfigureAuthentication(HttpTransportBindingElement http, HttpTransportSecurity transportSecurity) + { + http.AuthenticationScheme = MapToAuthenticationScheme(transportSecurity.ClientCredentialType); + // Also propagate ProxyCredentialType -> ProxyAuthenticationScheme so authenticated + // corporate proxies (Basic/Digest/Ntlm/Negotiate) work when a ProxyAddress is set on + // the binding. Mirrors HttpTransportSecurity.ConfigureAuthentication in + // System.ServiceModel.Http. HttpProxyCredentialTypeHelper is internal to + // System.ServiceModel.Http but visible to us via [InternalsVisibleTo]. + http.ProxyAuthenticationScheme = HttpProxyCredentialTypeHelper.MapToAuthenticationScheme(transportSecurity.ProxyCredentialType); + // Realm property is not exposed on dotnet/wcf's HttpTransportBindingElement / + // HttpTransportSecurity (server-side only). Skip in the client port. + http.ExtendedProtectionPolicy = transportSecurity.ExtendedProtectionPolicy; + } + + private static AuthenticationSchemes MapToAuthenticationScheme(HttpClientCredentialType clientCredentialType) + { + AuthenticationSchemes result; + switch (clientCredentialType) + { + case HttpClientCredentialType.Certificate: + // fall through to None case + case HttpClientCredentialType.None: + result = AuthenticationSchemes.Anonymous; + break; + case HttpClientCredentialType.Basic: + result = AuthenticationSchemes.Basic; + break; + case HttpClientCredentialType.Digest: + result = AuthenticationSchemes.Digest; + break; + case HttpClientCredentialType.Ntlm: + result = AuthenticationSchemes.Ntlm; + break; + case HttpClientCredentialType.Windows: + result = AuthenticationSchemes.Negotiate; + break; + case HttpClientCredentialType.InheritedFromHost: + result = AuthenticationSchemes.None; + break; + default: + Fx.Assert("unsupported client credential type"); + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); + } + return result; + } + + private static void DisableAuthentication(HttpTransportBindingElement http) + { + http.AuthenticationScheme = AuthenticationSchemes.Anonymous; + // Realm property not exposed in dotnet/wcf - see ConfigureAuthentication. + //ExtendedProtectionPolicy is always copied - even for security mode None, Message and TransportWithMessageCredential, + //because the settings for ExtendedProtectionPolicy are always below the element + //http.ExtendedProtectionPolicy = extendedProtectionPolicy; + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Pool.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Pool.cs new file mode 100644 index 00000000000..14b2311eab2 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Pool.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace System.ServiceModel +{ + // see SynchronizedPool for a threadsafe implementation + internal class Pool where T : class + { + private T[] _items; + + public Pool(int maxCount) + { + _items = new T[maxCount]; + } + + public int Count { get; private set; } + + public T Take() + { + if (Count > 0) + { + T item = _items[--Count]; + _items[Count] = null; + return item; + } + else + { + return null; + } + } + + public bool Return(T item) + { + if (Count < _items.Length) + { + _items[Count++] = item; + return true; + } + else + { + return false; + } + } + + public void Clear() + { + for (int i = 0; i < Count; i++) + { + _items[i] = null; + } + + Count = 0; + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Web/HttpDateParse.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/HttpDateParse.cs new file mode 100644 index 00000000000..7d3b2d6e079 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/HttpDateParse.cs @@ -0,0 +1,459 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Globalization; + +namespace System.ServiceModel.Web +{ + // DO NOT EDIT THIS CODE. + // + // All of the code from this class was taken from build 20717.00 + // of System.Net.HttpDateParse. If there is a bug with this code + // it should be fixed in the original System.Net.HttpDateParse + // and then ported here. [Microsoft] + + // TODO: This could likely be replaced with System.Net.HttpDateParser. + + internal static class HttpDateParse + { + private const int BASE_DEC = 10; // base 10 + + private const int DATE_1123_INDEX_DAY = 1; + private const int DATE_1123_INDEX_MONTH = 2; + private const int DATE_1123_INDEX_YEAR = 3; + private const int DATE_1123_INDEX_HRS = 4; + private const int DATE_1123_INDEX_MINS = 5; + private const int DATE_1123_INDEX_SECS = 6; + + private const int DATE_ANSI_INDEX_MONTH = 1; + private const int DATE_ANSI_INDEX_DAY = 2; + private const int DATE_ANSI_INDEX_HRS = 3; + private const int DATE_ANSI_INDEX_MINS = 4; + private const int DATE_ANSI_INDEX_SECS = 5; + private const int DATE_ANSI_INDEX_YEAR = 6; + + private const int DATE_INDEX_TZ = 7; + + private const int DATE_INDEX_LAST = DATE_INDEX_TZ; + private const int MAX_FIELD_DATE_ENTRIES = (DATE_INDEX_LAST + 1); + + // + // DATE_TOKEN's DWORD values used to determine what day/month we're on + // + + private const int DATE_TOKEN_JANUARY = 1; + private const int DATE_TOKEN_FEBRUARY = 2; + private const int DATE_TOKEN_Microsoft = 3; + private const int DATE_TOKEN_APRIL = 4; + private const int DATE_TOKEN_MAY = 5; + private const int DATE_TOKEN_JUNE = 6; + private const int DATE_TOKEN_JULY = 7; + private const int DATE_TOKEN_AUGUST = 8; + private const int DATE_TOKEN_SEPTEMBER = 9; + private const int DATE_TOKEN_OCTOBER = 10; + private const int DATE_TOKEN_NOVEMBER = 11; + private const int DATE_TOKEN_DECEMBER = 12; + private const int DATE_TOKEN_SUNDAY = 0; + private const int DATE_TOKEN_MONDAY = 1; + private const int DATE_TOKEN_TUESDAY = 2; + private const int DATE_TOKEN_WEDNESDAY = 3; + private const int DATE_TOKEN_THURSDAY = 4; + private const int DATE_TOKEN_FRIDAY = 5; + private const int DATE_TOKEN_SATURDAY = 6; + private const int DATE_TOKEN_GMT = -1000; + + private const int DATE_TOKEN_LAST = DATE_TOKEN_GMT; + + private const int DATE_TOKEN_ERROR = (DATE_TOKEN_LAST + 1); + + // + // MakeUpper - takes an assumed lower character and bit manipulates into a upper. + // (make sure the character is Lower case alpha char to begin, + // otherwise it corrupts) + // + private static char MakeUpper(char c) => char.ToUpper(c, CultureInfo.InvariantCulture); + + // Routine Description: + // + // Looks at the first three bytes of string to determine if we're looking + // at a Day of the Week, or Month, or "GMT" string. Is inlined so that + // the compiler can optimize this code into the caller FInternalParseHttpDate. + // + // Arguments: + // + // lpszDay - a string ptr to the first byte of the string in question. + // + // Return Value: + // + // DWORD + // Success - The Correct date token, 0-6 for day of the week, 1-14 for month, etc + // + // Failure - DATE_TOKEN_ERROR + private static int MapDayMonthToDword(char[] lpszDay, int index) + { + switch (MakeUpper(lpszDay[index])) + { // make uppercase + case 'A': + switch (MakeUpper(lpszDay[index + 1])) + { + case 'P': + return DATE_TOKEN_APRIL; + case 'U': + return DATE_TOKEN_AUGUST; + + } + return DATE_TOKEN_ERROR; + + case 'D': + return DATE_TOKEN_DECEMBER; + + case 'F': + switch (MakeUpper(lpszDay[index + 1])) + { + case 'R': + return DATE_TOKEN_FRIDAY; + case 'E': + return DATE_TOKEN_FEBRUARY; + } + + return DATE_TOKEN_ERROR; + + case 'G': + return DATE_TOKEN_GMT; + + case 'M': + + switch (MakeUpper(lpszDay[index + 1])) + { + case 'O': + return DATE_TOKEN_MONDAY; + case 'A': + switch (MakeUpper(lpszDay[index + 2])) + { + case 'R': + return DATE_TOKEN_Microsoft; + case 'Y': + return DATE_TOKEN_MAY; + } + + // fall through to error + break; + } + + return DATE_TOKEN_ERROR; + + case 'N': + return DATE_TOKEN_NOVEMBER; + + case 'J': + + switch (MakeUpper(lpszDay[index + 1])) + { + case 'A': + return DATE_TOKEN_JANUARY; + + case 'U': + switch (MakeUpper(lpszDay[index + 2])) + { + case 'N': + return DATE_TOKEN_JUNE; + case 'L': + return DATE_TOKEN_JULY; + } + + // fall through to error + break; + } + + return DATE_TOKEN_ERROR; + + case 'O': + return DATE_TOKEN_OCTOBER; + + case 'S': + + switch (MakeUpper(lpszDay[index + 1])) + { + case 'A': + return DATE_TOKEN_SATURDAY; + case 'U': + return DATE_TOKEN_SUNDAY; + case 'E': + return DATE_TOKEN_SEPTEMBER; + } + + return DATE_TOKEN_ERROR; + + + case 'T': + switch (MakeUpper(lpszDay[index + 1])) + { + case 'U': + return DATE_TOKEN_TUESDAY; + case 'H': + return DATE_TOKEN_THURSDAY; + } + + return DATE_TOKEN_ERROR; + + case 'U': + return DATE_TOKEN_GMT; + + case 'W': + return DATE_TOKEN_WEDNESDAY; + + } + + return DATE_TOKEN_ERROR; + } + + + // Routine Description: + // + // Parses through a ANSI, RFC850, or RFC1123 date format and covents it into + // a FILETIME/SYSTEMTIME time format. + // + // Important this a time-critical function and should only be changed + // with the intention of optimizing or a critical need work item. + // + // Arguments: + // + // lpft - Ptr to FILETIME structure. Used to store converted result. + // Must be NULL if not intended to be used !!! + // + // lpSysTime - Ptr to SYSTEMTIME struture. Used to return Systime if needed. + // + // lpcszDateStr - Const Date string to parse. + // + // Return Value: + // + // BOOL + // Success - TRUE + // Failure - FALSE + internal static bool ParseHttpDate(string DateString, out DateTime dtOut) + { + int index = 0; + int i = 0, iLastLettered = -1; + bool fIsANSIDateFormat = false; + int[] rgdwDateParseResults = new int[MAX_FIELD_DATE_ENTRIES]; + bool fRet = true; + char[] lpInputBuffer = DateString.ToCharArray(); + + dtOut = new DateTime(); + + // + // Date Parsing v2 (1 more to go), and here is how it works... + // We take a date string and churn through it once, converting + // integers to integers, Month,Day, and GMT strings into integers, + // and all is then placed IN order in a temp array. + // + // At the completetion of the parse stage, we simple look at + // the data, and then map the results into the correct + // places in the SYSTIME structure. Simple, No allocations, and + // No dirting the data. + // + // The end of the function does something munging and pretting + // up of the results to handle the year 2000, and TZ offsets + // Note: do we need to fully handle TZs anymore? + // + + while (index < DateString.Length && i < MAX_FIELD_DATE_ENTRIES) + { + if (lpInputBuffer[index] >= '0' && lpInputBuffer[index] <= '9') + { + // + // we have a numerical entry, scan through it and convent to DWORD + // + + rgdwDateParseResults[i] = 0; + + do + { + rgdwDateParseResults[i] *= BASE_DEC; + rgdwDateParseResults[i] += (lpInputBuffer[index] - '0'); + index++; + } while (index < DateString.Length && + lpInputBuffer[index] >= '0' && + lpInputBuffer[index] <= '9'); + + i++; // next token + } + else if ((lpInputBuffer[index] >= 'A' && lpInputBuffer[index] <= 'Z') || + (lpInputBuffer[index] >= 'a' && lpInputBuffer[index] <= 'z')) + { + // + // we have a string, should be a day, month, or GMT + // lets skim to the end of the string + // + + rgdwDateParseResults[i] = + MapDayMonthToDword(lpInputBuffer, index); + + iLastLettered = i; + + // We want to ignore the possibility of a time zone such as PST or EST in a non-standard + // date format such as "Thu Dec 17 16:01:28 PST 1998" (Notice that the year is _after_ the time zone + if ((rgdwDateParseResults[i] == DATE_TOKEN_ERROR) + && + !(fIsANSIDateFormat && (i == DATE_ANSI_INDEX_YEAR))) + { + fRet = false; + goto quit; + } + + // + // At this point if we have a vaild string + // at this index, we know for sure that we're + // looking at a ANSI type DATE format. + // + + if (i == DATE_ANSI_INDEX_MONTH) + { + fIsANSIDateFormat = true; + } + + // + // Read past the end of the current set of alpha characters, + // as MapDayMonthToDword only peeks at a few characters + // + + do + { + index++; + } while (index < DateString.Length && + ((lpInputBuffer[index] >= 'A' && lpInputBuffer[index] <= 'Z') || + (lpInputBuffer[index] >= 'a' && lpInputBuffer[index] <= 'z'))); + + i++; // next token + } + else + { + // + // For the generic case its either a space, comma, semi-colon, etc. + // the point is we really don't care, nor do we need to waste time + // worring about it (the orginal code did). The point is we + // care about the actual date information, So we just advance to the + // next lexume. + // + + index++; + } + } + + // + // We're finished parsing the string, now take the parsed tokens + // and turn them to the actual structured information we care about. + // So we build lpSysTime from the Array, using a local if none is passed in. + // + + int year; + int month; + int day; + int hour; + int minute; + int second; + int millisecond; + + millisecond = 0; + + if (fIsANSIDateFormat) + { + day = rgdwDateParseResults[DATE_ANSI_INDEX_DAY]; + month = rgdwDateParseResults[DATE_ANSI_INDEX_MONTH]; + hour = rgdwDateParseResults[DATE_ANSI_INDEX_HRS]; + minute = rgdwDateParseResults[DATE_ANSI_INDEX_MINS]; + second = rgdwDateParseResults[DATE_ANSI_INDEX_SECS]; + if (iLastLettered != DATE_ANSI_INDEX_YEAR) + { + year = rgdwDateParseResults[DATE_ANSI_INDEX_YEAR]; + } + else + { + // This is a fix to get around toString/toGMTstring (where the timezone is + // appended at the end. (See above) + year = rgdwDateParseResults[DATE_INDEX_TZ]; + } + } + else + { + day = rgdwDateParseResults[DATE_1123_INDEX_DAY]; + month = rgdwDateParseResults[DATE_1123_INDEX_MONTH]; + year = rgdwDateParseResults[DATE_1123_INDEX_YEAR]; + hour = rgdwDateParseResults[DATE_1123_INDEX_HRS]; + minute = rgdwDateParseResults[DATE_1123_INDEX_MINS]; + second = rgdwDateParseResults[DATE_1123_INDEX_SECS]; + } + + // + // Normalize the year, 90 == 1990, handle the year 2000, 02 == 2002 + // This is Year 2000 handling folks!!! We get this wrong and + // we all look bad. + // + + if (year < 100) + { + year += ((year < 80) ? 2000 : 1900); + } + + // + // if we got misformed time, then plug in the current time + // !lpszHrs || !lpszMins || !lpszSec + // + + if ((i < 4) + || (day > 31) + || (hour > 23) + || (minute > 59) + || (second > 59)) + { + fRet = false; + goto quit; + } + + // + // Now do the DateTime conversion + // + + dtOut = new DateTime(year, month, day, hour, minute, second, millisecond); + + // + // we want the system time to be accurate. This is _suhlow_ + // The time passed in is in the local time zone; we have to convert this into GMT. + // + + if (iLastLettered == DATE_ANSI_INDEX_YEAR) + { + // this should be an unusual case. + dtOut = dtOut.ToUniversalTime(); + } + + // + // If we have an Offset to another Time Zone + // then convert to appropriate GMT time + // + + if ((i > DATE_INDEX_TZ && + rgdwDateParseResults[DATE_INDEX_TZ] != DATE_TOKEN_GMT)) + { + + // + // if we received +/-nnnn as offset (hhmm), modify the output FILETIME + // + + double offset; + + offset = (double)rgdwDateParseResults[DATE_INDEX_TZ]; + dtOut.AddHours(offset); + } + + // In the end, we leave it all in LocalTime + + dtOut = dtOut.ToLocalTime(); + + quit: + + return fRet; + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Web/IWebFaultException.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/IWebFaultException.cs new file mode 100644 index 00000000000..9450ace344f --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/IWebFaultException.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Net; + +namespace System.ServiceModel.Web +{ + internal interface IWebFaultException + { + HttpStatusCode StatusCode { get; } + + Type DetailType { get; } + + object DetailObject { get; } + + Type[] KnownTypes { get; } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Web/IncomingWebRequestContext.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/IncomingWebRequestContext.cs new file mode 100644 index 00000000000..20c17d08630 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/IncomingWebRequestContext.cs @@ -0,0 +1,436 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Net; +using System.Net.Mime; +using System.ServiceModel.Channels; +using System.Runtime; + +namespace System.ServiceModel.Web +{ + public class IncomingWebRequestContext + { + private static readonly string s_httpGetMethod = "GET"; + private static readonly string s_httpHeadMethod = "HEAD"; + private static readonly string s_httpPutMethod = "PUT"; + private static readonly string s_httpPostMethod = "POST"; + private static readonly string s_httpDeleteMethod = "DELETE"; + + private Collection _cachedAcceptHeaderElements; + private string _acceptHeaderWhenHeaderElementsCached; + private readonly OperationContext _operationContext; + + internal const string UriTemplateMatchResultsPropertyName = "UriTemplateMatchResults"; + + internal IncomingWebRequestContext(OperationContext operationContext) + { + Fx.Assert(operationContext != null, "operationContext is null"); + _operationContext = operationContext; + } + + public string Accept => EnsureMessageProperty().Headers[HttpRequestHeader.Accept]; + + public long ContentLength => long.Parse(EnsureMessageProperty().Headers[HttpRequestHeader.ContentLength], CultureInfo.InvariantCulture); + + public string ContentType => EnsureMessageProperty().Headers[HttpRequestHeader.ContentType]; + + public IEnumerable IfMatch + { + get + { + string ifMatchHeader = MessageProperty.Headers[HttpRequestHeader.IfMatch]; + return (string.IsNullOrEmpty(ifMatchHeader)) ? null : Utility.QuoteAwareStringSplit(ifMatchHeader); + } + } + + public IEnumerable IfNoneMatch + { + get + { + string ifNoneMatchHeader = MessageProperty.Headers[HttpRequestHeader.IfNoneMatch]; + return (string.IsNullOrEmpty(ifNoneMatchHeader)) ? null : Utility.QuoteAwareStringSplit(ifNoneMatchHeader); + } + } + + public DateTime? IfModifiedSince + { + get + { + string dateTime = this.MessageProperty.Headers[HttpRequestHeader.IfModifiedSince]; + if (!string.IsNullOrEmpty(dateTime)) + { + if (HttpDateParse.ParseHttpDate(dateTime, out DateTime parsedDateTime)) + { + return parsedDateTime; + } + } + + return null; + } + } + + public DateTime? IfUnmodifiedSince + { + get + { + string dateTime = MessageProperty.Headers[HttpRequestHeader.IfUnmodifiedSince]; + if (!string.IsNullOrEmpty(dateTime)) + { + if (HttpDateParse.ParseHttpDate(dateTime, out DateTime parsedDateTime)) + { + return parsedDateTime; + } + } + + return null; + } + } + + public WebHeaderCollection Headers => EnsureMessageProperty().Headers; + + public string Method => EnsureMessageProperty().Method; + + public UriTemplateMatch UriTemplateMatch + { + get + { + if (_operationContext.IncomingMessageProperties.ContainsKey(UriTemplateMatchResultsPropertyName)) + { + return _operationContext.IncomingMessageProperties[UriTemplateMatchResultsPropertyName] as UriTemplateMatch; + } + else + { + return null; + } + } + set + { + _operationContext.IncomingMessageProperties[UriTemplateMatchResultsPropertyName] = value; + } + } + + public string UserAgent => EnsureMessageProperty().Headers[HttpRequestHeader.UserAgent]; + + private HttpRequestMessageProperty MessageProperty + { + get + { + if (_operationContext.IncomingMessageProperties == null) + { + return null; + } + + if (!_operationContext.IncomingMessageProperties.ContainsKey(HttpRequestMessageProperty.Name)) + { + return null; + } + + return _operationContext.IncomingMessageProperties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty; + } + } + + public void CheckConditionalRetrieve(string entityTag) + { + string validEtag = OutgoingWebResponseContext.GenerateValidEtagFromString(entityTag); + CheckConditionalRetrieveWithValidatedEtag(validEtag); + } + + public void CheckConditionalRetrieve(int entityTag) + { + string validEtag = OutgoingWebResponseContext.GenerateValidEtag(entityTag); + CheckConditionalRetrieveWithValidatedEtag(validEtag); + } + + public void CheckConditionalRetrieve(long entityTag) + { + string validEtag = OutgoingWebResponseContext.GenerateValidEtag(entityTag); + CheckConditionalRetrieveWithValidatedEtag(validEtag); + } + + public void CheckConditionalRetrieve(Guid entityTag) + { + string validEtag = OutgoingWebResponseContext.GenerateValidEtag(entityTag); + CheckConditionalRetrieveWithValidatedEtag(validEtag); + } + + public void CheckConditionalRetrieve(DateTime lastModified) + { + if (!string.Equals(Method, s_httpGetMethod, StringComparison.OrdinalIgnoreCase) && + !string.Equals(Method, s_httpHeadMethod, StringComparison.OrdinalIgnoreCase)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.ConditionalRetrieveGetAndHeadOnly, Method))); + } + + DateTime? ifModifiedSince = IfModifiedSince; + if (ifModifiedSince.HasValue) + { + long ticksDifference = lastModified.ToUniversalTime().Ticks - ifModifiedSince.Value.ToUniversalTime().Ticks; + if (ticksDifference < TimeSpan.TicksPerSecond) + { + WebOperationContext.Current.OutgoingResponse.LastModified = lastModified; + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new WebFaultException(HttpStatusCode.NotModified)); + } + } + } + + public void CheckConditionalUpdate(string entityTag) + { + string validEtag = OutgoingWebResponseContext.GenerateValidEtagFromString(entityTag); + CheckConditionalUpdateWithValidatedEtag(validEtag); + } + + public void CheckConditionalUpdate(int entityTag) + { + string validEtag = OutgoingWebResponseContext.GenerateValidEtag(entityTag); + CheckConditionalUpdateWithValidatedEtag(validEtag); + } + + public void CheckConditionalUpdate(long entityTag) + { + string validEtag = OutgoingWebResponseContext.GenerateValidEtag(entityTag); + CheckConditionalUpdateWithValidatedEtag(validEtag); + } + + public void CheckConditionalUpdate(Guid entityTag) + { + string validEtag = OutgoingWebResponseContext.GenerateValidEtag(entityTag); + CheckConditionalUpdateWithValidatedEtag(validEtag); + } + + public Collection GetAcceptHeaderElements() + { + string acceptHeader = Accept; + if (_cachedAcceptHeaderElements == null || + (!string.Equals(_acceptHeaderWhenHeaderElementsCached, acceptHeader, StringComparison.OrdinalIgnoreCase))) + { + if (string.IsNullOrEmpty(acceptHeader)) + { + _cachedAcceptHeaderElements = new Collection(); + _acceptHeaderWhenHeaderElementsCached = acceptHeader; + } + else + { + List contentTypeList = new List(); + int offset = 0; + while (true) + { + string nextItem = Utility.QuoteAwareSubString(acceptHeader, ref offset); + if (nextItem == null) + { + break; + } + + ContentType contentType = Utility.GetContentTypeOrNull(nextItem); + if (contentType != null) + { + contentTypeList.Add(contentType); + } + } + + contentTypeList.Sort(new AcceptHeaderElementComparer()); + _cachedAcceptHeaderElements = new Collection(contentTypeList); + _acceptHeaderWhenHeaderElementsCached = acceptHeader; + } + } + + return _cachedAcceptHeaderElements; + } + + private HttpRequestMessageProperty EnsureMessageProperty() + { + if (MessageProperty == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.HttpContextNoIncomingMessageProperty, typeof(HttpRequestMessageProperty).Name))); + } + + return MessageProperty; + } + + + private void CheckConditionalRetrieveWithValidatedEtag(string entityTag) + { + if (!string.Equals(Method, s_httpGetMethod, StringComparison.OrdinalIgnoreCase) && + !string.Equals(Method, s_httpHeadMethod, StringComparison.OrdinalIgnoreCase)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.ConditionalRetrieveGetAndHeadOnly, Method))); + } + + if (!string.IsNullOrEmpty(entityTag)) + { + string entityTagHeader = Headers[HttpRequestHeader.IfNoneMatch]; + if (!string.IsNullOrEmpty(entityTagHeader)) + { + if (IsWildCardCharacter(entityTagHeader) || + DoesHeaderContainEtag(entityTagHeader, entityTag)) + { + // set response entityTag directly because it has already been validated + WebOperationContext.Current.OutgoingResponse.ETag = entityTag; + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new WebFaultException(HttpStatusCode.NotModified)); + } + } + } + } + + private void CheckConditionalUpdateWithValidatedEtag(string entityTag) + { + bool isPutMethod = string.Equals(Method, s_httpPutMethod, StringComparison.OrdinalIgnoreCase); + if (!isPutMethod && + !string.Equals(Method, s_httpPostMethod, StringComparison.OrdinalIgnoreCase) && + !string.Equals(Method, s_httpDeleteMethod, StringComparison.OrdinalIgnoreCase)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.ConditionalUpdatePutPostAndDeleteOnly, Method))); + } + + string headerOfInterest; + + // if the current entityTag is null then the resource doesn't currently exist and the + // a PUT request should only succeed if If-None-Match equals '*'. + if (isPutMethod && string.IsNullOrEmpty(entityTag)) + { + headerOfInterest = Headers[HttpRequestHeader.IfNoneMatch]; + if (string.IsNullOrEmpty(headerOfInterest) || + !IsWildCardCharacter(headerOfInterest)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new WebFaultException(HttpStatusCode.PreconditionFailed)); + } + } + else + { + // all remaining cases are with an If-Match header + headerOfInterest = Headers[HttpRequestHeader.IfMatch]; + if (string.IsNullOrEmpty(headerOfInterest) || + (!IsWildCardCharacter(headerOfInterest) && + !DoesHeaderContainEtag(headerOfInterest, entityTag))) + { + // set response entityTag directly because it has already been validated + WebOperationContext.Current.OutgoingResponse.ETag = entityTag; + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new WebFaultException(HttpStatusCode.PreconditionFailed)); + } + } + } + + private static bool DoesHeaderContainEtag(string header, string entityTag) + { + int offset = 0; + while (true) + { + string nextEntityTag = Utility.QuoteAwareSubString(header, ref offset); + if (nextEntityTag == null) + { + break; + } + + if (string.Equals(nextEntityTag, entityTag, StringComparison.Ordinal)) + { + return true; + } + } + + return false; + } + + private static bool IsWildCardCharacter(string header) => header.Trim() == "*"; + } + + internal class AcceptHeaderElementComparer : IComparer + { + private static readonly NumberStyles s_numberStyles = NumberStyles.AllowDecimalPoint; + + public int Compare(ContentType x, ContentType y) + { + string[] xTypeSubType = x.MediaType.Split('/'); + string[] yTypeSubType = y.MediaType.Split('/'); + + Fx.Assert(xTypeSubType.Length == 2, "The creation of the ContentType would have failed if there wasn't a type and subtype."); + Fx.Assert(yTypeSubType.Length == 2, "The creation of the ContentType would have failed if there wasn't a type and subtype."); + + if (string.Equals(xTypeSubType[0], yTypeSubType[0], StringComparison.OrdinalIgnoreCase)) + { + if (string.Equals(xTypeSubType[1], yTypeSubType[1], StringComparison.OrdinalIgnoreCase)) + { + // need to check the number of parameters to determine which is more specific + bool xHasParam = HasParameters(x); + bool yHasParam = HasParameters(y); + if (xHasParam && !yHasParam) + { + return 1; + } + else if (!xHasParam && yHasParam) + { + return -1; + } + } + else + { + if (xTypeSubType[1][0] == '*' && xTypeSubType[1].Length == 1) + { + return 1; + } + if (yTypeSubType[1][0] == '*' && yTypeSubType[1].Length == 1) + { + return -1; + } + } + } + else if (xTypeSubType[0][0] == '*' && xTypeSubType[0].Length == 1) + { + return 1; + } + else if (yTypeSubType[0][0] == '*' && yTypeSubType[0].Length == 1) + { + return -1; + } + + decimal qualityDifference = GetQualityFactor(x) - GetQualityFactor(y); + if (qualityDifference < 0) + { + return 1; + } + else if (qualityDifference > 0) + { + return -1; + } + + return 0; + } + + private decimal GetQualityFactor(ContentType contentType) + { + foreach (string key in contentType.Parameters.Keys) + { + if (string.Equals("q", key, StringComparison.OrdinalIgnoreCase)) + { + if (decimal.TryParse(contentType.Parameters[key], s_numberStyles, CultureInfo.InvariantCulture, out decimal result) && + (result <= (decimal)1.0)) + { + return result; + } + } + } + + return (decimal)1.0; + } + + private bool HasParameters(ContentType contentType) + { + int number = 0; + foreach (string param in contentType.Parameters.Keys) + { + if (!string.Equals("q", param, StringComparison.OrdinalIgnoreCase)) + { + number++; + } + } + + return number > 0; + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Web/OutgoingWebResponseContext.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/OutgoingWebResponseContext.cs new file mode 100644 index 00000000000..90fcd7dd818 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/OutgoingWebResponseContext.cs @@ -0,0 +1,311 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Net; +using System.Text; +using System.ServiceModel.Channels; +using System.ServiceModel.Description; +using System.Runtime; + +namespace System.ServiceModel.Web +{ + public class OutgoingWebResponseContext + { + internal static readonly string s_webResponseFormatPropertyName = "WebResponseFormatProperty"; + internal static readonly string s_automatedFormatSelectionContentTypePropertyName = "AutomatedFormatSelectionContentTypePropertyName"; + + private Encoding _bindingWriteEncoding = null; + private readonly OperationContext _operationContext; + + internal OutgoingWebResponseContext(OperationContext operationContext) + { + Fx.Assert(operationContext != null, "operationContext is null"); + + _operationContext = operationContext; + } + + public long ContentLength + { + get { return long.Parse(MessageProperty.Headers[HttpResponseHeader.ContentLength], CultureInfo.InvariantCulture); } + set { MessageProperty.Headers[HttpResponseHeader.ContentLength] = value.ToString(CultureInfo.InvariantCulture); } + } + + public string ContentType + { + get { return MessageProperty.Headers[HttpResponseHeader.ContentType]; } + set { MessageProperty.Headers[HttpResponseHeader.ContentType] = value; } + } + + public string ETag + { + get { return MessageProperty.Headers[HttpResponseHeader.ETag]; } + set { MessageProperty.Headers[HttpResponseHeader.ETag] = value; } + } + + public WebHeaderCollection Headers => MessageProperty.Headers; + + public DateTime LastModified + { + get + { + string dateTime = MessageProperty.Headers[HttpRequestHeader.LastModified]; + if (!string.IsNullOrEmpty(dateTime)) + { + if (DateTime.TryParse(dateTime, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime parsedDateTime)) + { + return parsedDateTime; + } + } + + return DateTime.MinValue; + } + set + { + MessageProperty.Headers[HttpResponseHeader.LastModified] = + (value.Kind == DateTimeKind.Utc ? + value.ToString("R", CultureInfo.InvariantCulture) : + value.ToUniversalTime().ToString("R", CultureInfo.InvariantCulture)); + } + } + + public string Location + { + get { return MessageProperty.Headers[HttpResponseHeader.Location]; } + set { MessageProperty.Headers[HttpResponseHeader.Location] = value; } + } + + public HttpStatusCode StatusCode + { + get { return MessageProperty.StatusCode; } + set { MessageProperty.StatusCode = value; } + } + + public string StatusDescription + { + get { return MessageProperty.StatusDescription; } + set { MessageProperty.StatusDescription = value; } + } + + public bool SuppressEntityBody + { + // HttpResponseMessageProperty.SuppressEntityBody is not exposed in dotnet/wcf's client-only + // HttpResponseMessageProperty (it is present on HttpRequestMessageProperty). For the + // client-only port we make this property a no-op accessor; the server controls whether + // a response body is sent. + get { return false; } + set { } + } + + public WebMessageFormat? Format + { + get + { + if (!_operationContext.OutgoingMessageProperties.ContainsKey(s_webResponseFormatPropertyName)) + { + return null; + } + + return _operationContext.OutgoingMessageProperties[s_webResponseFormatPropertyName] as WebMessageFormat?; + } + set + { + if (value.HasValue) + { + if (!WebMessageFormatHelper.IsDefined(value.Value)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value))); + } + else + { + _operationContext.OutgoingMessageProperties[s_webResponseFormatPropertyName] = value.Value; + } + } + else + { + _operationContext.OutgoingMessageProperties[s_webResponseFormatPropertyName] = null; + } + + AutomatedFormatSelectionContentType = null; + } + } + + // This is an internal property because we need to carry the content-type that was selected by the FormatSelectingMessageInspector + // forward so that the formatter has access to it. However, we dond't want to use the ContentType property on this, because then + // developers would have to clear the ContentType property manually when overriding the format set by the + // FormatSelectingMessageInspector + internal string AutomatedFormatSelectionContentType + { + get + { + if (!_operationContext.OutgoingMessageProperties.ContainsKey(s_automatedFormatSelectionContentTypePropertyName)) + { + return null; + } + return _operationContext.OutgoingMessageProperties[s_automatedFormatSelectionContentTypePropertyName] as string; + } + set + { + _operationContext.OutgoingMessageProperties[s_automatedFormatSelectionContentTypePropertyName] = value; + } + } + + public Encoding BindingWriteEncoding + { + get + { + // The server-side BindingWriteEncoding logic relies on EndpointDispatcher.Id and + // OperationContext.Host (server-only types). For the client-only port we fall back to + // UTF-8, which matches the default WriteEncoding on WebMessageEncodingBindingElement. + return _bindingWriteEncoding ?? Encoding.UTF8; + } + } + + internal HttpResponseMessageProperty MessageProperty + { + get + { + if (!_operationContext.OutgoingMessageProperties.ContainsKey(HttpResponseMessageProperty.Name)) + { + _operationContext.OutgoingMessageProperties.Add(HttpResponseMessageProperty.Name, new HttpResponseMessageProperty()); + } + + return _operationContext.OutgoingMessageProperties[HttpResponseMessageProperty.Name] as HttpResponseMessageProperty; + } + } + + public void SetETag(string entityTag) + { + ETag = GenerateValidEtagFromString(entityTag); + } + + public void SetETag(int entityTag) + { + ETag = GenerateValidEtag(entityTag); + } + + public void SetETag(long entityTag) + { + ETag = GenerateValidEtag(entityTag); + } + + public void SetETag(Guid entityTag) + { + ETag = GenerateValidEtag(entityTag); + } + + public void SetStatusAsCreated(Uri locationUri) + { + if (locationUri == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(locationUri)); + } + + StatusCode = HttpStatusCode.Created; + Location = locationUri.ToString(); + } + + public void SetStatusAsNotFound() + { + StatusCode = HttpStatusCode.NotFound; + } + + public void SetStatusAsNotFound(string description) + { + StatusCode = HttpStatusCode.NotFound; + StatusDescription = description; + } + + internal static string GenerateValidEtagFromString(string entityTag) + { + // This method will generate a valid entityTag from a string by doing the following: + // 1) Adding surrounding double quotes if the string doesn't already start and end with them + // 2) Escaping any internal double quotes that aren't already escaped (preceded with a backslash) + // 3) If a string starts with a double quote but doesn't end with one, or vice-versa, then the + // double quote is considered internal and is escaped. + + if (string.IsNullOrEmpty(entityTag)) + { + return null; + } + + if (entityTag.StartsWith("W/\"", StringComparison.OrdinalIgnoreCase) && + entityTag.EndsWith("\"", StringComparison.OrdinalIgnoreCase)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.WeakEntityTagsNotSupported, entityTag))); + } + + List escapeCharacterInsertIndices = null; + int lastEtagIndex = entityTag.Length - 1; + bool startsWithQuote = entityTag[0] == '\"'; + bool endsWithQuote = entityTag[lastEtagIndex] == '\"'; + + // special case where the entityTag is a single character, a double quote, '"' + if (lastEtagIndex == 0 && startsWithQuote) + { + endsWithQuote = false; + } + + bool needsSurroundingQuotes = !startsWithQuote || !endsWithQuote; + + if (startsWithQuote && !endsWithQuote) + { + if (escapeCharacterInsertIndices == null) + { + escapeCharacterInsertIndices = new List(); + } + + escapeCharacterInsertIndices.Add(0); + } + + for (int x = 1; x < lastEtagIndex; x++) + { + if (entityTag[x] == '\"' && entityTag[x - 1] != '\\') + { + if (escapeCharacterInsertIndices == null) + { + escapeCharacterInsertIndices = new List(); + } + + escapeCharacterInsertIndices.Add(x + escapeCharacterInsertIndices.Count); + } + } + + // Possible that the ending internal quote is already escaped so must check the character before it + if (!startsWithQuote && endsWithQuote && entityTag[lastEtagIndex - 1] != '\\') + { + if (escapeCharacterInsertIndices == null) + { + escapeCharacterInsertIndices = new List(); + } + + escapeCharacterInsertIndices.Add(lastEtagIndex + escapeCharacterInsertIndices.Count); + } + + if (needsSurroundingQuotes || escapeCharacterInsertIndices != null) + { + int escapeCharacterInsertIndicesCount = (escapeCharacterInsertIndices == null) ? 0 : escapeCharacterInsertIndices.Count; + StringBuilder editedEtag = new StringBuilder(entityTag, entityTag.Length + escapeCharacterInsertIndicesCount + 2); + for (int x = 0; x < escapeCharacterInsertIndicesCount; x++) + { + editedEtag.Insert(escapeCharacterInsertIndices[x], '\\'); + } + + if (needsSurroundingQuotes) + { + editedEtag.Insert(entityTag.Length + escapeCharacterInsertIndicesCount, '\"'); + editedEtag.Insert(0, '\"'); + } + + entityTag = editedEtag.ToString(); + } + + return entityTag; + } + + internal static string GenerateValidEtag(object entityTag) => string.Format(CultureInfo.InvariantCulture, "\"{0}\"", entityTag.ToString()); + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Web/Utility.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/Utility.cs new file mode 100644 index 00000000000..4f4f36a62d2 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/Utility.cs @@ -0,0 +1,212 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Collections.Generic; +using System.Net.Mime; +using System.Text; +using System.Runtime; + +namespace System.ServiceModel.Web +{ + internal static class Utility + { + public const string ApplicationXml = "application/xml"; + public const string TextXml = "text/xml"; + public const string ApplicationJson = "application/json"; + public const string TextJson = "text/json"; + public const string GET = "GET"; + + public static bool IsXmlContent(this string contentType) + { + if (contentType == null) + { + return true; + } + + string contentTypeProcessed = contentType.Trim(); + + return contentTypeProcessed.StartsWith(ApplicationXml, StringComparison.OrdinalIgnoreCase) + || contentTypeProcessed.StartsWith(TextXml, StringComparison.OrdinalIgnoreCase); + } + + public static bool IsJsonContent(this string contentType) + { + if (contentType == null) + { + return true; + } + + string contentTypeProcessed = contentType.Trim(); + + return contentTypeProcessed.StartsWith(ApplicationJson, StringComparison.OrdinalIgnoreCase) + || contentTypeProcessed.StartsWith(TextJson, StringComparison.OrdinalIgnoreCase); + } + + public static string CombineUri(string former, string latter) + { + // Appending the latter string to the form string, + // while making sure there is a single slash char seperating the latter and the former. + // This method behaves differently than new Uri(baseUri, relativeUri) + // as CombineUri simply appends, whereas new Uri() actually replaces the last segment + // of the its base path with the relative uri. + + var builder = new StringBuilder(); + if (former.Length > 0 && latter.Length > 0) + { + if (former[former.Length - 1] == '/' && latter[0] == '/') + { + builder.Append(former, 0, former.Length - 1); + builder.Append(latter); + return builder.ToString(); + } + + if (former[former.Length - 1] != '/' && latter[0] != '/') + { + builder.Append(former); + builder.Append('/'); + builder.Append(latter); + return builder.ToString(); + } + } + + return former + latter; + } + + public static List QuoteAwareStringSplit(string str) + { + List subStrings = new List(); + int offset = 0; + while (true) + { + string subString = QuoteAwareSubString(str, ref offset); + if (subString == null) + { + break; + } + subStrings.Add(subString); + } + + return subStrings; + } + + // This method extracts substrings from a string starting at the offset + // and up until the next comma in the string. The sub string extraction is + // quote aware such that commas inside quoted-strings are ignored. On return, + // offset points to the next char beyond the comma of the substring returned + // and may point beyond the length of the header. + public static string QuoteAwareSubString(string str, ref int offset) + { + // this method will filter out empty-string and white-space-only items in + // the header. For example "x,,y" and "x, ,y" would result in just "x" and "y" + // substrings being returned. + + if (string.IsNullOrEmpty(str) || offset >= str.Length) + { + return null; + } + + int startIndex = (offset > 0) ? offset : 0; + + // trim whitespace and commas from the begining of the item + while (char.IsWhiteSpace(str[startIndex]) || str[startIndex] == ',') + { + startIndex++; + if (startIndex >= str.Length) + { + return null; + } + } + + int endIndex = startIndex; + bool insideQuotes = false; + + while (endIndex < str.Length) + { + if (str[endIndex] == '\"' && + (!insideQuotes || endIndex == 0 || str[endIndex - 1] != '\\')) + { + insideQuotes = !insideQuotes; + } + else if (str[endIndex] == ',' && !insideQuotes) + { + break; + } + endIndex++; + } + offset = endIndex + 1; + + // trim whitespace from the end of the item; the substring is guaranteed to + // have at least one non-whitespace character + while (char.IsWhiteSpace(str[endIndex - 1])) + { + endIndex--; + } + + return str.Substring(startIndex, endIndex - startIndex); + } + + public static ContentType GetContentType(string contentType) + { + string contentTypeTrimmed = contentType.Trim(); + if (!string.IsNullOrEmpty(contentTypeTrimmed)) + { + return GetContentTypeOrNull(contentTypeTrimmed); + } + + return null; + } + + public static ContentType GetContentTypeOrNull(string contentType) + { + try + { + Fx.Assert(contentType == contentType.Trim(), "The ContentType input argument should already be trimmed."); + Fx.Assert(!string.IsNullOrEmpty(contentType), "The ContentType input argument should not be null or empty."); + + ContentType contentTypeToReturn = new ContentType(contentType); + + // Need to check for "*/" because the ContentType constructor doesn't catch this + string[] typeAndSubType = contentTypeToReturn.MediaType.Split('/'); + Fx.Assert(typeAndSubType.Length == 2, "The creation of the ContentType would have failed if there wasn't a type and subtype."); + if (typeAndSubType[0][0] == '*' && typeAndSubType[0].Length == 1 && + !(typeAndSubType[1][0] == '*' && typeAndSubType[1].Length == 1)) + { + // + + + + // throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new FormatException( + // SR2.GetString(SR2.InvalidContentType, contentType))); + return null; + } + return contentTypeToReturn; + } + catch (FormatException) + { + // Return null to indicate that the content type creation failed + //System.ServiceModel.DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning); + } + + return null; + } + + public static string IEnumerableToCommaSeparatedString(IEnumerable items) + { + Fx.Assert(items != null, "The 'items' argument should never be null."); + + return string.Join(", ", items); + } + + public static void AddRange(ICollection list, IEnumerable itemsToAdd) + { + Fx.Assert(list != null, "The 'list' argument should never be null."); + Fx.Assert(itemsToAdd != null, "The 'itemsToAdd' argument should never be null."); + + foreach (T item in itemsToAdd) + { + list.Add(item); + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebChannelFactory.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebChannelFactory.cs new file mode 100644 index 00000000000..104a7484de6 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebChannelFactory.cs @@ -0,0 +1,98 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System.ServiceModel.Web +{ + using System.Collections.Generic; + using System.ServiceModel; + using System.ServiceModel.Channels; + using System.ServiceModel.Description; + using System.Diagnostics.CodeAnalysis; + using System.Net; + + public class WebChannelFactory : ChannelFactory + where TChannel : class + { + public WebChannelFactory() + : base() + { + } + + public WebChannelFactory(Binding binding) + : base(binding) + { + } + + public WebChannelFactory(ServiceEndpoint endpoint) : + base(endpoint) + { + } + + // The following constructors were available in .NET Framework's WebChannelFactory + // but ChannelFactory in dotnet/wcf does not expose matching base constructors + // (no (string endpointConfigurationName) or (Type channelType) overload), so they + // are intentionally omitted. Use WebChannelFactory(Binding, Uri) or + // WebChannelFactory(ServiceEndpoint) instead. + // + // [SuppressMessage(...)] + // public WebChannelFactory(string endpointConfigurationName) + // : base(endpointConfigurationName) { } + // + // public WebChannelFactory(Type channelType) + // : base(channelType) { } + + public WebChannelFactory(Uri remoteAddress) + : this(GetDefaultBinding(remoteAddress), remoteAddress) + { + } + + public WebChannelFactory(Binding binding, Uri remoteAddress) + : base(binding, (remoteAddress != null) ? new EndpointAddress(remoteAddress) : (EndpointAddress)null) + { + } + + // WebChannelFactory(string endpointConfigurationName, Uri remoteAddress) omitted + // (same reason as above). + + protected override void OnOpening() + { + if (this.Endpoint == null) + { + return; + } + + // if the binding is missing, set up a default binding + if (this.Endpoint.Binding == null && this.Endpoint.Address != null) + { + this.Endpoint.Binding = GetDefaultBinding(this.Endpoint.Address.Uri); + } + // WebServiceHost.SetRawContentTypeMapperIfNecessary is server-side and not part of + // this client-only port. Raw content-type mapping must be configured manually via + // WebMessageEncodingBindingElement.ContentTypeMapper if needed. + if (this.Endpoint.Behaviors.Find() == null) + { + this.Endpoint.Behaviors.Add(new WebHttpBehavior()); + } + base.OnOpening(); + } + + static Binding GetDefaultBinding(Uri remoteAddress) + { + if (remoteAddress == null || (remoteAddress.Scheme != Uri.UriSchemeHttp && remoteAddress.Scheme != Uri.UriSchemeHttps)) + { + return null; + } + if (remoteAddress.Scheme == Uri.UriSchemeHttp) + { + return new WebHttpBinding(); + } + else + { + WebHttpBinding result = new WebHttpBinding(); + result.Security.Mode = WebHttpSecurityMode.Transport; + result.Security.Transport.ClientCredentialType = HttpClientCredentialType.None; + return result; + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebFaultException.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebFaultException.cs new file mode 100644 index 00000000000..c75aeed5cb4 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebFaultException.cs @@ -0,0 +1,162 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.Collections.Generic; +using System.Net; +using System.Runtime.Serialization; +using System.Security; +using System.Security.Permissions; + +namespace System.ServiceModel.Web +{ + [Serializable] + public class WebFaultException : FaultException, IWebFaultException + { + internal const string WebFaultCodeNamespace = "http://schemas.microsoft.com/2009/WebFault"; + + public WebFaultException(HttpStatusCode statusCode) + : base(GetDefaultReason(statusCode), GetFaultCode(statusCode)) + { + StatusCode = statusCode; + } + + protected WebFaultException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + StatusCode = (HttpStatusCode)info.GetValue("statusCode", typeof(HttpStatusCode)); + } + + public HttpStatusCode StatusCode { get; private set; } + + Type IWebFaultException.DetailType => null; + + object IWebFaultException.DetailObject => null; + + Type[] IWebFaultException.KnownTypes => null; + + [Obsolete(DiagnosticId = "SYSLIB0051")] // SerializationInfo-based serialization is obsolete on .NET 8+ + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + + info.AddValue("statusCode", StatusCode); + } + + internal static FaultCode GetFaultCode(HttpStatusCode statusCode) + { + if ((int)statusCode >= (int)HttpStatusCode.InternalServerError) + { + return FaultCode.CreateReceiverFaultCode(statusCode.ToString(), WebFaultCodeNamespace); + } + else + { + return FaultCode.CreateSenderFaultCode(statusCode.ToString(), WebFaultCodeNamespace); + } + } + + // These reasons come from section 6.1.1 of http://www.ietf.org/rfc/rfc2616.txt + internal static string GetDefaultReason(HttpStatusCode statusCode) + { + switch ((int)statusCode) + { + case 100: return "Continue"; + case 101: return "Switching Protocols"; + case 200: return "OK"; + case 201: return "Created"; + case 202: return "Accepted"; + case 203: return "Non-Authoritative Information"; + case 204: return "No Content"; + case 205: return "Reset Content"; + case 206: return "Partial Content"; + case 300: return "Multiple Choices"; + case 301: return "Moved Permanently"; + case 302: return "Found"; + case 303: return "See Other"; + case 304: return "Not Modified"; + case 305: return "Use Proxy"; + case 307: return "Temporary Redirect"; + case 400: return "Bad Request"; + case 401: return "Unauthorized"; + case 402: return "Payment Required"; + case 403: return "Forbidden"; + case 404: return "Not Found"; + case 405: return "Method Not Allowed"; + case 406: return "Not Acceptable"; + case 407: return "Proxy Authentication Required"; + case 408: return "Request Time-out"; + case 409: return "Conflict"; + case 410: return "Gone"; + case 411: return "Length Required"; + case 412: return "Precondition Failed"; + case 413: return "Request Entity Too Large"; + case 414: return "Request-URI Too Large"; + case 415: return "Unsupported Media Type"; + case 416: return "Requested range not satisfiable"; + case 417: return "Expectation Failed"; + case 500: return "Internal Server Error"; + case 501: return "Not Implemented"; + case 502: return "Bad Gateway"; + case 503: return "Service Unavailable"; + case 504: return "Gateway Time-out"; + case 505: return "HTTP Version not supported"; + default: + { + int errorClass = ((int)statusCode) / 100; + switch (errorClass) + { + case 1: return "Informational"; + case 2: return "Success"; + case 3: return "Redirection"; + case 4: return "Client Error"; + case 5: return "Server Error"; + default: return null; + } + } + } + } + } + + [Serializable] + public class WebFaultException : FaultException, IWebFaultException + { + private Type[] _knownTypes; + + public WebFaultException(T detail, HttpStatusCode statusCode) + : base(detail, WebFaultException.GetDefaultReason(statusCode), WebFaultException.GetFaultCode(statusCode)) + { + StatusCode = statusCode; + } + + public WebFaultException(T detail, HttpStatusCode statusCode, IEnumerable knownTypes) + : base(detail, WebFaultException.GetDefaultReason(statusCode), WebFaultException.GetFaultCode(statusCode)) + { + StatusCode = statusCode; + _knownTypes = (knownTypes == null) ? null : new List(knownTypes).ToArray(); + } + + protected WebFaultException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + StatusCode = (HttpStatusCode)info.GetValue("statusCode", typeof(HttpStatusCode)); + _knownTypes = (Type[])info.GetValue("knownTypes", typeof(Type[])); + } + + public HttpStatusCode StatusCode { get; private set; } + + Type IWebFaultException.DetailType => typeof(T); + + object IWebFaultException.DetailObject => Detail; + + Type[] IWebFaultException.KnownTypes => _knownTypes; + + [Obsolete(DiagnosticId = "SYSLIB0051")] // SerializationInfo-based serialization is obsolete on .NET 8+ + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + base.GetObjectData(info, context); + + info.AddValue("statusCode", StatusCode); + info.AddValue("knownTypes", _knownTypes); + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebGetAttribute.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebGetAttribute.cs new file mode 100644 index 00000000000..2d1e7cd5d7a --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebGetAttribute.cs @@ -0,0 +1,113 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.ServiceModel.Channels; +using System.ServiceModel.Description; +using System.ServiceModel.Dispatcher; + +namespace System.ServiceModel.Web +{ + [AttributeUsage(AttributeTargets.Method)] + public sealed class WebGetAttribute : Attribute, IOperationContractAttributeProvider, IOperationBehavior + { + private WebMessageBodyStyle _bodyStyle; + private WebMessageFormat _requestMessageFormat; + private WebMessageFormat _responseMessageFormat; + + public WebGetAttribute() + { + } + + public WebMessageBodyStyle BodyStyle + { + get { return _bodyStyle; } + set + { + if (!WebMessageBodyStyleHelper.IsDefined(value)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value))); + } + + _bodyStyle = value; + IsBodyStyleSetExplicitly = true; + } + } + + public bool IsBodyStyleSetExplicitly { get; private set; } + + public bool IsRequestFormatSetExplicitly { get; private set; } + + public bool IsResponseFormatSetExplicitly { get; private set; } + + public WebMessageFormat RequestFormat + { + get + { + + return _requestMessageFormat; + } + set + { + if (!WebMessageFormatHelper.IsDefined(value)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value))); + } + + _requestMessageFormat = value; + IsRequestFormatSetExplicitly = true; + } + } + + public WebMessageFormat ResponseFormat + { + get + { + + return _responseMessageFormat; + } + set + { + if (!WebMessageFormatHelper.IsDefined(value)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value))); + } + + _responseMessageFormat = value; + IsResponseFormatSetExplicitly = true; + } + } + + public string UriTemplate { get; set; } + + void IOperationBehavior.AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) + { + } // do nothing + + void IOperationBehavior.ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) + { + } // do nothing + + void IOperationBehavior.ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) + { + } // do nothing + + void IOperationBehavior.Validate(OperationDescription operationDescription) + { + } // do nothing + + internal WebMessageBodyStyle GetBodyStyleOrDefault(WebMessageBodyStyle defaultStyle) + { + if (IsBodyStyleSetExplicitly) + { + return BodyStyle; + } + else + { + return defaultStyle; + } + } + + OperationContractAttribute IOperationContractAttributeProvider.GetOperationContractAttribute() => new OperationContractAttribute(); + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebInvokeAttribute.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebInvokeAttribute.cs new file mode 100644 index 00000000000..186ff9e81e3 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebInvokeAttribute.cs @@ -0,0 +1,115 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.ServiceModel.Channels; +using System.ServiceModel.Description; +using System.ServiceModel.Dispatcher; + +namespace System.ServiceModel.Web +{ + [AttributeUsage(AttributeTargets.Method)] + public sealed class WebInvokeAttribute : Attribute, IOperationContractAttributeProvider, IOperationBehavior + { + private WebMessageBodyStyle _bodyStyle; + private WebMessageFormat _requestMessageFormat; + private WebMessageFormat _responseMessageFormat; + + public WebInvokeAttribute() + { + } + + public WebMessageBodyStyle BodyStyle + { + get { return _bodyStyle; } + set + { + if (!WebMessageBodyStyleHelper.IsDefined(value)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value))); + } + + _bodyStyle = value; + IsBodyStyleSetExplicitly = true; + } + } + + public bool IsBodyStyleSetExplicitly { get; private set; } + + public bool IsRequestFormatSetExplicitly { get; private set; } + + public bool IsResponseFormatSetExplicitly { get; private set; } + + public string Method { get; set; } + + public WebMessageFormat RequestFormat + { + get + { + + return _requestMessageFormat; + } + set + { + if (!WebMessageFormatHelper.IsDefined(value)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value))); + } + + _requestMessageFormat = value; + IsRequestFormatSetExplicitly = true; + } + } + + public WebMessageFormat ResponseFormat + { + get + { + + return _responseMessageFormat; + } + set + { + if (!WebMessageFormatHelper.IsDefined(value)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value))); + } + + _responseMessageFormat = value; + IsResponseFormatSetExplicitly = true; + } + } + + public string UriTemplate { get; set; } + + void IOperationBehavior.AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) + { + } // do nothing + + void IOperationBehavior.ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) + { + } // do nothing + + void IOperationBehavior.ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) + { + } // do nothing + + void IOperationBehavior.Validate(OperationDescription operationDescription) + { + } // do nothing + + internal WebMessageBodyStyle GetBodyStyleOrDefault(WebMessageBodyStyle defaultStyle) + { + if (IsBodyStyleSetExplicitly) + { + return BodyStyle; + } + else + { + return defaultStyle; + } + } + + OperationContractAttribute IOperationContractAttributeProvider.GetOperationContractAttribute() => new OperationContractAttribute(); + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebMessageBodyStyle.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebMessageBodyStyle.cs new file mode 100644 index 00000000000..b2bcb51c571 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebMessageBodyStyle.cs @@ -0,0 +1,13 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System.ServiceModel.Web +{ + public enum WebMessageBodyStyle + { + Bare, + Wrapped, + WrappedRequest, + WrappedResponse + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebMessageBodyStyleHelper.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebMessageBodyStyleHelper.cs new file mode 100644 index 00000000000..02de9ff8455 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebMessageBodyStyleHelper.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System.ServiceModel.Web +{ + internal static class WebMessageBodyStyleHelper + { + internal static bool IsDefined(WebMessageBodyStyle style) + { + return (style == WebMessageBodyStyle.Bare + || style == WebMessageBodyStyle.Wrapped + || style == WebMessageBodyStyle.WrappedRequest + || style == WebMessageBodyStyle.WrappedResponse); + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebMessageFormat.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebMessageFormat.cs new file mode 100644 index 00000000000..a52bb183bc0 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebMessageFormat.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System.ServiceModel.Web +{ + public enum WebMessageFormat + { + Xml, + Json + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebMessageFormatHelper.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebMessageFormatHelper.cs new file mode 100644 index 00000000000..e7b1a8fc86c --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebMessageFormatHelper.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System.ServiceModel.Web +{ + internal static class WebMessageFormatHelper + { + internal static bool IsDefined(WebMessageFormat format) => format == WebMessageFormat.Xml || format == WebMessageFormat.Json; + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebOperationContext.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebOperationContext.cs new file mode 100644 index 00000000000..5fdb8081952 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/Web/WebOperationContext.cs @@ -0,0 +1,240 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.IO; +using System.Runtime.Serialization.Json; +using System.Text; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Serialization; +using System.ServiceModel.Channels; +using System.ServiceModel.Description; +using System.ServiceModel.Dispatcher; + +namespace System.ServiceModel.Web +{ + public class WebOperationContext : IExtension + { + internal static readonly string s_defaultTextMediaType = "text/plain"; + internal static readonly string s_defaultJsonMediaType = JsonGlobals.ApplicationJsonMediaType; + internal static readonly string s_defaultXmlMediaType = "application/xml"; + internal static readonly string s_defaultAtomMediaType = "application/atom+xml"; + internal static readonly string s_defaultStreamMediaType = "application/octet-stream"; + + private readonly OperationContext _operationContext; + + public WebOperationContext(OperationContext operationContext) + { + _operationContext = operationContext ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(operationContext)); + + if (operationContext.Extensions.Find() == null) + { + operationContext.Extensions.Add(this); + } + } + + public static WebOperationContext Current + { + get + { + if (OperationContext.Current == null) + { + return null; + } + + WebOperationContext existing = OperationContext.Current.Extensions.Find(); + if (existing != null) + { + return existing; + } + + return new WebOperationContext(OperationContext.Current); + } + } + + public IncomingWebRequestContext IncomingRequest => new IncomingWebRequestContext(_operationContext); + + public OutgoingWebResponseContext OutgoingResponse => new OutgoingWebResponseContext(_operationContext); + + public void Attach(OperationContext owner) + { + } + + public void Detach(OperationContext owner) + { + } + + public Message CreateJsonResponse(T instance) + { + DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T)); + + return CreateJsonResponse(instance, serializer); + } + + public Message CreateJsonResponse(T instance, DataContractJsonSerializer serializer) + { + if (serializer == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(serializer)); + } + + Message message = Message.CreateMessage(MessageVersion.None, null, instance, serializer); + message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.JsonProperty); + AddContentType(s_defaultJsonMediaType, OutgoingResponse.BindingWriteEncoding); + + return message; + } + + public Message CreateXmlResponse(T instance) + { + System.Runtime.Serialization.DataContractSerializer serializer = new System.Runtime.Serialization.DataContractSerializer(typeof(T)); + + return CreateXmlResponse(instance, serializer); + } + + public Message CreateXmlResponse(T instance, System.Runtime.Serialization.XmlObjectSerializer serializer) + { + if (serializer == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(serializer)); + } + + Message message = Message.CreateMessage(MessageVersion.None, null, instance, serializer); + message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.XmlProperty); + AddContentType(s_defaultXmlMediaType, OutgoingResponse.BindingWriteEncoding); + + return message; + } + + public Message CreateXmlResponse(T instance, XmlSerializer serializer) + { + if (serializer == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(serializer)); + } + + Message message = Message.CreateMessage(MessageVersion.None, (string)null, new XmlSerializerBodyWriter(instance, serializer)); + message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.XmlProperty); + AddContentType(s_defaultXmlMediaType, OutgoingResponse.BindingWriteEncoding); + + return message; + } + + public Message CreateXmlResponse(XDocument document) + { + if (document == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(document)); + } + + Message message; + if (document.FirstNode == null) + { + message = Message.CreateMessage(MessageVersion.None, (string)null); + } + else + { + message = Message.CreateMessage(MessageVersion.None, (string)null, document.CreateReader()); + } + + message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.XmlProperty); + AddContentType(s_defaultXmlMediaType, OutgoingResponse.BindingWriteEncoding); + + return message; + } + + public Message CreateXmlResponse(XElement element) + { + if (element == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(element)); + } + + Message message = Message.CreateMessage(MessageVersion.None, (string)null, element.CreateReader()); + message.Properties.Add(WebBodyFormatMessageProperty.Name, WebBodyFormatMessageProperty.XmlProperty); + AddContentType(s_defaultXmlMediaType, OutgoingResponse.BindingWriteEncoding); + + return message; + } + + public Message CreateTextResponse(string text) => CreateTextResponse(text, s_defaultTextMediaType, Encoding.UTF8); + + public Message CreateTextResponse(string text, string contentType) => CreateTextResponse(text, contentType, Encoding.UTF8); + + public Message CreateTextResponse(string text, string contentType, Encoding encoding) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + new NotSupportedException(SR.WebHttpRawContentNotSupported)); + } + + public Message CreateTextResponse(Action textWriter, string contentType) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + new NotSupportedException(SR.WebHttpRawContentNotSupported)); + } + + public Message CreateTextResponse(Action textWriter, string contentType, Encoding encoding) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + new NotSupportedException(SR.WebHttpRawContentNotSupported)); + } + + public Message CreateStreamResponse(Stream stream, string contentType) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + new NotSupportedException(SR.WebHttpRawContentNotSupported)); + } + + public Message CreateStreamResponse(/*StreamBodyWriter*/ object bodyWriter, string contentType) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + new NotSupportedException(SR.WebHttpRawContentNotSupported)); + } + + public Message CreateStreamResponse(Action streamWriter, string contentType) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + new NotSupportedException(SR.WebHttpRawContentNotSupported)); + } + + public UriTemplate GetUriTemplate(string operationName) + { + // WebHttpDispatchOperationSelector is server-side and not part of this client-only port. + // Construct UriTemplate manually from the [WebGet]/[WebInvoke] attribute on your contract instead. + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + new NotSupportedException(SR.WebHttpServerSideOperationSelectorNotSupported)); + } + + private void AddContentType(string contentType, Encoding encoding) + { + if (string.IsNullOrEmpty(OutgoingResponse.ContentType)) + { + if (encoding != null) + { + contentType = WebMessageEncoderFactory.GetContentType(contentType, encoding); + } + + OutgoingResponse.ContentType = contentType; + } + } + + internal class XmlSerializerBodyWriter : BodyWriter + { + private readonly object _instance; + private readonly XmlSerializer _serializer; + + public XmlSerializerBodyWriter(object instance, XmlSerializer serializer) + : base(false) + { + _instance = instance ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(instance)); + _serializer = serializer ?? throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(serializer)); + } + + protected override void OnWriteBodyContents(XmlDictionaryWriter writer) + { + _serializer.Serialize(writer, _instance); + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/WebHttpBinding.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/WebHttpBinding.cs new file mode 100644 index 00000000000..1219834d3a5 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/WebHttpBinding.cs @@ -0,0 +1,253 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System.ComponentModel; +using System.Text; +using System.Xml; +using System.ServiceModel.Channels; + +namespace System.ServiceModel +{ + public class WebHttpBinding : Binding + { + private HttpsTransportBindingElement _httpsTransportBindingElement; + // private BindingElements + private HttpTransportBindingElement _httpTransportBindingElement; + private WebHttpSecurity _security = new WebHttpSecurity(); + private WebMessageEncodingBindingElement _webMessageEncodingBindingElement; + + public WebHttpBinding() : base() + { + Initialize(); + } + + public WebHttpBinding(WebHttpSecurityMode securityMode) : base() + { + Initialize(); + _security.Mode = securityMode; + } + + [DefaultValue(HttpTransportDefaults.AllowCookies)] + public bool AllowCookies + { + get { return _httpTransportBindingElement.AllowCookies; } + set + { + _httpTransportBindingElement.AllowCookies = value; + _httpsTransportBindingElement.AllowCookies = value; + } + } + + [DefaultValue(HttpTransportDefaults.BypassProxyOnLocal)] + public bool BypassProxyOnLocal + { + get { return _httpTransportBindingElement.BypassProxyOnLocal; } + set + { + _httpTransportBindingElement.BypassProxyOnLocal = value; + _httpsTransportBindingElement.BypassProxyOnLocal = value; + } + } + + public EnvelopeVersion EnvelopeVersion => EnvelopeVersion.None; + + // HostNameComparisonMode is not exposed on HttpTransportBindingElement in + // dotnet/wcf, so it is intentionally omitted here (unlike .NET Framework). + + [DefaultValue(TransportDefaults.MaxBufferPoolSize)] + public long MaxBufferPoolSize + { + get { return _httpTransportBindingElement.MaxBufferPoolSize; } + set + { + _httpTransportBindingElement.MaxBufferPoolSize = value; + _httpsTransportBindingElement.MaxBufferPoolSize = value; + } + } + + [DefaultValue(TransportDefaults.MaxBufferSize)] + public int MaxBufferSize + { + get { return _httpTransportBindingElement.MaxBufferSize; } + set + { + _httpTransportBindingElement.MaxBufferSize = value; + _httpsTransportBindingElement.MaxBufferSize = value; + } + } + + [DefaultValue(TransportDefaults.MaxReceivedMessageSize)] + public long MaxReceivedMessageSize + { + get { return _httpTransportBindingElement.MaxReceivedMessageSize; } + set + { + _httpTransportBindingElement.MaxReceivedMessageSize = value; + _httpsTransportBindingElement.MaxReceivedMessageSize = value; + } + } + + public XmlDictionaryReaderQuotas ReaderQuotas + { + get { return _webMessageEncodingBindingElement.ReaderQuotas; } + set + { + if (value == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(value)); + } + + value.CopyTo(_webMessageEncodingBindingElement.ReaderQuotas); + } + } + + public override string Scheme => GetTransport().Scheme; + + public WebHttpSecurity Security + { + get { return _security; } + set + { + if (value == null) + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull(nameof(value)); + + _security = value; + } + } + + [DefaultValue(HttpTransportDefaults.ProxyAddress)] + [TypeConverter(typeof(UriTypeConverter))] + public Uri ProxyAddress + { + get { return _httpTransportBindingElement.ProxyAddress; } + set + { + _httpTransportBindingElement.ProxyAddress = value; + _httpsTransportBindingElement.ProxyAddress = value; + } + } + + [DefaultValue(HttpTransportDefaults.UseDefaultWebProxy)] + public bool UseDefaultWebProxy + { + get { return _httpTransportBindingElement.UseDefaultWebProxy; } + set + { + _httpTransportBindingElement.UseDefaultWebProxy = value; + _httpsTransportBindingElement.UseDefaultWebProxy = value; + } + } + + [DefaultValue(HttpTransportDefaults.TransferMode)] + public TransferMode TransferMode + { + get { return _httpTransportBindingElement.TransferMode; } + set + { + _httpTransportBindingElement.TransferMode = value; + _httpsTransportBindingElement.TransferMode = value; + } + } + + [TypeConverter(typeof(System.ComponentModel.StringConverter))] + public Encoding WriteEncoding + { + get { return _webMessageEncodingBindingElement.WriteEncoding; } + set + { + _webMessageEncodingBindingElement.WriteEncoding = value; + } + } + + public WebContentTypeMapper ContentTypeMapper + { + get { return _webMessageEncodingBindingElement.ContentTypeMapper; } + set + { + _webMessageEncodingBindingElement.ContentTypeMapper = value; + } + } + + public bool CrossDomainScriptAccessEnabled + { + get { return _webMessageEncodingBindingElement.CrossDomainScriptAccessEnabled; } + set + { + _webMessageEncodingBindingElement.CrossDomainScriptAccessEnabled = value; + } + } + + public override BindingElementCollection CreateBindingElements() + { + // return collection of BindingElements + BindingElementCollection bindingElements = new BindingElementCollection(); + // order of BindingElements is important + // add encoding + bindingElements.Add(_webMessageEncodingBindingElement); + // add transport (http or https) + bindingElements.Add(GetTransport()); + + return bindingElements.Clone(); + } + + public override IChannelFactory BuildChannelFactory(BindingParameterCollection parameters) + { + // ClientCredentialType.InheritedFromHost is only valid on server-side + // (IIS-hosted) scenarios; on a client channel factory it would map to + // AuthenticationSchemes.None and blow up deep inside the HTTP transport + // with an ArgumentException. Fail fast here with the same clear message + // the .NET Framework WebHttpBinding produced, matching WSHttpBinding's + // equivalent guard in dotnet/wcf. + if ((_security.Mode == WebHttpSecurityMode.Transport + || _security.Mode == WebHttpSecurityMode.TransportCredentialOnly) + && _security.Transport.ClientCredentialType == HttpClientCredentialType.InheritedFromHost) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( + new InvalidOperationException(SR.Format(SR.HttpClientCredentialTypeInvalid, _security.Transport.ClientCredentialType))); + } + + return base.BuildChannelFactory(parameters); + } + + private TransportBindingElement GetTransport() + { + if (_security.Mode == WebHttpSecurityMode.Transport) + { + _security.EnableTransportSecurity(_httpsTransportBindingElement); + _security.ApplyAuthorizationPolicySupport(_httpsTransportBindingElement); + return _httpsTransportBindingElement; + } + else if (_security.Mode == WebHttpSecurityMode.TransportCredentialOnly) + { + _security.EnableTransportAuthentication(_httpTransportBindingElement); + _security.ApplyAuthorizationPolicySupport(_httpTransportBindingElement); + return _httpTransportBindingElement; + } + else + { + // ensure that there is no transport security + _security.DisableTransportAuthentication(_httpTransportBindingElement); + _security.ApplyAuthorizationPolicySupport(_httpTransportBindingElement); + return _httpTransportBindingElement; + } + } + + private void Initialize() + { + _httpTransportBindingElement = new HttpTransportBindingElement + { + ManualAddressing = true + }; + + _httpsTransportBindingElement = new HttpsTransportBindingElement + { + ManualAddressing = true + }; + + _webMessageEncodingBindingElement = new WebMessageEncodingBindingElement + { + MessageVersion = MessageVersion.None + }; + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/WebHttpSecurity.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/WebHttpSecurity.cs new file mode 100644 index 00000000000..d93bbc8df5f --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/WebHttpSecurity.cs @@ -0,0 +1,68 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +using System; +using System.ServiceModel.Channels; + +namespace System.ServiceModel +{ + public sealed class WebHttpSecurity + { + internal const WebHttpSecurityMode DefaultMode = WebHttpSecurityMode.None; + private WebHttpSecurityMode _mode; + private HttpTransportSecurity _transportSecurity; + + public WebHttpSecurity() + { + _transportSecurity = new HttpTransportSecurity(); + } + + public WebHttpSecurityMode Mode + { + get { return _mode; } + set + { + if (!WebHttpSecurityModeHelper.IsDefined(value)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(value))); + } + + _mode = value; + IsModeSet = true; + } + } + + internal bool IsModeSet { get; private set; } + + public HttpTransportSecurity Transport + { + get { return _transportSecurity; } + set + { + _transportSecurity = (value == null) ? new HttpTransportSecurity() : value; + } + } + + internal void DisableTransportAuthentication(HttpTransportBindingElement http) + { + HttpTransportHelpers.DisableTransportAuthentication(http); + } + + internal void EnableTransportAuthentication(HttpTransportBindingElement http) + { + HttpTransportHelpers.ConfigureTransportAuthentication(http, _transportSecurity); + } + + internal void EnableTransportSecurity(HttpsTransportBindingElement https) + { + HttpTransportHelpers.ConfigureTransportProtectionAndAuthentication(https, _transportSecurity); + } + + internal void ApplyAuthorizationPolicySupport(HttpTransportBindingElement httpTransport) + { + // AlwaysUseAuthorizationPolicySupport is server-side only; dotnet/wcf's + // HttpTransportBindingElement and HttpTransportSecurity don't expose it. + // No-op for the client port. + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/WebHttpSecurityMode.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/WebHttpSecurityMode.cs new file mode 100644 index 00000000000..2233622c9b5 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/WebHttpSecurityMode.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license.; + +namespace System.ServiceModel +{ + public enum WebHttpSecurityMode + { + None, + Transport, + TransportCredentialOnly, + } +} diff --git a/src/System.ServiceModel.Web/src/System/ServiceModel/WebHttpSecurityModeHelper.cs b/src/System.ServiceModel.Web/src/System/ServiceModel/WebHttpSecurityModeHelper.cs new file mode 100644 index 00000000000..2b538137580 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/ServiceModel/WebHttpSecurityModeHelper.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System.ServiceModel +{ + internal static class WebHttpSecurityModeHelper + { + internal static bool IsDefined(WebHttpSecurityMode value) + { + return (value == WebHttpSecurityMode.None || + value == WebHttpSecurityMode.Transport || + value == WebHttpSecurityMode.TransportCredentialOnly); + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplate.cs b/src/System.ServiceModel.Web/src/System/UriTemplate.cs new file mode 100644 index 00000000000..e8060d89aae --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplate.cs @@ -0,0 +1,1731 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Collections.Specialized; + using System.Runtime; + using System.ServiceModel; + using System.ServiceModel.Channels; + using System.Text; + using System.Threading; + using System.Runtime.CompilerServices; + using System.Globalization; + + [TypeForwardedFrom("System.ServiceModel.Web, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public class UriTemplate + { + internal readonly int firstOptionalSegment; + + internal readonly string originalTemplate; + internal readonly Dictionary queries; // keys are original case specified in UriTemplate constructor, dictionary ignores case + internal readonly List segments; + internal const string WildcardPath = "*"; + readonly Dictionary additionalDefaults; // keys are original case specified in UriTemplate constructor, dictionary ignores case + readonly string fragment; + + readonly bool ignoreTrailingSlash; + + const string NullableDefault = "null"; + readonly WildcardInfo wildcard; + IDictionary defaults; + ConcurrentDictionary unescapedDefaults; + + VariablesCollection variables; + + // constructors validates that template is well-formed + public UriTemplate(string template) + : this(template, false) + { + } + public UriTemplate(string template, bool ignoreTrailingSlash) + : this(template, ignoreTrailingSlash, null) + { + } + public UriTemplate(string template, IDictionary additionalDefaults) + : this(template, false, additionalDefaults) + { + } + public UriTemplate(string template, bool ignoreTrailingSlash, IDictionary additionalDefaults) + { + if (template == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("template"); + } + this.originalTemplate = template; + this.ignoreTrailingSlash = ignoreTrailingSlash; + this.segments = new List(); + this.queries = new Dictionary(StringComparer.OrdinalIgnoreCase); + + // parse it + string pathTemplate; + string queryTemplate; + // ignore a leading slash + if (template.StartsWith("/", StringComparison.Ordinal)) + { + template = template.Substring(1); + } + // pull out fragment + int fragmentStart = template.IndexOf('#'); + if (fragmentStart == -1) + { + this.fragment = ""; + } + else + { + this.fragment = template.Substring(fragmentStart + 1); + template = template.Substring(0, fragmentStart); + } + // pull out path and query + int queryStart = template.IndexOf('?'); + if (queryStart == -1) + { + queryTemplate = string.Empty; + pathTemplate = template; + } + else + { + queryTemplate = template.Substring(queryStart + 1); + pathTemplate = template.Substring(0, queryStart); + } + template = null; // to ensure we don't accidentally reference this variable any more + + // setup path template and validate + if (!string.IsNullOrEmpty(pathTemplate)) + { + int startIndex = 0; + while (startIndex < pathTemplate.Length) + { + // Identify the next segment + int endIndex = pathTemplate.IndexOf('/', startIndex); + string segment; + if (endIndex != -1) + { + segment = pathTemplate.Substring(startIndex, endIndex + 1 - startIndex); + startIndex = endIndex + 1; + } + else + { + segment = pathTemplate.Substring(startIndex); + startIndex = pathTemplate.Length; + } + // Checking for wildcard segment ("*") or ("{*}") + UriTemplatePartType wildcardType; + if ((startIndex == pathTemplate.Length) && + UriTemplateHelpers.IsWildcardSegment(segment, out wildcardType)) + { + switch (wildcardType) + { + case UriTemplatePartType.Literal: + this.wildcard = new WildcardInfo(this); + break; + + case UriTemplatePartType.Variable: + this.wildcard = new WildcardInfo(this, segment); + break; + + default: + Fx.Assert("Error in identifying the type of the wildcard segment"); + break; + } + } + else + { + this.segments.Add(UriTemplatePathSegment.CreateFromUriTemplate(segment, this)); + } + } + } + + // setup query template and validate + if (!string.IsNullOrEmpty(queryTemplate)) + { + int startIndex = 0; + while (startIndex < queryTemplate.Length) + { + // Identify the next query part + int endIndex = queryTemplate.IndexOf('&', startIndex); + int queryPartStart = startIndex; + int queryPartEnd; + if (endIndex != -1) + { + queryPartEnd = endIndex; + startIndex = endIndex + 1; + if (startIndex >= queryTemplate.Length) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format( + SR.UTQueryCannotEndInAmpersand, this.originalTemplate))); + } + } + else + { + queryPartEnd = queryTemplate.Length; + startIndex = queryTemplate.Length; + } + // Checking query part type; identifying key and value + int equalSignIndex = queryTemplate.IndexOf('=', queryPartStart, queryPartEnd - queryPartStart); + string key; + string value; + if (equalSignIndex >= 0) + { + key = queryTemplate.Substring(queryPartStart, equalSignIndex - queryPartStart); + value = queryTemplate.Substring(equalSignIndex + 1, queryPartEnd - equalSignIndex - 1); + } + else + { + key = queryTemplate.Substring(queryPartStart, queryPartEnd - queryPartStart); + value = null; + } + if (string.IsNullOrEmpty(key)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format( + SR.UTQueryCannotHaveEmptyName, this.originalTemplate))); + } + if (UriTemplateHelpers.IdentifyPartType(key) != UriTemplatePartType.Literal) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("template", SR.Format( + SR.UTQueryMustHaveLiteralNames, this.originalTemplate)); + } + // Adding a new entry to the queries dictionary + key = UrlUtility.UrlDecode(key, Encoding.UTF8); + if (this.queries.ContainsKey(key)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format( + SR.UTQueryNamesMustBeUnique, this.originalTemplate))); + } + this.queries.Add(key, UriTemplateQueryValue.CreateFromUriTemplate(value, this)); + } + } + + // Process additional defaults (if has some) : + if (additionalDefaults != null) + { + if (this.variables == null) + { + if (additionalDefaults.Count > 0) + { + this.additionalDefaults = new Dictionary(additionalDefaults, StringComparer.OrdinalIgnoreCase); + } + } + else + { + foreach (KeyValuePair kvp in additionalDefaults) + { + string uppercaseKey = kvp.Key.ToUpperInvariant(); + if ((this.variables.DefaultValues != null) && this.variables.DefaultValues.ContainsKey(uppercaseKey)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("additionalDefaults", + SR.Format(SR.UTAdditionalDefaultIsInvalid, kvp.Key, this.originalTemplate)); + } + if (this.variables.PathSegmentVariableNames.Contains(uppercaseKey)) + { + this.variables.AddDefaultValue(uppercaseKey, kvp.Value); + } + else if (this.variables.QueryValueVariableNames.Contains(uppercaseKey)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UTDefaultValueToQueryVarFromAdditionalDefaults, this.originalTemplate, + uppercaseKey))); + } + else if (string.Compare(kvp.Value, UriTemplate.NullableDefault, StringComparison.OrdinalIgnoreCase) == 0) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UTNullableDefaultAtAdditionalDefaults, this.originalTemplate, + uppercaseKey))); + } + else + { + if (this.additionalDefaults == null) + { + this.additionalDefaults = new Dictionary(additionalDefaults.Count, StringComparer.OrdinalIgnoreCase); + } + this.additionalDefaults.Add(kvp.Key, kvp.Value); + } + } + } + } + + // Validate defaults (if should) + if ((this.variables != null) && (this.variables.DefaultValues != null)) + { + this.variables.ValidateDefaults(out this.firstOptionalSegment); + } + else + { + this.firstOptionalSegment = this.segments.Count; + } + } + + public IDictionary Defaults + { + get + { + if (this.defaults == null) + { + Interlocked.CompareExchange>(ref this.defaults, new UriTemplateDefaults(this), null); + } + return this.defaults; + } + } + public bool IgnoreTrailingSlash + { + get + { + return this.ignoreTrailingSlash; + } + } + public ReadOnlyCollection PathSegmentVariableNames + { + get + { + if (this.variables == null) + { + return VariablesCollection.EmptyCollection; + } + else + { + return this.variables.PathSegmentVariableNames; + } + } + } + public ReadOnlyCollection QueryValueVariableNames + { + get + { + if (this.variables == null) + { + return VariablesCollection.EmptyCollection; + } + else + { + return this.variables.QueryValueVariableNames; + } + } + } + + internal bool HasNoVariables + { + get + { + return (this.variables == null); + } + } + internal bool HasWildcard + { + get + { + return (this.wildcard != null); + } + } + + // make a Uri by subbing in the values, throw on bad input + public Uri BindByName(Uri baseAddress, IDictionary parameters) + { + return BindByName(baseAddress, parameters, false); + } + public Uri BindByName(Uri baseAddress, IDictionary parameters, bool omitDefaults) + { + if (baseAddress == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("baseAddress"); + } + if (!baseAddress.IsAbsoluteUri) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("baseAddress", SR.Format( + SR.UTBadBaseAddress)); + } + + BindInformation bindInfo; + if (this.variables == null) + { + bindInfo = PrepareBindInformation(parameters, omitDefaults); + } + else + { + bindInfo = this.variables.PrepareBindInformation(parameters, omitDefaults); + } + return Bind(baseAddress, bindInfo, omitDefaults); + } + public Uri BindByName(Uri baseAddress, NameValueCollection parameters) + { + return BindByName(baseAddress, parameters, false); + } + public Uri BindByName(Uri baseAddress, NameValueCollection parameters, bool omitDefaults) + { + if (baseAddress == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("baseAddress"); + } + if (!baseAddress.IsAbsoluteUri) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("baseAddress", SR.Format( + SR.UTBadBaseAddress)); + } + + BindInformation bindInfo; + if (this.variables == null) + { + bindInfo = PrepareBindInformation(parameters, omitDefaults); + } + else + { + bindInfo = this.variables.PrepareBindInformation(parameters, omitDefaults); + } + return Bind(baseAddress, bindInfo, omitDefaults); + } + public Uri BindByPosition(Uri baseAddress, params string[] values) + { + if (baseAddress == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("baseAddress"); + } + if (!baseAddress.IsAbsoluteUri) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("baseAddress", SR.Format( + SR.UTBadBaseAddress)); + } + + BindInformation bindInfo; + if (this.variables == null) + { + if (values.Length > 0) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.Format( + SR.UTBindByPositionNoVariables, this.originalTemplate, values.Length))); + } + bindInfo = new BindInformation(this.additionalDefaults); + } + else + { + bindInfo = this.variables.PrepareBindInformation(values); + } + return Bind(baseAddress, bindInfo, false); + } + + // A note about UriTemplate equivalency: + // The introduction of defaults and, more over, terminal defaults, broke the simple + // intuative notion of equivalency between templates. We will define equivalent + // templates as such based on the structure of them and not based on the set of uri + // that are matched by them. The result is that, even though they do not match the + // same set of uri's, the following templates are equivalent: + // - "/foo/{bar}" + // - "/foo/{bar=xyz}" + // A direct result from the support for 'terminal defaults' is that the IsPathEquivalentTo + // method, which was used both to determine the equivalence between templates, as + // well as verify that all the templates, combined together in the same PathEquivalentSet, + // are equivalent in thier path is no longer valid for both purposes. We will break + // it to two distinct methods, each will be called in a different case. + public bool IsEquivalentTo(UriTemplate other) + { + if (other == null) + { + return false; + } + if (other.segments == null || other.queries == null) + { + // they never are null, but PreSharp is complaining, + // and warning suppression isn't working + return false; + } + if (!IsPathFullyEquivalent(other)) + { + return false; + } + if (!IsQueryEquivalent(other)) + { + return false; + } + Fx.Assert(UriTemplateEquivalenceComparer.Instance.GetHashCode(this) == UriTemplateEquivalenceComparer.Instance.GetHashCode(other), "bad GetHashCode impl"); + return true; + } + + public UriTemplateMatch Match(Uri baseAddress, Uri candidate) + { + if (baseAddress == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("baseAddress"); + } + if (!baseAddress.IsAbsoluteUri) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("baseAddress", SR.Format( + SR.UTBadBaseAddress)); + } + if (candidate == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("candidate"); + } + + // ensure that the candidate is 'under' the base address + if (!candidate.IsAbsoluteUri) + { + return null; + } + string basePath = UriTemplateHelpers.GetUriPath(baseAddress); + string candidatePath = UriTemplateHelpers.GetUriPath(candidate); + if (candidatePath.Length < basePath.Length) + { + return null; + } + if (!candidatePath.StartsWith(basePath, StringComparison.OrdinalIgnoreCase)) + { + return null; + } + + // Identifying the relative segments \ checking matching to the path : + int numSegmentsInBaseAddress = baseAddress.Segments.Length; + string[] candidateSegments = candidate.Segments; + int numMatchedSegments; + Collection relativeCandidateSegments; + if (!IsCandidatePathMatch(numSegmentsInBaseAddress, candidateSegments, + out numMatchedSegments, out relativeCandidateSegments)) + { + return null; + } + // Checking matching to the query (if should) : + NameValueCollection candidateQuery = null; + if (!UriTemplateHelpers.CanMatchQueryTrivially(this)) + { + candidateQuery = UriTemplateHelpers.ParseQueryString(candidate.Query); + if (!UriTemplateHelpers.CanMatchQueryInterestingly(this, candidateQuery, false)) + { + return null; + } + } + + // We matched; lets build the UriTemplateMatch + return CreateUriTemplateMatch(baseAddress, candidate, null, numMatchedSegments, + relativeCandidateSegments, candidateQuery); + } + + public override string ToString() + { + return this.originalTemplate; + } + + internal string AddPathVariable(UriTemplatePartType sourceNature, string varDeclaration) + { + bool hasDefaultValue; + return AddPathVariable(sourceNature, varDeclaration, out hasDefaultValue); + } + internal string AddPathVariable(UriTemplatePartType sourceNature, string varDeclaration, + out bool hasDefaultValue) + { + if (this.variables == null) + { + this.variables = new VariablesCollection(this); + } + return this.variables.AddPathVariable(sourceNature, varDeclaration, out hasDefaultValue); + } + internal string AddQueryVariable(string varDeclaration) + { + if (this.variables == null) + { + this.variables = new VariablesCollection(this); + } + return this.variables.AddQueryVariable(varDeclaration); + } + + internal UriTemplateMatch CreateUriTemplateMatch(Uri baseUri, Uri uri, object data, + int numMatchedSegments, Collection relativePathSegments, NameValueCollection uriQuery) + { + UriTemplateMatch result = new UriTemplateMatch(); + result.RequestUri = uri; + result.BaseUri = baseUri; + if (uriQuery != null) + { + result.SetQueryParameters(uriQuery); + } + result.SetRelativePathSegments(relativePathSegments); + result.Data = data; + result.Template = this; + for (int i = 0; i < numMatchedSegments; i++) + { + this.segments[i].Lookup(result.RelativePathSegments[i], result.BoundVariables); + } + if (this.wildcard != null) + { + this.wildcard.Lookup(numMatchedSegments, result.RelativePathSegments, + result.BoundVariables); + } + else if (numMatchedSegments < this.segments.Count) + { + BindTerminalDefaults(numMatchedSegments, result.BoundVariables); + } + if (this.queries.Count > 0) + { + foreach (KeyValuePair kvp in this.queries) + { + kvp.Value.Lookup(result.QueryParameters[kvp.Key], result.BoundVariables); + //UriTemplateHelpers.AssertCanonical(varName); + } + } + if (this.additionalDefaults != null) + { + foreach (KeyValuePair kvp in this.additionalDefaults) + { + result.BoundVariables.Add(kvp.Key, UnescapeDefaultValue(kvp.Value)); + } + } + Fx.Assert(result.RelativePathSegments.Count - numMatchedSegments >= 0, "bad segment computation"); + result.SetWildcardPathSegmentsStart(numMatchedSegments); + + return result; + } + + internal bool IsPathPartiallyEquivalentAt(UriTemplate other, int segmentsCount) + { + // Refer to the note on template equivalency at IsEquivalentTo + // This method checks if any uri with given number of segments, which can be matched + // by this template, can be also matched by the other template. + Fx.Assert(segmentsCount >= this.firstOptionalSegment - 1, "How can that be? The Trie is constructed that way!"); + Fx.Assert(segmentsCount <= this.segments.Count, "How can that be? The Trie is constructed that way!"); + Fx.Assert(segmentsCount >= other.firstOptionalSegment - 1, "How can that be? The Trie is constructed that way!"); + Fx.Assert(segmentsCount <= other.segments.Count, "How can that be? The Trie is constructed that way!"); + for (int i = 0; i < segmentsCount; ++i) + { + if (!this.segments[i].IsEquivalentTo(other.segments[i], + ((i == segmentsCount - 1) && (this.ignoreTrailingSlash || other.ignoreTrailingSlash)))) + { + return false; + } + } + return true; + } + internal bool IsQueryEquivalent(UriTemplate other) + { + if (this.queries.Count != other.queries.Count) + { + return false; + } + foreach (string key in this.queries.Keys) + { + UriTemplateQueryValue utqv = this.queries[key]; + UriTemplateQueryValue otherUtqv; + if (!other.queries.TryGetValue(key, out otherUtqv)) + { + return false; + } + if (!utqv.IsEquivalentTo(otherUtqv)) + { + return false; + } + } + return true; + } + + internal static Uri RewriteUri(Uri uri, string host) + { + if (!string.IsNullOrEmpty(host)) + { + string originalHostHeader = uri.Host + ((!uri.IsDefaultPort) ? ":" + uri.Port.ToString(CultureInfo.InvariantCulture) : string.Empty); + if (!String.Equals(originalHostHeader, host, StringComparison.OrdinalIgnoreCase)) + { + Uri sourceUri = new Uri(String.Format(CultureInfo.InvariantCulture, "{0}://{1}", uri.Scheme, host)); + return (new UriBuilder(uri) { Host = sourceUri.Host, Port = sourceUri.Port }).Uri; + } + } + return uri; + } + + Uri Bind(Uri baseAddress, BindInformation bindInfo, bool omitDefaults) + { + UriBuilder result = new UriBuilder(baseAddress); + int parameterIndex = 0; + int lastPathParameter = ((this.variables == null) ? -1 : this.variables.PathSegmentVariableNames.Count - 1); + int lastPathParameterToBind; + if (lastPathParameter == -1) + { + lastPathParameterToBind = -1; + } + else if (omitDefaults) + { + lastPathParameterToBind = bindInfo.LastNonDefaultPathParameter; + } + else + { + lastPathParameterToBind = bindInfo.LastNonNullablePathParameter; + } + string[] parameters = bindInfo.NormalizedParameters; + IDictionary extraQueryParameters = bindInfo.AdditionalParameters; + // Binding the path : + StringBuilder pathString = new StringBuilder(result.Path); + if (pathString[pathString.Length - 1] != '/') + { + pathString.Append('/'); + } + if (lastPathParameterToBind < lastPathParameter) + { + // Binding all the parameters we need + int segmentIndex = 0; + while (parameterIndex <= lastPathParameterToBind) + { + Fx.Assert(segmentIndex < this.segments.Count, + "Calculation of LastNonDefaultPathParameter,lastPathParameter or parameterIndex failed"); + this.segments[segmentIndex++].Bind(parameters, ref parameterIndex, pathString); + } + Fx.Assert(parameterIndex == lastPathParameterToBind + 1, + "That is the exit criteria from the loop"); + // Maybe we have some literals yet to bind + Fx.Assert(segmentIndex < this.segments.Count, + "Calculation of LastNonDefaultPathParameter,lastPathParameter or parameterIndex failed"); + while (this.segments[segmentIndex].Nature == UriTemplatePartType.Literal) + { + this.segments[segmentIndex++].Bind(parameters, ref parameterIndex, pathString); + Fx.Assert(parameterIndex == lastPathParameterToBind + 1, + "We have moved the parameter index in a literal binding"); + Fx.Assert(segmentIndex < this.segments.Count, + "Calculation of LastNonDefaultPathParameter,lastPathParameter or parameterIndex failed"); + } + // We're done; skip to the beggining of the query parameters + parameterIndex = lastPathParameter + 1; + } + else if (this.segments.Count > 0 || this.wildcard != null) + { + for (int i = 0; i < this.segments.Count; i++) + { + this.segments[i].Bind(parameters, ref parameterIndex, pathString); + } + if (this.wildcard != null) + { + this.wildcard.Bind(parameters, ref parameterIndex, pathString); + } + } + if (this.ignoreTrailingSlash && (pathString[pathString.Length - 1] == '/')) + { + pathString.Remove(pathString.Length - 1, 1); + } + result.Path = pathString.ToString(); + // Binding the query : + if ((this.queries.Count != 0) || (extraQueryParameters != null)) + { + StringBuilder query = new StringBuilder(""); + foreach (string key in this.queries.Keys) + { + this.queries[key].Bind(key, parameters, ref parameterIndex, query); + } + if (extraQueryParameters != null) + { + foreach (string key in extraQueryParameters.Keys) + { + if (this.queries.ContainsKey(key.ToUpperInvariant())) + { + // This can only be if the key passed has the same name as some literal key + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("parameters", SR.Format( + SR.UTBothLiteralAndNameValueCollectionKey, key)); + } + string value = extraQueryParameters[key]; + string escapedValue = (string.IsNullOrEmpty(value) ? string.Empty : UrlUtility.UrlEncode(value, Encoding.UTF8)); + query.AppendFormat("&{0}={1}", UrlUtility.UrlEncode(key, Encoding.UTF8), escapedValue); + } + } + if (query.Length != 0) + { + query.Remove(0, 1); // remove extra leading '&' + } + result.Query = query.ToString(); + } + // Adding the fragment (if needed) + if (this.fragment != null) + { + result.Fragment = this.fragment; + } + + return result.Uri; + } + void BindTerminalDefaults(int numMatchedSegments, NameValueCollection boundParameters) + { + Fx.Assert(!this.HasWildcard, "There are no terminal default when ends with wildcard"); + Fx.Assert(numMatchedSegments < this.segments.Count, "Otherwise - no defaults to bind"); + Fx.Assert(this.variables != null, "Otherwise - no default values to bind"); + Fx.Assert(this.variables.DefaultValues != null, "Otherwise - no default values to bind"); + for (int i = numMatchedSegments; i < this.segments.Count; i++) + { + switch (this.segments[i].Nature) + { + case UriTemplatePartType.Variable: + { + UriTemplateVariablePathSegment vps = this.segments[i] as UriTemplateVariablePathSegment; + Fx.Assert(vps != null, "How can that be? That its nature"); + this.variables.LookupDefault(vps.VarName, boundParameters); + } + break; + + default: + Fx.Assert("We only support terminal defaults on Variable segments"); + break; + } + } + } + + bool IsCandidatePathMatch(int numSegmentsInBaseAddress, string[] candidateSegments, + out int numMatchedSegments, out Collection relativeSegments) + { + int numRelativeSegments = candidateSegments.Length - numSegmentsInBaseAddress; + Fx.Assert(numRelativeSegments >= 0, "bad segments num"); + relativeSegments = new Collection(); + bool isStillMatch = true; + int relativeSegmentsIndex = 0; + while (isStillMatch && (relativeSegmentsIndex < numRelativeSegments)) + { + string segment = candidateSegments[relativeSegmentsIndex + numSegmentsInBaseAddress]; + // Mathcing to next regular segment in the template (if there is one); building the wire segment representation + if (relativeSegmentsIndex < this.segments.Count) + { + bool ignoreSlash = (this.ignoreTrailingSlash && (relativeSegmentsIndex == numRelativeSegments - 1)); + UriTemplateLiteralPathSegment lps = UriTemplateLiteralPathSegment.CreateFromWireData(segment); + if (!this.segments[relativeSegmentsIndex].IsMatch(lps, ignoreSlash)) + { + isStillMatch = false; + break; + } + string relPathSeg = Uri.UnescapeDataString(segment); + if (lps.EndsWithSlash) + { + Fx.Assert(relPathSeg.EndsWith("/", StringComparison.Ordinal), "problem with relative path segment"); + relPathSeg = relPathSeg.Substring(0, relPathSeg.Length - 1); // trim slash + } + relativeSegments.Add(relPathSeg); + } + // Checking if the template has a wild card ('*') or a final star var segment ("{*}" + else if (this.HasWildcard) + { + break; + } + else + { + isStillMatch = false; + break; + } + relativeSegmentsIndex++; + } + if (isStillMatch) + { + numMatchedSegments = relativeSegmentsIndex; + // building the wire representation to segments that were matched to a wild card + if (relativeSegmentsIndex < numRelativeSegments) + { + while (relativeSegmentsIndex < numRelativeSegments) + { + string relPathSeg = Uri.UnescapeDataString(candidateSegments[relativeSegmentsIndex + numSegmentsInBaseAddress]); + if (relPathSeg.EndsWith("/", StringComparison.Ordinal)) + { + relPathSeg = relPathSeg.Substring(0, relPathSeg.Length - 1); // trim slash + } + relativeSegments.Add(relPathSeg); + relativeSegmentsIndex++; + } + } + // Checking if we matched all required segments already + else if (numMatchedSegments < this.firstOptionalSegment) + { + isStillMatch = false; + } + } + else + { + numMatchedSegments = 0; + } + + return isStillMatch; + } + + bool IsPathFullyEquivalent(UriTemplate other) + { + // Refer to the note on template equivalency at IsEquivalentTo + // This method checks if both templates has a fully equivalent path. + if (this.HasWildcard != other.HasWildcard) + { + return false; + } + if (this.segments.Count != other.segments.Count) + { + return false; + } + for (int i = 0; i < this.segments.Count; ++i) + { + if (!this.segments[i].IsEquivalentTo(other.segments[i], + (i == this.segments.Count - 1) && !this.HasWildcard && (this.ignoreTrailingSlash || other.ignoreTrailingSlash))) + { + return false; + } + } + return true; + } + + BindInformation PrepareBindInformation(IDictionary parameters, bool omitDefaults) + { + if (parameters == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameters"); + } + + IDictionary extraParameters = new Dictionary(UriTemplateHelpers.GetQueryKeyComparer()); + foreach (KeyValuePair kvp in parameters) + { + if (string.IsNullOrEmpty(kvp.Key)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("parameters", + SR.Format(SR.UTBindByNameCalledWithEmptyKey)); + } + + extraParameters.Add(kvp); + } + BindInformation bindInfo; + ProcessDefaultsAndCreateBindInfo(omitDefaults, extraParameters, out bindInfo); + return bindInfo; + } + BindInformation PrepareBindInformation(NameValueCollection parameters, bool omitDefaults) + { + if (parameters == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameters"); + } + + IDictionary extraParameters = new Dictionary(UriTemplateHelpers.GetQueryKeyComparer()); + foreach (string key in parameters.AllKeys) + { + if (string.IsNullOrEmpty(key)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("parameters", + SR.Format(SR.UTBindByNameCalledWithEmptyKey)); + } + + extraParameters.Add(key, parameters[key]); + } + BindInformation bindInfo; + ProcessDefaultsAndCreateBindInfo(omitDefaults, extraParameters, out bindInfo); + return bindInfo; + } + void ProcessDefaultsAndCreateBindInfo(bool omitDefaults, IDictionary extraParameters, + out BindInformation bindInfo) + { + Fx.Assert(extraParameters != null, "We are expected to create it at the calling PrepareBindInformation"); + if (this.additionalDefaults != null) + { + if (omitDefaults) + { + foreach (KeyValuePair kvp in this.additionalDefaults) + { + string extraParameter; + if (extraParameters.TryGetValue(kvp.Key, out extraParameter)) + { + if (string.Compare(extraParameter, kvp.Value, StringComparison.Ordinal) == 0) + { + extraParameters.Remove(kvp.Key); + } + } + } + } + else + { + foreach (KeyValuePair kvp in this.additionalDefaults) + { + if (!extraParameters.ContainsKey(kvp.Key)) + { + extraParameters.Add(kvp.Key, kvp.Value); + } + } + } + } + if (extraParameters.Count == 0) + { + extraParameters = null; + } + bindInfo = new BindInformation(extraParameters); + } + + string UnescapeDefaultValue(string escapedValue) + { + if (string.IsNullOrEmpty(escapedValue)) + { + return escapedValue; + } + if (this.unescapedDefaults == null) + { + this.unescapedDefaults = new ConcurrentDictionary(StringComparer.Ordinal); + } + + return this.unescapedDefaults.GetOrAdd(escapedValue, Uri.UnescapeDataString); + } + + struct BindInformation + { + IDictionary additionalParameters; + int lastNonDefaultPathParameter; + int lastNonNullablePathParameter; + string[] normalizedParameters; + + public BindInformation(string[] normalizedParameters, int lastNonDefaultPathParameter, + int lastNonNullablePathParameter, IDictionary additionalParameters) + { + this.normalizedParameters = normalizedParameters; + this.lastNonDefaultPathParameter = lastNonDefaultPathParameter; + this.lastNonNullablePathParameter = lastNonNullablePathParameter; + this.additionalParameters = additionalParameters; + } + public BindInformation(IDictionary additionalParameters) + { + this.normalizedParameters = null; + this.lastNonDefaultPathParameter = -1; + this.lastNonNullablePathParameter = -1; + this.additionalParameters = additionalParameters; + } + + public IDictionary AdditionalParameters + { + get + { + return this.additionalParameters; + } + } + public int LastNonDefaultPathParameter + { + get + { + return this.lastNonDefaultPathParameter; + } + } + public int LastNonNullablePathParameter + { + get + { + return this.lastNonNullablePathParameter; + } + } + public string[] NormalizedParameters + { + get + { + return this.normalizedParameters; + } + } + } + + class UriTemplateDefaults : IDictionary + { + Dictionary defaults; + ReadOnlyCollection keys; + ReadOnlyCollection values; + + public UriTemplateDefaults(UriTemplate template) + { + this.defaults = new Dictionary(StringComparer.OrdinalIgnoreCase); + if ((template.variables != null) && (template.variables.DefaultValues != null)) + { + foreach (KeyValuePair kvp in template.variables.DefaultValues) + { + this.defaults.Add(kvp.Key, kvp.Value); + } + } + if (template.additionalDefaults != null) + { + foreach (KeyValuePair kvp in template.additionalDefaults) + { + this.defaults.Add(kvp.Key.ToUpperInvariant(), kvp.Value); + } + } + this.keys = new ReadOnlyCollection(new List(this.defaults.Keys)); + this.values = new ReadOnlyCollection(new List(this.defaults.Values)); + } + + // ICollection> Members + public int Count + { + get + { + return this.defaults.Count; + } + } + public bool IsReadOnly + { + get + { + return true; + } + } + + // IDictionary Members + public ICollection Keys + { + get + { + return this.keys; + } + } + public ICollection Values + { + get + { + return this.values; + } + } + public string this[string key] + { + get + { + return this.defaults[key]; + } + set + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException( + SR.Format(SR.UTDefaultValuesAreImmutable))); + } + } + + public void Add(string key, string value) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException( + SR.Format(SR.UTDefaultValuesAreImmutable))); + } + + public void Add(KeyValuePair item) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException( + SR.Format(SR.UTDefaultValuesAreImmutable))); + } + public void Clear() + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException( + SR.Format(SR.UTDefaultValuesAreImmutable))); + } + public bool Contains(KeyValuePair item) + { + return (this.defaults as ICollection>).Contains(item); + } + public bool ContainsKey(string key) + { + return this.defaults.ContainsKey(key); + } + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + (this.defaults as ICollection>).CopyTo(array, arrayIndex); + } + + // IEnumerable> Members + public IEnumerator> GetEnumerator() + { + return this.defaults.GetEnumerator(); + } + public bool Remove(string key) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException( + SR.Format(SR.UTDefaultValuesAreImmutable))); + } + public bool Remove(KeyValuePair item) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException( + SR.Format(SR.UTDefaultValuesAreImmutable))); + } + + // IEnumerable Members + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this.defaults.GetEnumerator(); + } + public bool TryGetValue(string key, out string value) + { + return this.defaults.TryGetValue(key, out value); + } + } + + class VariablesCollection + { + readonly UriTemplate owner; + static ReadOnlyCollection emptyStringCollection = null; + Dictionary defaultValues; // key is the variable name (in uppercase; as appear in the variable names lists) + int firstNullablePathVariable; + List pathSegmentVariableNames; // ToUpperInvariant, in order they occur in the original template string + ReadOnlyCollection pathSegmentVariableNamesSnapshot = null; + List pathSegmentVariableNature; + List queryValueVariableNames; // ToUpperInvariant, in order they occur in the original template string + ReadOnlyCollection queryValueVariableNamesSnapshot = null; + + public VariablesCollection(UriTemplate owner) + { + this.owner = owner; + this.pathSegmentVariableNames = new List(); + this.pathSegmentVariableNature = new List(); + this.queryValueVariableNames = new List(); + this.firstNullablePathVariable = -1; + } + + public static ReadOnlyCollection EmptyCollection + { + get + { + if (emptyStringCollection == null) + { + emptyStringCollection = new ReadOnlyCollection(new List()); + } + return emptyStringCollection; + } + } + + public Dictionary DefaultValues + { + get + { + return this.defaultValues; + } + } + public ReadOnlyCollection PathSegmentVariableNames + { + get + { + if (this.pathSegmentVariableNamesSnapshot == null) + { + Interlocked.CompareExchange>(ref this.pathSegmentVariableNamesSnapshot, new ReadOnlyCollection( + this.pathSegmentVariableNames), null); + } + return this.pathSegmentVariableNamesSnapshot; + } + } + public ReadOnlyCollection QueryValueVariableNames + { + get + { + if (this.queryValueVariableNamesSnapshot == null) + { + Interlocked.CompareExchange>(ref this.queryValueVariableNamesSnapshot, new ReadOnlyCollection( + this.queryValueVariableNames), null); + } + return this.queryValueVariableNamesSnapshot; + } + } + + public void AddDefaultValue(string varName, string value) + { + int varIndex = this.pathSegmentVariableNames.IndexOf(varName); + Fx.Assert(varIndex != -1, "Adding default value is restricted to path variables"); + if ((this.owner.wildcard != null) && this.owner.wildcard.HasVariable && + (varIndex == this.pathSegmentVariableNames.Count - 1)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UTStarVariableWithDefaultsFromAdditionalDefaults, + this.owner.originalTemplate, varName))); + } + if (this.pathSegmentVariableNature[varIndex] != UriTemplatePartType.Variable) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UTDefaultValueToCompoundSegmentVarFromAdditionalDefaults, + this.owner.originalTemplate, varName))); + } + if (string.IsNullOrEmpty(value) || + (string.Compare(value, UriTemplate.NullableDefault, StringComparison.OrdinalIgnoreCase) == 0)) + { + value = null; + } + if (this.defaultValues == null) + { + this.defaultValues = new Dictionary(); + } + this.defaultValues.Add(varName, value); + } + + public string AddPathVariable(UriTemplatePartType sourceNature, string varDeclaration, out bool hasDefaultValue) + { + Fx.Assert(sourceNature != UriTemplatePartType.Literal, "Literal path segments can't be the source for path variables"); + string varName; + string defaultValue; + ParseVariableDeclaration(varDeclaration, out varName, out defaultValue); + hasDefaultValue = (defaultValue != null); + if (varName.IndexOf(UriTemplate.WildcardPath, StringComparison.Ordinal) != -1) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException( + SR.Format(SR.UTInvalidWildcardInVariableOrLiteral, this.owner.originalTemplate, UriTemplate.WildcardPath))); + } + string uppercaseVarName = varName.ToUpperInvariant(); + if (this.pathSegmentVariableNames.Contains(uppercaseVarName) || + this.queryValueVariableNames.Contains(uppercaseVarName)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UTVarNamesMustBeUnique, this.owner.originalTemplate, varName))); + } + this.pathSegmentVariableNames.Add(uppercaseVarName); + this.pathSegmentVariableNature.Add(sourceNature); + if (hasDefaultValue) + { + if (defaultValue == string.Empty) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UTInvalidDefaultPathValue, this.owner.originalTemplate, + varDeclaration, varName))); + } + if (string.Compare(defaultValue, UriTemplate.NullableDefault, StringComparison.OrdinalIgnoreCase) == 0) + { + defaultValue = null; + } + if (this.defaultValues == null) + { + this.defaultValues = new Dictionary(); + } + this.defaultValues.Add(uppercaseVarName, defaultValue); + } + return uppercaseVarName; + } + public string AddQueryVariable(string varDeclaration) + { + string varName; + string defaultValue; + ParseVariableDeclaration(varDeclaration, out varName, out defaultValue); + if (varName.IndexOf(UriTemplate.WildcardPath, StringComparison.Ordinal) != -1) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException( + SR.Format(SR.UTInvalidWildcardInVariableOrLiteral, this.owner.originalTemplate, UriTemplate.WildcardPath))); + } + if (defaultValue != null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UTDefaultValueToQueryVar, this.owner.originalTemplate, + varDeclaration, varName))); + } + string uppercaseVarName = varName.ToUpperInvariant(); + if (this.pathSegmentVariableNames.Contains(uppercaseVarName) || + this.queryValueVariableNames.Contains(uppercaseVarName)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UTVarNamesMustBeUnique, this.owner.originalTemplate, varName))); + } + this.queryValueVariableNames.Add(uppercaseVarName); + return uppercaseVarName; + } + + public void LookupDefault(string varName, NameValueCollection boundParameters) + { + Fx.Assert(this.defaultValues.ContainsKey(varName), "Otherwise, we don't have a value to bind"); + boundParameters.Add(varName, owner.UnescapeDefaultValue(this.defaultValues[varName])); + } + + public BindInformation PrepareBindInformation(IDictionary parameters, bool omitDefaults) + { + if (parameters == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameters"); + } + + string[] normalizedParameters = PrepareNormalizedParameters(); + IDictionary extraParameters = null; + foreach (string key in parameters.Keys) + { + ProcessBindParameter(key, parameters[key], normalizedParameters, ref extraParameters); + } + BindInformation bindInfo; + ProcessDefaultsAndCreateBindInfo(omitDefaults, normalizedParameters, extraParameters, out bindInfo); + return bindInfo; + } + public BindInformation PrepareBindInformation(NameValueCollection parameters, bool omitDefaults) + { + if (parameters == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("parameters"); + } + + string[] normalizedParameters = PrepareNormalizedParameters(); + IDictionary extraParameters = null; + foreach (string key in parameters.AllKeys) + { + ProcessBindParameter(key, parameters[key], normalizedParameters, ref extraParameters); + } + BindInformation bindInfo; + ProcessDefaultsAndCreateBindInfo(omitDefaults, normalizedParameters, extraParameters, out bindInfo); + return bindInfo; + } + public BindInformation PrepareBindInformation(params string[] parameters) + { + if (parameters == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("values"); + } + if ((parameters.Length < this.pathSegmentVariableNames.Count) || + (parameters.Length > this.pathSegmentVariableNames.Count + this.queryValueVariableNames.Count)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException( + SR.Format(SR.UTBindByPositionWrongCount, this.owner.originalTemplate, + this.pathSegmentVariableNames.Count, this.queryValueVariableNames.Count, + parameters.Length))); + } + + string[] normalizedParameters; + if (parameters.Length == this.pathSegmentVariableNames.Count + this.queryValueVariableNames.Count) + { + normalizedParameters = parameters; + } + else + { + normalizedParameters = new string[this.pathSegmentVariableNames.Count + this.queryValueVariableNames.Count]; + parameters.CopyTo(normalizedParameters, 0); + for (int i = parameters.Length; i < normalizedParameters.Length; i++) + { + normalizedParameters[i] = null; + } + } + int lastNonDefaultPathParameter; + int lastNonNullablePathParameter; + LoadDefaultsAndValidate(normalizedParameters, out lastNonDefaultPathParameter, + out lastNonNullablePathParameter); + return new BindInformation(normalizedParameters, lastNonDefaultPathParameter, + lastNonNullablePathParameter, this.owner.additionalDefaults); + } + public void ValidateDefaults(out int firstOptionalSegment) + { + Fx.Assert(this.defaultValues != null, "We are checking this condition from the c'tor"); + Fx.Assert(this.pathSegmentVariableNames.Count > 0, "Otherwise, how can we have default values"); + // Finding the first valid nullable defaults + for (int i = this.pathSegmentVariableNames.Count - 1; (i >= 0) && (this.firstNullablePathVariable == -1); i--) + { + string varName = this.pathSegmentVariableNames[i]; + string defaultValue; + if (!this.defaultValues.TryGetValue(varName, out defaultValue)) + { + this.firstNullablePathVariable = i + 1; + } + else if (defaultValue != null) + { + this.firstNullablePathVariable = i + 1; + } + } + if (this.firstNullablePathVariable == -1) + { + this.firstNullablePathVariable = 0; + } + // Making sure that there are no nullables to the left of the first valid nullable + if (this.firstNullablePathVariable > 1) + { + for (int i = this.firstNullablePathVariable - 2; i >= 0; i--) + { + string varName = this.pathSegmentVariableNames[i]; + string defaultValue; + if (this.defaultValues.TryGetValue(varName, out defaultValue)) + { + if (defaultValue == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UTNullableDefaultMustBeFollowedWithNullables, this.owner.originalTemplate, + varName, this.pathSegmentVariableNames[i + 1]))); + } + } + } + } + // Making sure that there are no Literals\WildCards to the right + // Based on the fact that only Variable Path Segments support default values, + // if firstNullablePathVariable=N and pathSegmentVariableNames.Count=M then + // the nature of the last M-N path segments should be StringNature.Variable; otherwise, + // there was a literal segment in between. Also, there shouldn't be a wildcard. + if (this.firstNullablePathVariable < this.pathSegmentVariableNames.Count) + { + if (this.owner.HasWildcard) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UTNullableDefaultMustNotBeFollowedWithWildcard, + this.owner.originalTemplate, this.pathSegmentVariableNames[this.firstNullablePathVariable]))); + } + for (int i = this.pathSegmentVariableNames.Count - 1; i >= this.firstNullablePathVariable; i--) + { + int segmentIndex = this.owner.segments.Count - (this.pathSegmentVariableNames.Count - i); + if (this.owner.segments[segmentIndex].Nature != UriTemplatePartType.Variable) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UTNullableDefaultMustNotBeFollowedWithLiteral, + this.owner.originalTemplate, this.pathSegmentVariableNames[this.firstNullablePathVariable], + this.owner.segments[segmentIndex].OriginalSegment))); + } + } + } + // Now that we have the firstNullablePathVariable set, lets calculate the firstOptionalSegment. + // We already knows that the last M-N path segments (when M=pathSegmentVariableNames.Count and + // N=firstNullablePathVariable) are optional (see the previos comment). We will start there and + // move to the left, stopping at the first segment, which is not a variable or is a variable + // and doesn't have a default value. + int numNullablePathVariables = (this.pathSegmentVariableNames.Count - this.firstNullablePathVariable); + firstOptionalSegment = this.owner.segments.Count - numNullablePathVariables; + if (!this.owner.HasWildcard) + { + while (firstOptionalSegment > 0) + { + UriTemplatePathSegment ps = this.owner.segments[firstOptionalSegment - 1]; + if (ps.Nature != UriTemplatePartType.Variable) + { + break; + } + UriTemplateVariablePathSegment vps = (ps as UriTemplateVariablePathSegment); + Fx.Assert(vps != null, "Should be; that's his nature"); + if (!this.defaultValues.ContainsKey(vps.VarName)) + { + break; + } + firstOptionalSegment--; + } + } + } + + void AddAdditionalDefaults(ref IDictionary extraParameters) + { + if (extraParameters == null) + { + extraParameters = this.owner.additionalDefaults; + } + else + { + foreach (KeyValuePair kvp in this.owner.additionalDefaults) + { + if (!extraParameters.ContainsKey(kvp.Key)) + { + extraParameters.Add(kvp.Key, kvp.Value); + } + } + } + } + void LoadDefaultsAndValidate(string[] normalizedParameters, out int lastNonDefaultPathParameter, + out int lastNonNullablePathParameter) + { + // First step - loading defaults + for (int i = 0; i < this.pathSegmentVariableNames.Count; i++) + { + if (string.IsNullOrEmpty(normalizedParameters[i]) && (this.defaultValues != null)) + { + this.defaultValues.TryGetValue(this.pathSegmentVariableNames[i], out normalizedParameters[i]); + } + } + // Second step - calculating bind constrains + lastNonDefaultPathParameter = this.pathSegmentVariableNames.Count - 1; + if ((this.defaultValues != null) && + (this.owner.segments[this.owner.segments.Count - 1].Nature != UriTemplatePartType.Literal)) + { + bool foundNonDefaultPathParameter = false; + while (!foundNonDefaultPathParameter && (lastNonDefaultPathParameter >= 0)) + { + string defaultValue; + if (this.defaultValues.TryGetValue(this.pathSegmentVariableNames[lastNonDefaultPathParameter], + out defaultValue)) + { + if (string.Compare(normalizedParameters[lastNonDefaultPathParameter], + defaultValue, StringComparison.Ordinal) != 0) + { + foundNonDefaultPathParameter = true; + } + else + { + lastNonDefaultPathParameter--; + } + } + else + { + foundNonDefaultPathParameter = true; + } + } + } + if (this.firstNullablePathVariable > lastNonDefaultPathParameter) + { + lastNonNullablePathParameter = this.firstNullablePathVariable - 1; + } + else + { + lastNonNullablePathParameter = lastNonDefaultPathParameter; + } + // Third step - validate + for (int i = 0; i <= lastNonNullablePathParameter; i++) + { + // Skip validation for terminating star variable segment : + if (this.owner.HasWildcard && this.owner.wildcard.HasVariable && + (i == this.pathSegmentVariableNames.Count - 1)) + { + continue; + } + // Validate + if (string.IsNullOrEmpty(normalizedParameters[i])) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("parameters", + SR.Format(SR.BindUriTemplateToNullOrEmptyPathParam, this.pathSegmentVariableNames[i])); + } + } + } + void ParseVariableDeclaration(string varDeclaration, out string varName, out string defaultValue) + { + if ((varDeclaration.IndexOf('{') != -1) || (varDeclaration.IndexOf('}') != -1)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException( + SR.Format(SR.UTInvalidVarDeclaration, this.owner.originalTemplate, varDeclaration))); + } + int equalSignIndex = varDeclaration.IndexOf('='); + switch (equalSignIndex) + { + case -1: + varName = varDeclaration; + defaultValue = null; + break; + + case 0: + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException( + SR.Format(SR.UTInvalidVarDeclaration, this.owner.originalTemplate, varDeclaration))); + + default: + varName = varDeclaration.Substring(0, equalSignIndex); + defaultValue = varDeclaration.Substring(equalSignIndex + 1); + if (defaultValue.IndexOf('=') != -1) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException( + SR.Format(SR.UTInvalidVarDeclaration, this.owner.originalTemplate, varDeclaration))); + } + break; + } + } + string[] PrepareNormalizedParameters() + { + string[] normalizedParameters = new string[this.pathSegmentVariableNames.Count + this.queryValueVariableNames.Count]; + for (int i = 0; i < normalizedParameters.Length; i++) + { + normalizedParameters[i] = null; + } + return normalizedParameters; + } + void ProcessBindParameter(string name, string value, string[] normalizedParameters, + ref IDictionary extraParameters) + { + if (string.IsNullOrEmpty(name)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("parameters", + SR.Format(SR.UTBindByNameCalledWithEmptyKey)); + } + + string uppercaseVarName = name.ToUpperInvariant(); + int pathVarIndex = this.pathSegmentVariableNames.IndexOf(uppercaseVarName); + if (pathVarIndex != -1) + { + normalizedParameters[pathVarIndex] = (string.IsNullOrEmpty(value) ? string.Empty : value); + return; + } + int queryVarIndex = this.queryValueVariableNames.IndexOf(uppercaseVarName); + if (queryVarIndex != -1) + { + normalizedParameters[this.pathSegmentVariableNames.Count + queryVarIndex] = (string.IsNullOrEmpty(value) ? string.Empty : value); + return; + } + if (extraParameters == null) + { + extraParameters = new Dictionary(UriTemplateHelpers.GetQueryKeyComparer()); + } + extraParameters.Add(name, value); + } + void ProcessDefaultsAndCreateBindInfo(bool omitDefaults, string[] normalizedParameters, + IDictionary extraParameters, out BindInformation bindInfo) + { + int lastNonDefaultPathParameter; + int lastNonNullablePathParameter; + LoadDefaultsAndValidate(normalizedParameters, out lastNonDefaultPathParameter, + out lastNonNullablePathParameter); + if (this.owner.additionalDefaults != null) + { + if (omitDefaults) + { + RemoveAdditionalDefaults(ref extraParameters); + } + else + { + AddAdditionalDefaults(ref extraParameters); + } + } + bindInfo = new BindInformation(normalizedParameters, lastNonDefaultPathParameter, + lastNonNullablePathParameter, extraParameters); + } + void RemoveAdditionalDefaults(ref IDictionary extraParameters) + { + if (extraParameters == null) + { + return; + } + + foreach (KeyValuePair kvp in this.owner.additionalDefaults) + { + string extraParameter; + if (extraParameters.TryGetValue(kvp.Key, out extraParameter)) + { + if (string.Compare(extraParameter, kvp.Value, StringComparison.Ordinal) == 0) + { + extraParameters.Remove(kvp.Key); + } + } + } + if (extraParameters.Count == 0) + { + extraParameters = null; + } + } + } + + class WildcardInfo + { + readonly UriTemplate owner; + readonly string varName; + + public WildcardInfo(UriTemplate owner) + { + this.varName = null; + this.owner = owner; + } + public WildcardInfo(UriTemplate owner, string segment) + { + Fx.Assert(!segment.EndsWith("/", StringComparison.Ordinal), "We are expecting to check this earlier"); + + bool hasDefault; + this.varName = owner.AddPathVariable(UriTemplatePartType.Variable, + segment.Substring(1 + WildcardPath.Length, segment.Length - 2 - WildcardPath.Length), + out hasDefault); + // Since this is a terminating star segment there shouldn't be a default + if (hasDefault) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UTStarVariableWithDefaults, owner.originalTemplate, + segment, this.varName))); + } + this.owner = owner; + } + + internal bool HasVariable + { + get + { + return (!string.IsNullOrEmpty(this.varName)); + } + } + + public void Bind(string[] values, ref int valueIndex, StringBuilder path) + { + if (HasVariable) + { + Fx.Assert(valueIndex < values.Length, "Not enough values to bind"); + if (string.IsNullOrEmpty(values[valueIndex])) + { + valueIndex++; + } + else + { + path.Append(values[valueIndex++]); + } + } + } + public void Lookup(int numMatchedSegments, Collection relativePathSegments, + NameValueCollection boundParameters) + { + Fx.Assert(numMatchedSegments == this.owner.segments.Count, "We should have matched the other segments"); + if (HasVariable) + { + StringBuilder remainingPath = new StringBuilder(); + for (int i = numMatchedSegments; i < relativePathSegments.Count; i++) + { + if (i < relativePathSegments.Count - 1) + { + remainingPath.AppendFormat("{0}/", relativePathSegments[i]); + } + else + { + remainingPath.Append(relativePathSegments[i]); + } + } + boundParameters.Add(this.varName, remainingPath.ToString()); + } + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplateCompoundPathSegment.cs b/src/System.ServiceModel.Web/src/System/UriTemplateCompoundPathSegment.cs new file mode 100644 index 00000000000..d20cdedc9d7 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplateCompoundPathSegment.cs @@ -0,0 +1,486 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + using System.Collections.Generic; + using System.Collections.Specialized; + using System.Runtime; + using System.ServiceModel; + using System.Text; + + // Thin wrapper around formatted string; use type system to help ensure we + // are doing canonicalization right/consistently - the literal sections are held in an + // un-escaped format + // We are assuming that the string will be always built as Lit{Var}Lit[{Var}Lit[{Var}Lit[...]]], + // when the first and last literals may be empty + class UriTemplateCompoundPathSegment : UriTemplatePathSegment, IComparable + { + readonly string firstLiteral; + readonly List varLitPairs; + + CompoundSegmentClass csClass; + + UriTemplateCompoundPathSegment(string originalSegment, bool endsWithSlash, string firstLiteral) + : base(originalSegment, UriTemplatePartType.Compound, endsWithSlash) + { + this.firstLiteral = firstLiteral; + this.varLitPairs = new List(); + } + public static new UriTemplateCompoundPathSegment CreateFromUriTemplate(string segment, UriTemplate template) + { + string origSegment = segment; + bool endsWithSlash = segment.EndsWith("/", StringComparison.Ordinal); + if (endsWithSlash) + { + segment = segment.Remove(segment.Length - 1); + } + + int nextVarStart = segment.IndexOf("{", StringComparison.Ordinal); + Fx.Assert(nextVarStart >= 0, "The method is only called after identifying a '{' character in the segment"); + string firstLiteral = ((nextVarStart > 0) ? segment.Substring(0, nextVarStart) : string.Empty); + if (firstLiteral.IndexOf(UriTemplate.WildcardPath, StringComparison.Ordinal) != -1) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException( + SR.Format(SR.UTInvalidWildcardInVariableOrLiteral, template.originalTemplate, UriTemplate.WildcardPath))); + } + UriTemplateCompoundPathSegment result = new UriTemplateCompoundPathSegment(origSegment, endsWithSlash, + ((firstLiteral != string.Empty) ? Uri.UnescapeDataString(firstLiteral) : string.Empty)); + do + { + int nextVarEnd = segment.IndexOf("}", nextVarStart + 1, StringComparison.Ordinal); + if (nextVarEnd < nextVarStart + 2) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException( + SR.Format(SR.UTInvalidFormatSegmentOrQueryPart, segment))); + } + bool hasDefault; + string varName = template.AddPathVariable(UriTemplatePartType.Compound, + segment.Substring(nextVarStart + 1, nextVarEnd - nextVarStart - 1), out hasDefault); + if (hasDefault) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UTDefaultValueToCompoundSegmentVar, template, origSegment, varName))); + } + nextVarStart = segment.IndexOf("{", nextVarEnd + 1, StringComparison.Ordinal); + string literal; + if (nextVarStart > 0) + { + if (nextVarStart == nextVarEnd + 1) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("template", + SR.Format(SR.UTDoesNotSupportAdjacentVarsInCompoundSegment, template, segment)); + } + literal = segment.Substring(nextVarEnd + 1, nextVarStart - nextVarEnd - 1); + } + else if (nextVarEnd + 1 < segment.Length) + { + literal = segment.Substring(nextVarEnd + 1); + } + else + { + literal = string.Empty; + } + if (literal.IndexOf(UriTemplate.WildcardPath, StringComparison.Ordinal) != -1) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException( + SR.Format(SR.UTInvalidWildcardInVariableOrLiteral, template.originalTemplate, UriTemplate.WildcardPath))); + } + if (literal.IndexOf('}') != -1) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException( + SR.Format(SR.UTInvalidFormatSegmentOrQueryPart, segment))); + } + result.varLitPairs.Add(new VarAndLitPair(varName, ((literal == string.Empty) ? string.Empty : Uri.UnescapeDataString(literal)))); + } while (nextVarStart > 0); + + if (string.IsNullOrEmpty(result.firstLiteral)) + { + if (string.IsNullOrEmpty(result.varLitPairs[result.varLitPairs.Count - 1].Literal)) + { + result.csClass = CompoundSegmentClass.HasNoPrefixNorSuffix; + } + else + { + result.csClass = CompoundSegmentClass.HasOnlySuffix; + } + } + else + { + if (string.IsNullOrEmpty(result.varLitPairs[result.varLitPairs.Count - 1].Literal)) + { + result.csClass = CompoundSegmentClass.HasOnlyPrefix; + } + else + { + result.csClass = CompoundSegmentClass.HasPrefixAndSuffix; + } + } + + return result; + } + + public override void Bind(string[] values, ref int valueIndex, StringBuilder path) + { + Fx.Assert(valueIndex + this.varLitPairs.Count <= values.Length, "Not enough values to bind"); + path.Append(this.firstLiteral); + for (int pairIndex = 0; pairIndex < this.varLitPairs.Count; pairIndex++) + { + path.Append(values[valueIndex++]); + path.Append(this.varLitPairs[pairIndex].Literal); + } + if (this.EndsWithSlash) + { + path.Append("/"); + } + } + public override bool IsEquivalentTo(UriTemplatePathSegment other, bool ignoreTrailingSlash) + { + if (other == null) + { + Fx.Assert("why would we ever call this?"); + return false; + } + if (!ignoreTrailingSlash && (this.EndsWithSlash != other.EndsWithSlash)) + { + return false; + } + UriTemplateCompoundPathSegment otherAsCompound = other as UriTemplateCompoundPathSegment; + if (otherAsCompound == null) + { + // if other can't be cast as a compound then it can't be equivalent + return false; + } + if (this.varLitPairs.Count != otherAsCompound.varLitPairs.Count) + { + return false; + } + if (StringComparer.OrdinalIgnoreCase.Compare(this.firstLiteral, otherAsCompound.firstLiteral) != 0) + { + return false; + } + for (int pairIndex = 0; pairIndex < this.varLitPairs.Count; pairIndex++) + { + if (StringComparer.OrdinalIgnoreCase.Compare(this.varLitPairs[pairIndex].Literal, + otherAsCompound.varLitPairs[pairIndex].Literal) != 0) + { + return false; + } + } + + return true; + } + public override bool IsMatch(UriTemplateLiteralPathSegment segment, bool ignoreTrailingSlash) + { + if (!ignoreTrailingSlash && (this.EndsWithSlash != segment.EndsWithSlash)) + { + return false; + } + return TryLookup(segment.AsUnescapedString(), null); + } + public override void Lookup(string segment, NameValueCollection boundParameters) + { + if (!TryLookup(segment, boundParameters)) + { + Fx.Assert("How can that be? Lookup is expected to be called after IsMatch"); + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UTCSRLookupBeforeMatch))); + } + } + + bool TryLookup(string segment, NameValueCollection boundParameters) + { + int segmentPosition = 0; + if (!string.IsNullOrEmpty(this.firstLiteral)) + { + if (segment.StartsWith(this.firstLiteral, StringComparison.Ordinal)) + { + segmentPosition = this.firstLiteral.Length; + } + else + { + return false; + } + } + for (int pairIndex = 0; pairIndex < this.varLitPairs.Count - 1; pairIndex++) + { + int nextLiteralPosition = segment.IndexOf(this.varLitPairs[pairIndex].Literal, segmentPosition, StringComparison.Ordinal); + if (nextLiteralPosition < segmentPosition + 1) + { + return false; + } + if (boundParameters != null) + { + string varValue = segment.Substring(segmentPosition, nextLiteralPosition - segmentPosition); + boundParameters.Add(this.varLitPairs[pairIndex].VarName, varValue); + } + segmentPosition = nextLiteralPosition + this.varLitPairs[pairIndex].Literal.Length; + } + if (segmentPosition < segment.Length) + { + if (string.IsNullOrEmpty(this.varLitPairs[varLitPairs.Count - 1].Literal)) + { + if (boundParameters != null) + { + boundParameters.Add(this.varLitPairs[varLitPairs.Count - 1].VarName, + segment.Substring(segmentPosition)); + } + return true; + } + else if ((segmentPosition + this.varLitPairs[varLitPairs.Count - 1].Literal.Length < segment.Length) && + segment.EndsWith(this.varLitPairs[varLitPairs.Count - 1].Literal, StringComparison.Ordinal)) + { + if (boundParameters != null) + { + boundParameters.Add(this.varLitPairs[varLitPairs.Count - 1].VarName, + segment.Substring(segmentPosition, segment.Length - segmentPosition - this.varLitPairs[varLitPairs.Count - 1].Literal.Length)); + } + return true; + } + else + { + return false; + } + } + else + { + return false; + } + } + + // A note about comparing compound segments: + // We are using this for generating the sorted collections at the nodes of the UriTemplateTrieNode. + // The idea is that we are sorting the segments based on preferred matching, when we have two + // compound segments matching the same wire segment, we will give preference to the preceding one. + // The order is based on the following concepts: + // - We are defining four classes of compound segments: prefix+suffix, prefix-only, suffix-only + // and none + // - Whenever we are comparing segments from different class the preferred one is the segment with + // the prefared class, based on the order we defined them (p+s \ p \ s \ n). + // - Within each class the preference is based on the prefix\suffix, while prefix has precedence + // over suffix if both exists. + // - If after comparing the class, as well as the prefix\suffix, we didn't reach to a conclusion, + // the preference is given to the segment with more variables parts. + // This order mostly follows the intuitive common sense; the major issue comes from preferring the + // prefix over the suffix in the case where both exist. This is derived from the problematic of any + // other type of solution that don't prefere the prefix over the suffix or vice versa. To better + // understanding lets considered the following example: + // In comparing 'foo{x}bar' and 'food{x}ar', unless we are preferring prefix or suffix, we have + // to state that they have the same order. So is the case with 'foo{x}babar' and 'food{x}ar', which + // will lead us to claiming the 'foo{x}bar' and 'foo{x}babar' are from the same order, which they + // clearly are not. + // Taking other approaches to this problem results in similar cases. The only solution is preferring + // either the prefix or the suffix over the other; since we already preferred prefix over suffix + // implicitly (we preferred the prefix only class over the suffix only, we also prefared literal + // over variable, if in the same path segment) that still maintain consistency. + // Therefore: + // - 'food{var}' should be before 'foo{var}'; '{x}.{y}.{z}' should be before '{x}.{y}'. + // - the order between '{var}bar' and '{var}qux' is not important + // - '{x}.{y}' and '{x}_{y}' should have the same order + // - 'foo{x}bar' is less preferred than 'food{x}ar' + // In the above third case - if we are opening the table with allowDuplicate=false, we will throw; + // if we are opening it with allowDuplicate=true we will let it go and might match both templates + // for certain wire candidates. + int IComparable.CompareTo(UriTemplateCompoundPathSegment other) + { + Fx.Assert(other != null, "We are only expected to get here for comparing real compound segments"); + + switch (this.csClass) + { + case CompoundSegmentClass.HasPrefixAndSuffix: + switch (other.csClass) + { + case CompoundSegmentClass.HasPrefixAndSuffix: + return CompareToOtherThatHasPrefixAndSuffix(other); + + case CompoundSegmentClass.HasOnlyPrefix: + case CompoundSegmentClass.HasOnlySuffix: + case CompoundSegmentClass.HasNoPrefixNorSuffix: + return -1; + + default: + Fx.Assert("Invalid other.CompoundSegmentClass"); + return 0; + } + + case CompoundSegmentClass.HasOnlyPrefix: + switch (other.csClass) + { + case CompoundSegmentClass.HasPrefixAndSuffix: + return 1; + + case CompoundSegmentClass.HasOnlyPrefix: + return CompareToOtherThatHasOnlyPrefix(other); + + case CompoundSegmentClass.HasOnlySuffix: + case CompoundSegmentClass.HasNoPrefixNorSuffix: + return -1; + + default: + Fx.Assert("Invalid other.CompoundSegmentClass"); + return 0; + } + + case CompoundSegmentClass.HasOnlySuffix: + switch (other.csClass) + { + case CompoundSegmentClass.HasPrefixAndSuffix: + case CompoundSegmentClass.HasOnlyPrefix: + return 1; + + case CompoundSegmentClass.HasOnlySuffix: + return CompareToOtherThatHasOnlySuffix(other); + + case CompoundSegmentClass.HasNoPrefixNorSuffix: + return -1; + + default: + Fx.Assert("Invalid other.CompoundSegmentClass"); + return 0; + } + + case CompoundSegmentClass.HasNoPrefixNorSuffix: + switch (other.csClass) + { + case CompoundSegmentClass.HasPrefixAndSuffix: + case CompoundSegmentClass.HasOnlyPrefix: + case CompoundSegmentClass.HasOnlySuffix: + return 1; + + case CompoundSegmentClass.HasNoPrefixNorSuffix: + return CompareToOtherThatHasNoPrefixNorSuffix(other); + + default: + Fx.Assert("Invalid other.CompoundSegmentClass"); + return 0; + } + + default: + Fx.Assert("Invalid this.CompoundSegmentClass"); + return 0; + } + } + int CompareToOtherThatHasPrefixAndSuffix(UriTemplateCompoundPathSegment other) + { + Fx.Assert(this.csClass == CompoundSegmentClass.HasPrefixAndSuffix, "Otherwise, how did we got here?"); + Fx.Assert(other.csClass == CompoundSegmentClass.HasPrefixAndSuffix, "Otherwise, how did we got here?"); + + // In this case we are determining the order based on the prefix of the two segments, + // then by their suffix and then based on the number of variables + int prefixOrder = ComparePrefixToOtherPrefix(other); + if (prefixOrder == 0) + { + int suffixOrder = CompareSuffixToOtherSuffix(other); + if (suffixOrder == 0) + { + return (other.varLitPairs.Count - this.varLitPairs.Count); + } + else + { + return suffixOrder; + } + } + else + { + return prefixOrder; + } + } + int CompareToOtherThatHasOnlyPrefix(UriTemplateCompoundPathSegment other) + { + Fx.Assert(this.csClass == CompoundSegmentClass.HasOnlyPrefix, "Otherwise, how did we got here?"); + Fx.Assert(other.csClass == CompoundSegmentClass.HasOnlyPrefix, "Otherwise, how did we got here?"); + + // In this case we are determining the order based on the prefix of the two segments, + // then based on the number of variables + int prefixOrder = ComparePrefixToOtherPrefix(other); + if (prefixOrder == 0) + { + return (other.varLitPairs.Count - this.varLitPairs.Count); + } + else + { + return prefixOrder; + } + } + int CompareToOtherThatHasOnlySuffix(UriTemplateCompoundPathSegment other) + { + Fx.Assert(this.csClass == CompoundSegmentClass.HasOnlySuffix, "Otherwise, how did we got here?"); + Fx.Assert(other.csClass == CompoundSegmentClass.HasOnlySuffix, "Otherwise, how did we got here?"); + + // In this case we are determining the order based on the suffix of the two segments, + // then based on the number of variables + int suffixOrder = CompareSuffixToOtherSuffix(other); + if (suffixOrder == 0) + { + return (other.varLitPairs.Count - this.varLitPairs.Count); + } + else + { + return suffixOrder; + } + } + int CompareToOtherThatHasNoPrefixNorSuffix(UriTemplateCompoundPathSegment other) + { + Fx.Assert(this.csClass == CompoundSegmentClass.HasNoPrefixNorSuffix, "Otherwise, how did we got here?"); + Fx.Assert(other.csClass == CompoundSegmentClass.HasNoPrefixNorSuffix, "Otherwise, how did we got here?"); + + // In this case the order is determined by the number of variables + return (other.varLitPairs.Count - this.varLitPairs.Count); + } + int ComparePrefixToOtherPrefix(UriTemplateCompoundPathSegment other) + { + return string.Compare(other.firstLiteral, this.firstLiteral, StringComparison.OrdinalIgnoreCase); + } + int CompareSuffixToOtherSuffix(UriTemplateCompoundPathSegment other) + { + string reversedSuffix = ReverseString(this.varLitPairs[this.varLitPairs.Count - 1].Literal); + string reversedOtherSuffix = ReverseString(other.varLitPairs[other.varLitPairs.Count - 1].Literal); + return string.Compare(reversedOtherSuffix, reversedSuffix, StringComparison.OrdinalIgnoreCase); + } + static string ReverseString(string stringToReverse) + { + char[] reversedString = new char[stringToReverse.Length]; + for (int i = 0; i < stringToReverse.Length; i++) + { + reversedString[i] = stringToReverse[stringToReverse.Length - i - 1]; + } + return new string(reversedString); + } + + enum CompoundSegmentClass + { + Undefined, + HasPrefixAndSuffix, + HasOnlyPrefix, + HasOnlySuffix, + HasNoPrefixNorSuffix + } + + struct VarAndLitPair + { + readonly string literal; + readonly string varName; + + public VarAndLitPair(string varName, string literal) + { + this.varName = varName; + this.literal = literal; + } + + public string Literal + { + get + { + return this.literal; + } + } + public string VarName + { + get + { + return this.varName; + } + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplateEquivalenceComparer.cs b/src/System.ServiceModel.Web/src/System/UriTemplateEquivalenceComparer.cs new file mode 100644 index 00000000000..09ffb36296e --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplateEquivalenceComparer.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +#pragma warning disable 1634, 1691 // Stops compiler from warning about unknown warnings (for Presharp) + +namespace System +{ + using System.Collections.Generic; + using System.ServiceModel; + using System.Runtime.CompilerServices; + + [TypeForwardedFrom("System.ServiceModel.Web, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public class UriTemplateEquivalenceComparer : IEqualityComparer + { + static UriTemplateEquivalenceComparer instance; + internal static UriTemplateEquivalenceComparer Instance + { + get + { + if (instance == null) + { + // lock-free, fine if we allocate more than one + instance = new UriTemplateEquivalenceComparer(); + } + return instance; + } + } + + public bool Equals(UriTemplate x, UriTemplate y) + { + if (x == null) + { + return y == null; + } + return x.IsEquivalentTo(y); + } + public int GetHashCode(UriTemplate obj) + { + if (obj == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("obj"); + } +#pragma warning disable 56506 // obj.xxx is never null + // prefer final literal segment (common literal prefixes are common in some scenarios) + for (int i = obj.segments.Count - 1; i >= 0; --i) + { + if (obj.segments[i].Nature == UriTemplatePartType.Literal) + { + return obj.segments[i].GetHashCode(); + } + } + return obj.segments.Count + obj.queries.Count; +#pragma warning restore 56506 + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplateHelpers.cs b/src/System.ServiceModel.Web/src/System/UriTemplateHelpers.cs new file mode 100644 index 00000000000..f708b32031e --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplateHelpers.cs @@ -0,0 +1,387 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + using System.Collections.Generic; + using System.Collections.Specialized; + using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; + using System.Runtime; + using System.ServiceModel; + using System.ServiceModel.Channels; + + static class UriTemplateHelpers + { + static UriTemplateQueryComparer queryComparer = new UriTemplateQueryComparer(); + static UriTemplateQueryKeyComparer queryKeyComperar = new UriTemplateQueryKeyComparer(); + + [Conditional("DEBUG")] + public static void AssertCanonical(string s) + { + Fx.Assert(s == s.ToUpperInvariant(), "non-canonicalized"); + } + public static bool CanMatchQueryInterestingly(UriTemplate ut, NameValueCollection query, bool mustBeEspeciallyInteresting) + { + if (ut.queries.Count == 0) + { + return false; // trivial, not interesting + } + string[] queryKeys = query.AllKeys; + foreach (KeyValuePair kvp in ut.queries) + { + string queryKeyName = kvp.Key; + if (kvp.Value.Nature == UriTemplatePartType.Literal) + { + bool queryKeysContainsQueryVarName = false; + for (int i = 0; i < queryKeys.Length; ++i) + { + if (StringComparer.OrdinalIgnoreCase.Equals(queryKeys[i], queryKeyName)) + { + queryKeysContainsQueryVarName = true; + break; + } + } + if (!queryKeysContainsQueryVarName) + { + return false; + } + if (kvp.Value == UriTemplateQueryValue.Empty) + { + if (!string.IsNullOrEmpty(query[queryKeyName])) + { + return false; + } + } + else + { + if (((UriTemplateLiteralQueryValue)(kvp.Value)).AsRawUnescapedString() != query[queryKeyName]) + { + return false; + } + } + } + else + { + if (mustBeEspeciallyInteresting && Array.IndexOf(queryKeys, queryKeyName) == -1) + { + return false; + } + } + } + return true; + } + + public static bool CanMatchQueryTrivially(UriTemplate ut) + { + return (ut.queries.Count == 0); + } + + public static void DisambiguateSamePath(UriTemplate[] array, int a, int b, bool allowDuplicateEquivalentUriTemplates) + { + // [a,b) all have same path + // ensure queries make them unambiguous + Fx.Assert(b > a, "array bug"); + // sort empty queries to front + Array.Sort(array, a, b - a, queryComparer); + if (b - a == 1) + { + return; // if only one, cannot be ambiguous + } + if (!allowDuplicateEquivalentUriTemplates) + { + // ensure at most one empty query and ignore it + if (array[a].queries.Count == 0) + { + a++; + } + if (array[a].queries.Count == 0) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format( + SR.UTTDuplicate, array[a].ToString(), array[a - 1].ToString()))); + } + if (b - a == 1) + { + return; // if only one, cannot be ambiguous + } + } + else + { + while (a < b && array[a].queries.Count == 0) // all equivalent + { + a++; + } + if (b - a <= 1) + { + return; + } + } + Fx.Assert(b > a, "array bug"); + // now consider non-empty queries + // more than one, so enforce that + // forall + // exist set of querystringvars S where + // every op has literal value foreach var in S, and + // those literal tuples are different + EnsureQueriesAreDistinct(array, a, b, allowDuplicateEquivalentUriTemplates); + } + + public static IEqualityComparer GetQueryKeyComparer() + { + return queryKeyComperar; + } + + public static string GetUriPath(Uri uri) + { + return uri.GetComponents(UriComponents.Path | UriComponents.KeepDelimiter, UriFormat.Unescaped); + } + public static bool HasQueryLiteralRequirements(UriTemplate ut) + { + foreach (UriTemplateQueryValue utqv in ut.queries.Values) + { + if (utqv.Nature == UriTemplatePartType.Literal) + { + return true; + } + } + return false; + } + + public static UriTemplatePartType IdentifyPartType(string part) + { + // Identifying the nature of a string - Literal|Compound|Variable + // Algorithem is based on the following steps: + // - Finding the position of the first open curlly brace ('{') and close curlly brace ('}') + // in the string + // - If we don't find any this is a Literal + // - otherwise, we validate that position of the close brace is at least two characters from + // the position of the open brace + // - Then we identify if we are dealing with a compound string or a single variable string + // + var name is not at the string start --> Compound + // + var name is shorter then the entire string (End < Length-2 or End==Length-2 + // and string ends with '/') --> Compound + // + otherwise --> Variable + int varStartIndex = part.IndexOf("{", StringComparison.Ordinal); + int varEndIndex = part.IndexOf("}", StringComparison.Ordinal); + if (varStartIndex == -1) + { + if (varEndIndex != -1) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException( + SR.Format(SR.UTInvalidFormatSegmentOrQueryPart, part))); + } + return UriTemplatePartType.Literal; + } + else + { + if (varEndIndex < varStartIndex + 2) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException( + SR.Format(SR.UTInvalidFormatSegmentOrQueryPart, part))); + } + if (varStartIndex > 0) + { + return UriTemplatePartType.Compound; + } + else if ((varEndIndex < part.Length - 2) || + ((varEndIndex == part.Length - 2) && !part.EndsWith("/", StringComparison.Ordinal))) + { + return UriTemplatePartType.Compound; + } + else + { + return UriTemplatePartType.Variable; + } + } + } + public static bool IsWildcardPath(string path) + { + if (path.IndexOf('/') != -1) + { + return false; + } + UriTemplatePartType partType; + return IsWildcardSegment(path, out partType); + } + + [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", Justification = "This is internal method that needs to return multiple things")] + public static bool IsWildcardSegment(string segment, out UriTemplatePartType type) + { + type = IdentifyPartType(segment); + switch (type) + { + case UriTemplatePartType.Literal: + return (string.Compare(segment, UriTemplate.WildcardPath, StringComparison.Ordinal) == 0); + + case UriTemplatePartType.Compound: + return false; + + case UriTemplatePartType.Variable: + return ((segment.IndexOf(UriTemplate.WildcardPath, StringComparison.Ordinal) == 1) && + !segment.EndsWith("/", StringComparison.Ordinal) && + (segment.Length > UriTemplate.WildcardPath.Length + 2)); + + default: + Fx.Assert("Bad part type identification !"); + return false; + } + } + public static NameValueCollection ParseQueryString(string query) + { + // We are adjusting the parsing of UrlUtility.ParseQueryString, which identify + // ?wsdl as a null key with wsdl as a value + NameValueCollection result = UrlUtility.ParseQueryString(query); + string nullKeyValuesString = result[(string)null]; + if (!string.IsNullOrEmpty(nullKeyValuesString)) + { + result.Remove(null); + string[] nullKeyValues = nullKeyValuesString.Split(','); + for (int i = 0; i < nullKeyValues.Length; i++) + { + result.Add(nullKeyValues[i], null); + } + } + return result; + } + static bool AllTemplatesAreEquivalent(IList array, int a, int b) + { + for (int i = a; i < b - 1; ++i) + { + if (!array[i].IsEquivalentTo(array[i + 1])) + { + return false; + } + } + return true; + } + + static void EnsureQueriesAreDistinct(UriTemplate[] array, int a, int b, bool allowDuplicateEquivalentUriTemplates) + { + Dictionary queryVarNamesWithLiteralVals = new Dictionary(StringComparer.OrdinalIgnoreCase); + for (int i = a; i < b; ++i) + { + foreach (KeyValuePair kvp in array[i].queries) + { + if (kvp.Value.Nature == UriTemplatePartType.Literal) + { + if (!queryVarNamesWithLiteralVals.ContainsKey(kvp.Key)) + { + queryVarNamesWithLiteralVals.Add(kvp.Key, 0); + } + } + } + } + // now we have set of possibilities: + // further refine to only those for whom all templates have literals + Dictionary queryVarNamesAllLiterals = new Dictionary(queryVarNamesWithLiteralVals); + for (int i = a; i < b; ++i) + { + foreach (string s in queryVarNamesWithLiteralVals.Keys) + { + if (!array[i].queries.ContainsKey(s) || (array[i].queries[s].Nature != UriTemplatePartType.Literal)) + { + queryVarNamesAllLiterals.Remove(s); + } + } + } + queryVarNamesWithLiteralVals = null; // ensure we don't reference this variable any more + // now we have the set of names that every operation has as a literal + if (queryVarNamesAllLiterals.Count == 0) + { + if (allowDuplicateEquivalentUriTemplates && AllTemplatesAreEquivalent(array, a, b)) + { + // we're ok, do nothing + } + else + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format( + SR.UTTOtherAmbiguousQueries, array[a].ToString()))); + } + } + // now just ensure that each template has a unique tuple of values for the names + string[][] upsLits = new string[b - a][]; + for (int i = 0; i < b - a; ++i) + { + upsLits[i] = GetQueryLiterals(array[i + a], queryVarNamesAllLiterals); + } + for (int i = 0; i < b - a; ++i) + { + for (int j = i + 1; j < b - a; ++j) + { + if (Same(upsLits[i], upsLits[j])) + { + if (!array[i + a].IsEquivalentTo(array[j + a])) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format( + SR.UTTAmbiguousQueries, array[a + i].ToString(), array[j + a].ToString()))); + } + Fx.Assert(array[i + a].IsEquivalentTo(array[j + a]), "bad equiv logic"); + if (!allowDuplicateEquivalentUriTemplates) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format( + SR.UTTDuplicate, array[a + i].ToString(), array[j + a].ToString()))); + } + } + } + } + // we're good. whew! + } + static string[] GetQueryLiterals(UriTemplate up, Dictionary queryVarNames) + { + string[] queryLitVals = new string[queryVarNames.Count]; + int i = 0; + foreach (string queryVarName in queryVarNames.Keys) + { + Fx.Assert(up.queries.ContainsKey(queryVarName), "query doesn't have name"); + UriTemplateQueryValue utqv = up.queries[queryVarName]; + Fx.Assert(utqv.Nature == UriTemplatePartType.Literal, "query for name is not literal"); + if (utqv == UriTemplateQueryValue.Empty) + { + queryLitVals[i] = null; + } + else + { + queryLitVals[i] = ((UriTemplateLiteralQueryValue)(utqv)).AsRawUnescapedString(); + } + ++i; + } + return queryLitVals; + } + static bool Same(string[] a, string[] b) + { + Fx.Assert(a.Length == b.Length, "arrays not same length"); + for (int i = 0; i < a.Length; ++i) + { + if (a[i] != b[i]) + { + return false; + } + } + return true; + } + + class UriTemplateQueryComparer : IComparer + { + public int Compare(UriTemplate x, UriTemplate y) + { + // sort the empty queries to the front + return Comparer.Default.Compare(x.queries.Count, y.queries.Count); + } + } + class UriTemplateQueryKeyComparer : IEqualityComparer + { + public bool Equals(string x, string y) + { + return (string.Compare(x, y, StringComparison.OrdinalIgnoreCase) == 0); + } + public int GetHashCode(string obj) + { + if (obj == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("obj"); + } + return obj.ToUpperInvariant().GetHashCode(); + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplateLiteralPathSegment.cs b/src/System.ServiceModel.Web/src/System/UriTemplateLiteralPathSegment.cs new file mode 100644 index 00000000000..e582903c46b --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplateLiteralPathSegment.cs @@ -0,0 +1,142 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + using System.Collections.Specialized; + using System.Runtime; + using System.ServiceModel; + using System.Text; + + // thin wrapper around string; use type system to help ensure we + // are doing canonicalization right/consistently + class UriTemplateLiteralPathSegment : UriTemplatePathSegment, IComparable + { + + // segment doesn't store trailing slash + readonly string segment; + static Uri dummyUri = new Uri("http://localhost"); + + UriTemplateLiteralPathSegment(string segment) + : base(segment, UriTemplatePartType.Literal, segment.EndsWith("/", StringComparison.Ordinal)) + { + Fx.Assert(segment != null, "bad literal segment"); + if (this.EndsWithSlash) + { + this.segment = segment.Remove(segment.Length - 1); + } + else + { + this.segment = segment; + } + } + public static new UriTemplateLiteralPathSegment CreateFromUriTemplate(string segment, UriTemplate template) + { + // run it through UriBuilder to escape-if-necessary it + if (string.Compare(segment, "/", StringComparison.Ordinal) == 0) + { + // running an empty segment through UriBuilder has unexpected/wrong results + return new UriTemplateLiteralPathSegment("/"); + } + if (segment.IndexOf(UriTemplate.WildcardPath, StringComparison.Ordinal) != -1) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException( + SR.Format(SR.UTInvalidWildcardInVariableOrLiteral, template.originalTemplate, UriTemplate.WildcardPath))); + } + // '*' is not usually escaped by the Uri\UriBuilder to %2a, since we forbid passing a + // clear character and the workaroud is to pass the escaped form, we should replace the + // escaped form with the regular one. + segment = segment.Replace("%2a", "*").Replace("%2A", "*"); + UriBuilder ub = new UriBuilder(dummyUri); + ub.Path = segment; + string escapedIfNecessarySegment = ub.Uri.AbsolutePath.Substring(1); + if (escapedIfNecessarySegment == string.Empty) + { + // This path through UriBuilder will sometimes '----' various segments + // such as '../' and './'. When this happens and the result is an empty + // string, we should just throw and tell the user we don't handle that. + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("segment", + SR.Format(SR.UTInvalidFormatSegmentOrQueryPart, segment)); + } + return new UriTemplateLiteralPathSegment(escapedIfNecessarySegment); + } + public static UriTemplateLiteralPathSegment CreateFromWireData(string segment) + { + return new UriTemplateLiteralPathSegment(segment); + } + + public string AsUnescapedString() + { + Fx.Assert(this.segment != null, "this should only be called by Bind\\Lookup"); + return Uri.UnescapeDataString(this.segment); + } + public override void Bind(string[] values, ref int valueIndex, StringBuilder path) + { + if (this.EndsWithSlash) + { + path.AppendFormat("{0}/", AsUnescapedString()); + } + else + { + path.Append(AsUnescapedString()); + } + } + + public int CompareTo(UriTemplateLiteralPathSegment other) + { + return StringComparer.OrdinalIgnoreCase.Compare(this.segment, other.segment); + } + + public override bool Equals(object obj) + { + UriTemplateLiteralPathSegment lps = obj as UriTemplateLiteralPathSegment; + if (lps == null) + { + Fx.Assert("why would we ever call this?"); + return false; + } + else + { + return ((this.EndsWithSlash == lps.EndsWithSlash) && + StringComparer.OrdinalIgnoreCase.Equals(this.segment, lps.segment)); + } + } + public override int GetHashCode() + { + return StringComparer.OrdinalIgnoreCase.GetHashCode(this.segment); + } + + public override bool IsEquivalentTo(UriTemplatePathSegment other, bool ignoreTrailingSlash) + { + if (other == null) + { + Fx.Assert("why would we ever call this?"); + return false; + } + if (other.Nature != UriTemplatePartType.Literal) + { + return false; + } + UriTemplateLiteralPathSegment otherAsLiteral = other as UriTemplateLiteralPathSegment; + Fx.Assert(otherAsLiteral != null, "The nature requires that this will be OK"); + return IsMatch(otherAsLiteral, ignoreTrailingSlash); + } + public override bool IsMatch(UriTemplateLiteralPathSegment segment, bool ignoreTrailingSlash) + { + if (!ignoreTrailingSlash && (segment.EndsWithSlash != this.EndsWithSlash)) + { + return false; + } + return (CompareTo(segment) == 0); + } + public bool IsNullOrEmpty() + { + return string.IsNullOrEmpty(this.segment); + } + public override void Lookup(string segment, NameValueCollection boundParameters) + { + Fx.Assert(StringComparer.OrdinalIgnoreCase.Compare(AsUnescapedString(), segment) == 0, + "How can that be? Lookup is expected to be called after IsMatch"); + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplateLiteralQueryValue.cs b/src/System.ServiceModel.Web/src/System/UriTemplateLiteralQueryValue.cs new file mode 100644 index 00000000000..6c8a8944491 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplateLiteralQueryValue.cs @@ -0,0 +1,84 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + using System.Collections.Specialized; + using System.Runtime; + using System.ServiceModel.Channels; + using System.Text; + + // thin wrapper around string; use type system to help ensure we + // are doing canonicalization right/consistently + class UriTemplateLiteralQueryValue : UriTemplateQueryValue, IComparable + { + readonly string value; // an unescaped representation + + UriTemplateLiteralQueryValue(string value) + : base(UriTemplatePartType.Literal) + { + Fx.Assert(value != null, "bad literal value"); + this.value = value; + } + public static UriTemplateLiteralQueryValue CreateFromUriTemplate(string value) + { + return new UriTemplateLiteralQueryValue(UrlUtility.UrlDecode(value, Encoding.UTF8)); + } + + public string AsEscapedString() + { + return UrlUtility.UrlEncode(this.value, Encoding.UTF8); + } + public string AsRawUnescapedString() + { + return this.value; + } + public override void Bind(string keyName, string[] values, ref int valueIndex, StringBuilder query) + { + query.AppendFormat("&{0}={1}", UrlUtility.UrlEncode(keyName, Encoding.UTF8), AsEscapedString()); + } + + public int CompareTo(UriTemplateLiteralQueryValue other) + { + return string.Compare(this.value, other.value, StringComparison.Ordinal); + } + + public override bool Equals(object obj) + { + UriTemplateLiteralQueryValue lqv = obj as UriTemplateLiteralQueryValue; + if (lqv == null) + { + Fx.Assert("why would we ever call this?"); + return false; + } + else + { + return this.value == lqv.value; + } + } + public override int GetHashCode() + { + return this.value.GetHashCode(); + } + + public override bool IsEquivalentTo(UriTemplateQueryValue other) + { + if (other == null) + { + Fx.Assert("why would we ever call this?"); + return false; + } + if (other.Nature != UriTemplatePartType.Literal) + { + return false; + } + UriTemplateLiteralQueryValue otherAsLiteral = other as UriTemplateLiteralQueryValue; + Fx.Assert(otherAsLiteral != null, "The nature requires that this will be OK"); + return (CompareTo(otherAsLiteral) == 0); + } + public override void Lookup(string value, NameValueCollection boundParameters) + { + Fx.Assert(string.Compare(this.value, value, StringComparison.Ordinal) == 0, "How can that be?"); + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplateMatch.cs b/src/System.ServiceModel.Web/src/System/UriTemplateMatch.cs new file mode 100644 index 00000000000..a8ad33e25ec --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplateMatch.cs @@ -0,0 +1,176 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + using System.Collections.ObjectModel; + using System.Collections.Specialized; + using System.Runtime; + using System.Runtime.CompilerServices; + using System.ServiceModel.Channels; + using System.Net; + + [TypeForwardedFrom("System.ServiceModel.Web, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public class UriTemplateMatch + { + Uri baseUri; + NameValueCollection boundVariables; + object data; + NameValueCollection queryParameters; + Collection relativePathSegments; + Uri requestUri; + UriTemplate template; + Collection wildcardPathSegments; + int wildcardSegmentsStartOffset = -1; + Uri originalBaseUri; + HttpRequestMessageProperty requestProp; + + public UriTemplateMatch() + { + } + + public Uri BaseUri // the base address, untouched + { + get + { + if (this.baseUri == null && this.originalBaseUri != null) + { + this.baseUri = UriTemplate.RewriteUri(this.originalBaseUri, this.requestProp.Headers[HttpRequestHeader.Host]); + } + return this.baseUri; + } + set + { + this.baseUri = value; + this.originalBaseUri = null; + this.requestProp = null; + } + } + public NameValueCollection BoundVariables // result of TryLookup, values are decoded + { + get + { + if (this.boundVariables == null) + { + this.boundVariables = new NameValueCollection(); + } + return this.boundVariables; + } + } + public object Data + { + get + { + return this.data; + } + set + { + this.data = value; + } + } + public NameValueCollection QueryParameters // the result of UrlUtility.ParseQueryString (keys and values are decoded) + { + get + { + if (this.queryParameters == null) + { + PopulateQueryParameters(); + } + return this.queryParameters; + } + } + public Collection RelativePathSegments // entire Path (after the base address), decoded + { + get + { + if (this.relativePathSegments == null) + { + this.relativePathSegments = new Collection(); + } + return this.relativePathSegments; + } + } + public Uri RequestUri // uri on the wire, untouched + { + get + { + return this.requestUri; + } + set + { + this.requestUri = value; + } + } + public UriTemplate Template // which one got matched + { + get + { + return this.template; + } + set + { + this.template = value; + } + } + public Collection WildcardPathSegments // just the Path part matched by "*", decoded + { + get + { + if (this.wildcardPathSegments == null) + { + PopulateWildcardSegments(); + } + return this.wildcardPathSegments; + } + } + + internal void SetQueryParameters(NameValueCollection queryParameters) + { + this.queryParameters = new NameValueCollection(queryParameters); + } + internal void SetRelativePathSegments(Collection segments) + { + Fx.Assert(segments != null, "segments != null"); + this.relativePathSegments = segments; + } + internal void SetWildcardPathSegmentsStart(int startOffset) + { + Fx.Assert(startOffset >= 0, "startOffset >= 0"); + this.wildcardSegmentsStartOffset = startOffset; + } + + internal void SetBaseUri(Uri originalBaseUri, HttpRequestMessageProperty requestProp) + { + this.baseUri = null; + this.originalBaseUri = originalBaseUri; + this.requestProp = requestProp; + } + + void PopulateQueryParameters() + { + if (this.requestUri != null) + { + this.queryParameters = UriTemplateHelpers.ParseQueryString(this.requestUri.Query); + } + else + { + this.queryParameters = new NameValueCollection(); + } + } + void PopulateWildcardSegments() + { + if (wildcardSegmentsStartOffset != -1) + { + this.wildcardPathSegments = new Collection(); + for (int i = this.wildcardSegmentsStartOffset; i < this.RelativePathSegments.Count; ++i) + { + this.wildcardPathSegments.Add(this.RelativePathSegments[i]); + } + } + else + { + this.wildcardPathSegments = new Collection(); + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplateMatchException.cs b/src/System.ServiceModel.Web/src/System/UriTemplateMatchException.cs new file mode 100644 index 00000000000..b985a411bd9 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplateMatchException.cs @@ -0,0 +1,30 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + using System.Runtime.Serialization; + using System.Runtime.CompilerServices; + + [TypeForwardedFrom("System.ServiceModel.Web, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + [Serializable] + public class UriTemplateMatchException : SystemException + { + public UriTemplateMatchException() + { + } + public UriTemplateMatchException(string message) + : base(message) + { + } + public UriTemplateMatchException(string message, Exception innerException) + : base(message, innerException) + { + } + [Obsolete(DiagnosticId = "SYSLIB0051")] // add this attribute to the serialization ctor + protected UriTemplateMatchException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplatePartType.cs b/src/System.ServiceModel.Web/src/System/UriTemplatePartType.cs new file mode 100644 index 00000000000..3400f171256 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplatePartType.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + enum UriTemplatePartType + { + Literal, + Compound, + Variable + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplatePathPartiallyEquivalentSet.cs b/src/System.ServiceModel.Web/src/System/UriTemplatePathPartiallyEquivalentSet.cs new file mode 100644 index 00000000000..c18fb4f32d9 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplatePathPartiallyEquivalentSet.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + using System.Collections.Generic; + + // This class was named UriTemplatePathEquivalentSet in the Orcas bits, where it used to + // represent a set of uri templates, which are equivalent in thier path. The introduction + // of terminal defaults, caused it to be no longer true; now it is representing a set + // of templates, which are equivalent in their path till a certian point, which is stored + // in the segmentsCount field. To highlight that fact the class was renamed as + // UriTemplatePathPartiallyEquivalentSet. + class UriTemplatePathPartiallyEquivalentSet + { + List> kvps; + int segmentsCount; + + public UriTemplatePathPartiallyEquivalentSet(int segmentsCount) + { + this.segmentsCount = segmentsCount; + this.kvps = new List>(); + } + public List> Items + { + get + { + return this.kvps; + } + } + + public int SegmentsCount + { + get + { + return this.segmentsCount; + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplatePathSegment.cs b/src/System.ServiceModel.Web/src/System/UriTemplatePathSegment.cs new file mode 100644 index 00000000000..ad020115d1c --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplatePathSegment.cs @@ -0,0 +1,88 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + using System.Collections.Specialized; + using System.Diagnostics; + using System.Runtime; + using System.Text; + + // This represents a Path segment, which can either be a Literal, a Variable or a Compound + [DebuggerDisplay("Segment={originalSegment} Nature={nature}")] + abstract class UriTemplatePathSegment + { + readonly bool endsWithSlash; + readonly UriTemplatePartType nature; + readonly string originalSegment; + + protected UriTemplatePathSegment(string originalSegment, UriTemplatePartType nature, + bool endsWithSlash) + { + this.originalSegment = originalSegment; + this.nature = nature; + this.endsWithSlash = endsWithSlash; + } + public bool EndsWithSlash + { + get + { + return this.endsWithSlash; + } + } + public UriTemplatePartType Nature + { + get + { + return this.nature; + } + } + + public string OriginalSegment + { + get + { + return this.originalSegment; + } + } + public static UriTemplatePathSegment CreateFromUriTemplate(string segment, UriTemplate template) + { + // Identifying the type of segment - Literal|Compound|Variable + switch (UriTemplateHelpers.IdentifyPartType(segment)) + { + case UriTemplatePartType.Literal: + return UriTemplateLiteralPathSegment.CreateFromUriTemplate(segment, template); + + case UriTemplatePartType.Compound: + return UriTemplateCompoundPathSegment.CreateFromUriTemplate(segment, template); + + case UriTemplatePartType.Variable: + if (segment.EndsWith("/", StringComparison.Ordinal)) + { + string varName = template.AddPathVariable(UriTemplatePartType.Variable, + segment.Substring(1, segment.Length - 3)); + return new UriTemplateVariablePathSegment(segment, true, varName); + } + else + { + string varName = template.AddPathVariable(UriTemplatePartType.Variable, + segment.Substring(1, segment.Length - 2)); + return new UriTemplateVariablePathSegment(segment, false, varName); + } + + default: + Fx.Assert("Invalid value from IdentifyStringNature"); + return null; + } + } + public abstract void Bind(string[] values, ref int valueIndex, StringBuilder path); + + public abstract bool IsEquivalentTo(UriTemplatePathSegment other, bool ignoreTrailingSlash); + public bool IsMatch(UriTemplateLiteralPathSegment segment) + { + return IsMatch(segment, false); + } + public abstract bool IsMatch(UriTemplateLiteralPathSegment segment, bool ignoreTrailingSlash); + public abstract void Lookup(string segment, NameValueCollection boundParameters); + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplateQueryValue.cs b/src/System.ServiceModel.Web/src/System/UriTemplateQueryValue.cs new file mode 100644 index 00000000000..ecc0929fa1b --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplateQueryValue.cs @@ -0,0 +1,104 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + using System.Collections.Specialized; + using System.Runtime; + using System.ServiceModel; + using System.ServiceModel.Channels; + using System.Text; + + // This represents a Query value, which can either be Empty, a Literal or a Variable + abstract class UriTemplateQueryValue + { + + readonly UriTemplatePartType nature; + static UriTemplateQueryValue empty = new EmptyUriTemplateQueryValue(); + + protected UriTemplateQueryValue(UriTemplatePartType nature) + { + this.nature = nature; + } + + public static UriTemplateQueryValue Empty + { + get + { + return UriTemplateQueryValue.empty; + } + } + + public UriTemplatePartType Nature + { + get + { + return this.nature; + } + } + public static UriTemplateQueryValue CreateFromUriTemplate(string value, UriTemplate template) + { + // Checking for empty value + if (value == null) + { + return UriTemplateQueryValue.Empty; + } + // Identifying the type of value - Literal|Compound|Variable + switch (UriTemplateHelpers.IdentifyPartType(value)) + { + case UriTemplatePartType.Literal: + return UriTemplateLiteralQueryValue.CreateFromUriTemplate(value); + + case UriTemplatePartType.Compound: + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format( + SR.UTQueryCannotHaveCompoundValue, template.originalTemplate))); + + case UriTemplatePartType.Variable: + return new UriTemplateVariableQueryValue(template.AddQueryVariable(value.Substring(1, value.Length - 2))); + + default: + Fx.Assert("Invalid value from IdentifyStringNature"); + return null; + } + } + + public static bool IsNullOrEmpty(UriTemplateQueryValue utqv) + { + if (utqv == null) + { + return true; + } + if (utqv == UriTemplateQueryValue.Empty) + { + return true; + } + return false; + } + public abstract void Bind(string keyName, string[] values, ref int valueIndex, StringBuilder query); + + public abstract bool IsEquivalentTo(UriTemplateQueryValue other); + public abstract void Lookup(string value, NameValueCollection boundParameters); + + class EmptyUriTemplateQueryValue : UriTemplateQueryValue + { + public EmptyUriTemplateQueryValue() + : base(UriTemplatePartType.Literal) + { + } + public override void Bind(string keyName, string[] values, ref int valueIndex, StringBuilder query) + { + query.AppendFormat("&{0}", UrlUtility.UrlEncode(keyName, Encoding.UTF8)); + } + + public override bool IsEquivalentTo(UriTemplateQueryValue other) + { + return (other == UriTemplateQueryValue.Empty); + } + public override void Lookup(string value, NameValueCollection boundParameters) + { + Fx.Assert(string.IsNullOrEmpty(value), "shouldn't have a value"); + } + } + } + +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplateTable.cs b/src/System.ServiceModel.Web/src/System/UriTemplateTable.cs new file mode 100644 index 00000000000..6ac2a9c242d --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplateTable.cs @@ -0,0 +1,607 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Collections.Specialized; + using System.Diagnostics; + using System.Diagnostics.CodeAnalysis; + using System.Runtime; + using System.ServiceModel; + using System.Runtime.CompilerServices; + + // this class is thread-safe + [TypeForwardedFrom("System.ServiceModel.Web, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")] + public class UriTemplateTable + { + Uri baseAddress; + string basePath; + Dictionary fastPathTable; // key is uri.PathAndQuery, fastPathTable may be null + bool noTemplateHasQueryPart; + int numSegmentsInBaseAddress; + Uri originalUncanonicalizedBaseAddress; + UriTemplateTrieNode rootNode; + UriTemplatesCollection templates; + object thisLock; + bool addTrailingSlashToBaseAddress; + + public UriTemplateTable() + : this(null, null, true) + { + } + public UriTemplateTable(IEnumerable> keyValuePairs) + : this(null, keyValuePairs, true) + { + } + public UriTemplateTable(Uri baseAddress) + : this(baseAddress, null, true) + { + } + + internal UriTemplateTable(Uri baseAddress, bool addTrailingSlashToBaseAddress) + : this(baseAddress, null, addTrailingSlashToBaseAddress) + { + } + + public UriTemplateTable(Uri baseAddress, IEnumerable> keyValuePairs) + : this(baseAddress, keyValuePairs, true) + { + } + + internal UriTemplateTable(Uri baseAddress, IEnumerable> keyValuePairs, bool addTrailingSlashToBaseAddress) + { + if (baseAddress != null && !baseAddress.IsAbsoluteUri) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("baseAddress", SR.Format( + SR.UTTMustBeAbsolute)); + } + + this.addTrailingSlashToBaseAddress = addTrailingSlashToBaseAddress; + this.originalUncanonicalizedBaseAddress = baseAddress; + + if (keyValuePairs != null) + { + this.templates = new UriTemplatesCollection(keyValuePairs); + } + else + { + this.templates = new UriTemplatesCollection(); + } + + this.thisLock = new object(); + this.baseAddress = baseAddress; + NormalizeBaseAddress(); + } + + public Uri BaseAddress + { + get + { + return this.baseAddress; + } + set + { + if (value == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value"); + } + lock (this.thisLock) + { + if (this.IsReadOnly) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( + SR.Format(SR.UTTCannotChangeBaseAddress))); + } + else + { + if (!value.IsAbsoluteUri) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("value", SR.Format( + SR.UTTBaseAddressMustBeAbsolute)); + } + else + { + this.originalUncanonicalizedBaseAddress = value; + this.baseAddress = value; + NormalizeBaseAddress(); + } + } + } + } + } + + public Uri OriginalBaseAddress + { + get + { + return this.originalUncanonicalizedBaseAddress; + } + } + + public bool IsReadOnly + { + get + { + return this.templates.IsFrozen; + } + } + public IList> KeyValuePairs + { + get + { + return this.templates; + } + } + + public void MakeReadOnly(bool allowDuplicateEquivalentUriTemplates) + { + // idempotent + lock (this.thisLock) + { + if (!this.IsReadOnly) + { + this.templates.Freeze(); + Validate(allowDuplicateEquivalentUriTemplates); + ConstructFastPathTable(); + } + } + } + public Collection Match(Uri uri) + { + if (uri == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("uri"); + } + if (!uri.IsAbsoluteUri) + { + return None(); + } + + this.MakeReadOnly(true); + + // Matching path : + Collection relativeSegments; + IList candidates; + if (!FastComputeRelativeSegmentsAndLookup(uri, out relativeSegments, out candidates)) + { + return None(); + } + // Matching query : + NameValueCollection queryParameters = null; + if (!this.noTemplateHasQueryPart && AtLeastOneCandidateHasQueryPart(candidates)) + { + Collection nextCandidates = new Collection(); + Fx.Assert(nextCandidates.Count == 0, "nextCandidates should be empty"); + + // then deal with query + queryParameters = UriTemplateHelpers.ParseQueryString(uri.Query); + bool mustBeEspeciallyInteresting = NoCandidateHasQueryLiteralRequirementsAndThereIsAnEmptyFallback(candidates); + for (int i = 0; i < candidates.Count; i++) + { + if (UriTemplateHelpers.CanMatchQueryInterestingly(candidates[i].Template, queryParameters, mustBeEspeciallyInteresting)) + { + nextCandidates.Add(candidates[i]); + } + } + if (nextCandidates.Count > 1) + { + Fx.Assert(AllEquivalent(nextCandidates, 0, nextCandidates.Count), "demux algorithm problem, multiple non-equivalent matches"); + } + + if (nextCandidates.Count == 0) + { + for (int i = 0; i < candidates.Count; i++) + { + if (UriTemplateHelpers.CanMatchQueryTrivially(candidates[i].Template)) + { + nextCandidates.Add(candidates[i]); + } + } + } + if (nextCandidates.Count == 0) + { + return None(); + } + if (nextCandidates.Count > 1) + { + Fx.Assert(AllEquivalent(nextCandidates, 0, nextCandidates.Count), "demux algorithm problem, multiple non-equivalent matches"); + } + + candidates = nextCandidates; + } + // Verifying that we have not broken the allowDuplicates settings because of terminal defaults + // This situation can be caused when we are hosting ".../" and ".../{foo=xyz}" in the same + // table. They are not equivalent; yet they reside together in the same path partially-equivalent + // set. If we hit a uri that ends up in that particular end-of-path set, we want to provide the + // user only the 'best' match and not both; thus preventing inconsistancy between the MakeReadonly + // settings and the matching results. We will assume that the 'best' matches will be the ones with + // the smallest number of segments - this will prefer ".../" over ".../{x=1}[/...]". + if (NotAllCandidatesArePathFullyEquivalent(candidates)) + { + Collection nextCandidates = new Collection(); + int minSegmentsCount = -1; + for (int i = 0; i < candidates.Count; i++) + { + UriTemplateTableMatchCandidate candidate = candidates[i]; + if (minSegmentsCount == -1) + { + minSegmentsCount = candidate.Template.segments.Count; + nextCandidates.Add(candidate); + } + else if (candidate.Template.segments.Count < minSegmentsCount) + { + minSegmentsCount = candidate.Template.segments.Count; + nextCandidates.Clear(); + nextCandidates.Add(candidate); + } + else if (candidate.Template.segments.Count == minSegmentsCount) + { + nextCandidates.Add(candidate); + } + } + Fx.Assert(minSegmentsCount != -1, "At least the first entry in the list should be kept"); + Fx.Assert(nextCandidates.Count >= 1, "At least the first entry in the list should be kept"); + Fx.Assert(nextCandidates[0].Template.segments.Count == minSegmentsCount, "Trivial"); + candidates = nextCandidates; + } + + // Building the actual result + Collection actualResults = new Collection(); + for (int i = 0; i < candidates.Count; i++) + { + UriTemplateTableMatchCandidate candidate = candidates[i]; + UriTemplateMatch match = candidate.Template.CreateUriTemplateMatch(this.originalUncanonicalizedBaseAddress, + uri, candidate.Data, candidate.SegmentsCount, relativeSegments, queryParameters); + actualResults.Add(match); + } + return actualResults; + } + public UriTemplateMatch MatchSingle(Uri uri) + { + Collection c = this.Match(uri); + if (c.Count == 0) + { + return null; + } + if (c.Count == 1) + { + return c[0]; + } + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new UriTemplateMatchException(SR.Format( + SR.UTTMultipleMatches))); + } + + [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This method is called within a Debug assert")] + static bool AllEquivalent(IList list, int a, int b) + { + for (int i = a; i < b - 1; ++i) + { + if (!list[i].Template.IsPathPartiallyEquivalentAt(list[i + 1].Template, list[i].SegmentsCount)) + { + return false; + } + if (!list[i].Template.IsQueryEquivalent(list[i + 1].Template)) + { + return false; + } + } + return true; + } + + static bool AtLeastOneCandidateHasQueryPart(IList candidates) + { + for (int i = 0; i < candidates.Count; i++) + { + if (!UriTemplateHelpers.CanMatchQueryTrivially(candidates[i].Template)) + { + return true; + } + } + return false; + } + static bool NoCandidateHasQueryLiteralRequirementsAndThereIsAnEmptyFallback( + IList candidates) + { + bool thereIsAmEmptyFallback = false; + for (int i = 0; i < candidates.Count; i++) + { + if (UriTemplateHelpers.HasQueryLiteralRequirements(candidates[i].Template)) + { + return false; + } + if (candidates[i].Template.queries.Count == 0) + { + thereIsAmEmptyFallback = true; + } + } + return thereIsAmEmptyFallback; + } + + static Collection None() + { + return new Collection(); + } + static bool NotAllCandidatesArePathFullyEquivalent(IList candidates) + { + if (candidates.Count <= 1) + { + return false; + } + + int segmentsCount = -1; + for (int i = 0; i < candidates.Count; i++) + { + if (segmentsCount == -1) + { + segmentsCount = candidates[i].Template.segments.Count; + } + else if (segmentsCount != candidates[i].Template.segments.Count) + { + return true; + } + } + return false; + } + + bool ComputeRelativeSegmentsAndLookup(Uri uri, + ICollection relativePathSegments, // add to this + ICollection candidates) // matched candidates + { + string[] uriSegments = uri.Segments; + int numRelativeSegments = uriSegments.Length - this.numSegmentsInBaseAddress; + Fx.Assert(numRelativeSegments >= 0, "bad num segments"); + UriTemplateLiteralPathSegment[] uSegments = new UriTemplateLiteralPathSegment[numRelativeSegments]; + for (int i = 0; i < numRelativeSegments; ++i) + { + string seg = uriSegments[i + this.numSegmentsInBaseAddress]; + // compute representation for matching + UriTemplateLiteralPathSegment lps = UriTemplateLiteralPathSegment.CreateFromWireData(seg); + uSegments[i] = lps; + // compute representation to project out into results + string relPathSeg = Uri.UnescapeDataString(seg); + if (lps.EndsWithSlash) + { + Fx.Assert(relPathSeg.EndsWith("/", StringComparison.Ordinal), "problem with relative path segment"); + relPathSeg = relPathSeg.Substring(0, relPathSeg.Length - 1); // trim slash + } + relativePathSegments.Add(relPathSeg); + } + return rootNode.Match(uSegments, candidates); + } + void ConstructFastPathTable() + { + this.noTemplateHasQueryPart = true; + foreach (KeyValuePair kvp in this.templates) + { + UriTemplate ut = kvp.Key; + if (!UriTemplateHelpers.CanMatchQueryTrivially(ut)) + { + this.noTemplateHasQueryPart = false; + } + if (ut.HasNoVariables && !ut.HasWildcard) + { + // eligible for fast path + if (this.fastPathTable == null) + { + this.fastPathTable = new Dictionary(); + } + Uri uri = ut.BindByPosition(this.originalUncanonicalizedBaseAddress); + string uriPath = UriTemplateHelpers.GetUriPath(uri); + if (this.fastPathTable.ContainsKey(uriPath)) + { + // nothing to do, we've already seen it + } + else + { + FastPathInfo fpInfo = new FastPathInfo(); + if (ComputeRelativeSegmentsAndLookup(uri, fpInfo.RelativePathSegments, + fpInfo.Candidates)) + { + fpInfo.Freeze(); + this.fastPathTable.Add(uriPath, fpInfo); + } + } + } + } + } + // this method checks the literal cache for a match if none, goes through the slower path of cracking the segments + bool FastComputeRelativeSegmentsAndLookup(Uri uri, out Collection relativePathSegments, + out IList candidates) + { + // Consider fast-path and lookup + // return false if not under base uri + string uriPath = UriTemplateHelpers.GetUriPath(uri); + FastPathInfo fpInfo = null; + if ((this.fastPathTable != null) && this.fastPathTable.TryGetValue(uriPath, out fpInfo)) + { + relativePathSegments = fpInfo.RelativePathSegments; + candidates = fpInfo.Candidates; + VerifyThatFastPathAndSlowPathHaveSameResults(uri, relativePathSegments, candidates); + return true; + } + else + { + relativePathSegments = new Collection(); + candidates = new Collection(); + return SlowComputeRelativeSegmentsAndLookup(uri, uriPath, relativePathSegments, candidates); + } + } + + void NormalizeBaseAddress() + { + if (this.baseAddress != null) + { + // ensure trailing slash on baseAddress, so that IsBaseOf will work later + UriBuilder ub = new UriBuilder(this.baseAddress); + if (this.addTrailingSlashToBaseAddress && !ub.Path.EndsWith("/", StringComparison.Ordinal)) + { + ub.Path = ub.Path + "/"; + } + ub.Host = "localhost"; // always normalize to localhost + ub.Port = -1; + ub.UserName = null; + ub.Password = null; + ub.Path = ub.Path.ToUpperInvariant(); + ub.Scheme = Uri.UriSchemeHttp; + this.baseAddress = ub.Uri; + basePath = UriTemplateHelpers.GetUriPath(this.baseAddress); + } + } + bool SlowComputeRelativeSegmentsAndLookup(Uri uri, string uriPath, Collection relativePathSegments, + ICollection candidates) + { + // ensure 'under' the base address + if (uriPath.Length < basePath.Length) + { + return false; + } + + if (!uriPath.StartsWith(basePath, StringComparison.OrdinalIgnoreCase)) + { + return false; + } + else + { + // uriPath StartsWith basePath, but this check is not enough - basePath 'service1' should not match with uriPath 'service123' + // make sure that after the match the next character is /, this is to avoid a uriPath of the form /service12/ matching with a basepath of the form /service1 + if (uriPath.Length > basePath.Length && !basePath.EndsWith("/", StringComparison.Ordinal) && uriPath[basePath.Length] != '/') + { + return false; + } + } + + return ComputeRelativeSegmentsAndLookup(uri, relativePathSegments, candidates); + } + + void Validate(bool allowDuplicateEquivalentUriTemplates) + { + if (this.baseAddress == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format( + SR.UTTBaseAddressNotSet))); + } + this.numSegmentsInBaseAddress = this.baseAddress.Segments.Length; + if (this.templates.Count == 0) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format( + SR.UTTEmptyKeyValuePairs))); + } + // build the trie and + // validate that forall Uri u, at most one UriTemplate is a best match for u + rootNode = UriTemplateTrieNode.Make(this.templates, allowDuplicateEquivalentUriTemplates); + } + [Conditional("DEBUG")] + void VerifyThatFastPathAndSlowPathHaveSameResults(Uri uri, Collection fastPathRelativePathSegments, + IList fastPathCandidates) + { + Collection slowPathRelativePathSegments = new Collection(); + List slowPathCandidates = new List(); + if (!SlowComputeRelativeSegmentsAndLookup(uri, UriTemplateHelpers.GetUriPath(uri), + slowPathRelativePathSegments, slowPathCandidates)) + { + Fx.Assert("fast path yielded a result but slow path yielded no result"); + } + // compare results + if (fastPathRelativePathSegments.Count != slowPathRelativePathSegments.Count) + { + Fx.Assert("fast path yielded different number of segments from slow path"); + } + for (int i = 0; i < fastPathRelativePathSegments.Count; ++i) + { + if (fastPathRelativePathSegments[i] != slowPathRelativePathSegments[i]) + { + Fx.Assert("fast path yielded different segments from slow path"); + } + } + if (fastPathCandidates.Count != slowPathCandidates.Count) + { + Fx.Assert("fast path yielded different number of candidates from slow path"); + } + for (int i = 0; i < fastPathCandidates.Count; i++) + { + if (!slowPathCandidates.Contains(fastPathCandidates[i])) + { + Fx.Assert("fast path yielded different candidates from slow path"); + } + } + } + + class FastPathInfo + { + FreezableCollection candidates; + FreezableCollection relativePathSegments; + + public FastPathInfo() + { + this.relativePathSegments = new FreezableCollection(); + this.candidates = new FreezableCollection(); + } + public Collection Candidates + { + get + { + return this.candidates; + } + } + + public Collection RelativePathSegments + { + get + { + return this.relativePathSegments; + } + } + + public void Freeze() + { + this.relativePathSegments.Freeze(); + this.candidates.Freeze(); + } + } + + class UriTemplatesCollection : FreezableCollection> + { + public UriTemplatesCollection() + : base() + { + } + [SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors", Justification = "This is a private class; virtual methods cannot be overriden")] + public UriTemplatesCollection(IEnumerable> keyValuePairs) + : base() + { + foreach (KeyValuePair kvp in keyValuePairs) + { + ThrowIfInvalid(kvp.Key, "keyValuePairs"); + base.Add(kvp); + } + } + + protected override void InsertItem(int index, KeyValuePair item) + { + ThrowIfInvalid(item.Key, "item"); + base.InsertItem(index, item); + } + protected override void SetItem(int index, KeyValuePair item) + { + ThrowIfInvalid(item.Key, "item"); + base.SetItem(index, item); + } + + static void ThrowIfInvalid(UriTemplate template, string argName) + { + if (template == null) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(argName, + SR.Format(SR.UTTNullTemplateKey)); + } + if (template.IgnoreTrailingSlash) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(argName, + SR.Format(SR.UTTInvalidTemplateKey, template)); + } + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplateTableMatchCandidate.cs b/src/System.ServiceModel.Web/src/System/UriTemplateTableMatchCandidate.cs new file mode 100644 index 00000000000..6a73be1d0e1 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplateTableMatchCandidate.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + struct UriTemplateTableMatchCandidate + { + readonly object data; + readonly int segmentsCount; + readonly UriTemplate template; + + public UriTemplateTableMatchCandidate(UriTemplate template, int segmentsCount, object data) + { + this.template = template; + this.segmentsCount = segmentsCount; + this.data = data; + } + public object Data + { + get + { + return this.data; + } + } + public int SegmentsCount + { + get + { + return this.segmentsCount; + } + } + + public UriTemplate Template + { + get + { + return this.template; + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplateTrieIntraNodeLocation.cs b/src/System.ServiceModel.Web/src/System/UriTemplateTrieIntraNodeLocation.cs new file mode 100644 index 00000000000..a40b1e987da --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplateTrieIntraNodeLocation.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + enum UriTemplateTrieIntraNodeLocation + { + BeforeLiteral, + AfterLiteral, + AfterCompound, + AfterVariable, + } + +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplateTrieLocation.cs b/src/System.ServiceModel.Web/src/System/UriTemplateTrieLocation.cs new file mode 100644 index 00000000000..b76c979361e --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplateTrieLocation.cs @@ -0,0 +1,17 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + class UriTemplateTrieLocation + { + public UriTemplateTrieIntraNodeLocation locationWithin; + public UriTemplateTrieNode node; + public UriTemplateTrieLocation(UriTemplateTrieNode n, UriTemplateTrieIntraNodeLocation i) + { + this.node = n; + this.locationWithin = i; + } + } + +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplateTrieNode.cs b/src/System.ServiceModel.Web/src/System/UriTemplateTrieNode.cs new file mode 100644 index 00000000000..d29034917a3 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplateTrieNode.cs @@ -0,0 +1,805 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + using System.Collections.Generic; + using System.Collections.ObjectModel; + using System.Runtime; + using System.ServiceModel; + + class UriTemplateTrieNode + { + int depth; // relative segment depth (root = 0) + UriTemplatePathPartiallyEquivalentSet endOfPath; // matches the non-existent segment at the end of a slash-terminated path + AscendingSortedCompoundSegmentsCollection finalCompoundSegment; // matches e.g. "{var}.{var}" + Dictionary finalLiteralSegment; // matches e.g. "segmentThatDoesntEndInSlash" + UriTemplatePathPartiallyEquivalentSet finalVariableSegment; // matches e.g. "{var}" + AscendingSortedCompoundSegmentsCollection nextCompoundSegment; // all are AfterLiteral; matches e.g. "{var}.{var}/" + Dictionary nextLiteralSegment; // all are BeforeLiteral; matches e.g. "path/" + UriTemplateTrieLocation nextVariableSegment; // is BeforeLiteral; matches e.g. "{var}/" + UriTemplateTrieLocation onFailure; // points to parent, at 'after me' + UriTemplatePathPartiallyEquivalentSet star; // matches any "extra/path/segments" at the end + + UriTemplateTrieNode(int depth) + { + this.depth = depth; + this.nextLiteralSegment = null; + this.nextCompoundSegment = null; + this.finalLiteralSegment = null; + this.finalCompoundSegment = null; + this.finalVariableSegment = new UriTemplatePathPartiallyEquivalentSet(depth + 1); + this.star = new UriTemplatePathPartiallyEquivalentSet(depth); + this.endOfPath = new UriTemplatePathPartiallyEquivalentSet(depth); + } + + public static UriTemplateTrieNode Make(IEnumerable> keyValuePairs, + bool allowDuplicateEquivalentUriTemplates) + { + // given a UTT at MakeReadOnly time, build the trie + // note that root.onFailure == null; + UriTemplateTrieNode root = new UriTemplateTrieNode(0); + foreach (KeyValuePair kvp in keyValuePairs) + { + Add(root, kvp); + } + Validate(root, allowDuplicateEquivalentUriTemplates); + return root; + } + + public bool Match(UriTemplateLiteralPathSegment[] wireData, ICollection candidates) + { + UriTemplateTrieLocation currentLocation = new UriTemplateTrieLocation(this, UriTemplateTrieIntraNodeLocation.BeforeLiteral); + return GetMatch(currentLocation, wireData, candidates); + } + + static void Add(UriTemplateTrieNode root, KeyValuePair kvp) + { + // Currently UTT doesn't support teplates with ignoreTrailingSlash == true; thus we + // don't care about supporting it in the trie as well. + UriTemplateTrieNode current = root; + UriTemplate ut = kvp.Key; + bool needProcessingOnFinalNode = ((ut.segments.Count == 0) || ut.HasWildcard || + ut.segments[ut.segments.Count - 1].EndsWithSlash); + for (int i = 0; i < ut.segments.Count; ++i) + { + if (i >= ut.firstOptionalSegment) + { + current.endOfPath.Items.Add(kvp); + } + UriTemplatePathSegment ps = ut.segments[i]; + if (!ps.EndsWithSlash) + { + Fx.Assert(i == ut.segments.Count - 1, "only the last segment can !EndsWithSlash"); + Fx.Assert(!ut.HasWildcard, "path star cannot have !EndsWithSlash"); + switch (ps.Nature) + { + case UriTemplatePartType.Literal: + current.AddFinalLiteralSegment(ps as UriTemplateLiteralPathSegment, kvp); + break; + + case UriTemplatePartType.Compound: + current.AddFinalCompoundSegment(ps as UriTemplateCompoundPathSegment, kvp); + break; + + case UriTemplatePartType.Variable: + current.finalVariableSegment.Items.Add(kvp); + break; + + default: + Fx.Assert("Invalid value as PathSegment.Nature"); + break; + } + } + else + { + Fx.Assert(ps.EndsWithSlash, "ps.EndsWithSlash"); + switch (ps.Nature) + { + case UriTemplatePartType.Literal: + current = current.AddNextLiteralSegment(ps as UriTemplateLiteralPathSegment); + break; + + case UriTemplatePartType.Compound: + current = current.AddNextCompoundSegment(ps as UriTemplateCompoundPathSegment); + break; + + case UriTemplatePartType.Variable: + current = current.AddNextVariableSegment(); + break; + + default: + Fx.Assert("Invalid value as PathSegment.Nature"); + break; + } + } + } + if (needProcessingOnFinalNode) + { + // if the last segment ended in a slash, there is still more to do + if (ut.HasWildcard) + { + // e.g. "path1/path2/*" + current.star.Items.Add(kvp); + } + else + { + // e.g. "path1/path2/" + current.endOfPath.Items.Add(kvp); + } + } + } + + static bool CheckMultipleMatches(IList> locationsSet, UriTemplateLiteralPathSegment[] wireData, + ICollection candidates) + { + bool result = false; + for (int i = 0; ((i < locationsSet.Count) && !result); i++) + { + for (int j = 0; j < locationsSet[i].Count; j++) + { + if (GetMatch(locationsSet[i][j], wireData, candidates)) + { + result = true; + } + } + } + return result; + } + static bool GetMatch(UriTemplateTrieLocation location, UriTemplateLiteralPathSegment[] wireData, + ICollection candidates) + { + int initialDepth = location.node.depth; + SingleLocationOrLocationsSet nextStep; + UriTemplatePathPartiallyEquivalentSet answer; + do + { + if (TryMatch(wireData, location, out answer, out nextStep)) + { + if (answer != null) + { + for (int i = 0; i < answer.Items.Count; i++) + { + candidates.Add(new UriTemplateTableMatchCandidate(answer.Items[i].Key, answer.SegmentsCount, + answer.Items[i].Value)); + } + } + return true; + } + if (nextStep.IsSingle) + { + location = nextStep.SingleLocation; + } + else + { + Fx.Assert(nextStep.LocationsSet != null, "This should be set to a valid value by TryMatch"); + if (CheckMultipleMatches(nextStep.LocationsSet, wireData, candidates)) + { + return true; + } + location = GetFailureLocationFromLocationsSet(nextStep.LocationsSet); + } + } while ((location != null) && (location.node.depth >= initialDepth)); + + // we walked the whole trie down and found nothing + return false; + } + static bool TryMatch(UriTemplateLiteralPathSegment[] wireUriSegments, UriTemplateTrieLocation currentLocation, + out UriTemplatePathPartiallyEquivalentSet success, out SingleLocationOrLocationsSet nextStep) + { + // if returns true, success is set to answer + // if returns false, nextStep is set to next place to look + success = null; + nextStep = new SingleLocationOrLocationsSet(); + + if (wireUriSegments.Length <= currentLocation.node.depth) + { + Fx.Assert(wireUriSegments.Length == 0 || wireUriSegments[wireUriSegments.Length - 1].EndsWithSlash, + "we should not have traversed this deep into the trie unless the wire path ended in a slash"); + + if (currentLocation.node.endOfPath.Items.Count != 0) + { + // exact match of e.g. "path1/path2/" + success = currentLocation.node.endOfPath; + return true; + } + else if (currentLocation.node.star.Items.Count != 0) + { + // inexact match of e.g. WIRE("path1/path2/") against TEMPLATE("path1/path2/*") + success = currentLocation.node.star; + return true; + } + else + { + nextStep = new SingleLocationOrLocationsSet(currentLocation.node.onFailure); + return false; + } + } + else + { + UriTemplateLiteralPathSegment curWireSeg = wireUriSegments[currentLocation.node.depth]; + bool considerLiteral = false; + bool considerCompound = false; + bool considerVariable = false; + bool considerStar = false; + switch (currentLocation.locationWithin) + { + case UriTemplateTrieIntraNodeLocation.BeforeLiteral: + considerLiteral = true; + considerCompound = true; + considerVariable = true; + considerStar = true; + break; + case UriTemplateTrieIntraNodeLocation.AfterLiteral: + considerLiteral = false; + considerCompound = true; + considerVariable = true; + considerStar = true; + break; + case UriTemplateTrieIntraNodeLocation.AfterCompound: + considerLiteral = false; + considerCompound = false; + considerVariable = true; + considerStar = true; + break; + case UriTemplateTrieIntraNodeLocation.AfterVariable: + considerLiteral = false; + considerCompound = false; + considerVariable = false; + considerStar = true; + break; + default: + Fx.Assert("bad kind"); + break; + } + if (curWireSeg.EndsWithSlash) + { + IList> compoundLocationsSet; + + if (considerLiteral && currentLocation.node.nextLiteralSegment != null && + currentLocation.node.nextLiteralSegment.ContainsKey(curWireSeg)) + { + nextStep = new SingleLocationOrLocationsSet(currentLocation.node.nextLiteralSegment[curWireSeg]); + return false; + } + else if (considerCompound && currentLocation.node.nextCompoundSegment != null && + AscendingSortedCompoundSegmentsCollection.Lookup(currentLocation.node.nextCompoundSegment, curWireSeg, out compoundLocationsSet)) + { + nextStep = new SingleLocationOrLocationsSet(compoundLocationsSet); + return false; + } + else if (considerVariable && currentLocation.node.nextVariableSegment != null && + !curWireSeg.IsNullOrEmpty()) + { + nextStep = new SingleLocationOrLocationsSet(currentLocation.node.nextVariableSegment); + return false; + } + else if (considerStar && currentLocation.node.star.Items.Count != 0) + { + // matches e.g. WIRE("path1/path2/path3") and TEMPLATE("path1/*") + success = currentLocation.node.star; + return true; + } + else + { + nextStep = new SingleLocationOrLocationsSet(currentLocation.node.onFailure); + return false; + } + } + else + { + IList> compoundPathEquivalentSets; + + Fx.Assert(!curWireSeg.EndsWithSlash, "!curWireSeg.EndsWithSlash"); + Fx.Assert(!curWireSeg.IsNullOrEmpty(), "!curWireSeg.IsNullOrEmpty()"); + if (considerLiteral && currentLocation.node.finalLiteralSegment != null && + currentLocation.node.finalLiteralSegment.ContainsKey(curWireSeg)) + { + // matches e.g. WIRE("path1/path2") and TEMPLATE("path1/path2") + success = currentLocation.node.finalLiteralSegment[curWireSeg]; + return true; + } + else if (considerCompound && currentLocation.node.finalCompoundSegment != null && + AscendingSortedCompoundSegmentsCollection.Lookup(currentLocation.node.finalCompoundSegment, curWireSeg, out compoundPathEquivalentSets)) + { + // matches e.g. WIRE("path1/path2") and TEMPLATE("path1/p{var}th2") + // we should take only the highest order match! + Fx.Assert(compoundPathEquivalentSets.Count >= 1, "Lookup is expected to return false otherwise"); + Fx.Assert(compoundPathEquivalentSets[0].Count > 0, "Find shouldn't return empty sublists"); + if (compoundPathEquivalentSets[0].Count == 1) + { + success = compoundPathEquivalentSets[0][0]; + } + else + { + success = new UriTemplatePathPartiallyEquivalentSet(currentLocation.node.depth + 1); + for (int i = 0; i < compoundPathEquivalentSets[0].Count; i++) + { + success.Items.AddRange(compoundPathEquivalentSets[0][i].Items); + } + } + return true; + } + else if (considerVariable && currentLocation.node.finalVariableSegment.Items.Count != 0) + { + // matches e.g. WIRE("path1/path2") and TEMPLATE("path1/{var}") + success = currentLocation.node.finalVariableSegment; + return true; + } + else if (considerStar && currentLocation.node.star.Items.Count != 0) + { + // matches e.g. WIRE("path1/path2") and TEMPLATE("path1/*") + success = currentLocation.node.star; + return true; + } + else + { + nextStep = new SingleLocationOrLocationsSet(currentLocation.node.onFailure); + return false; + } + } + } + } + + static UriTemplateTrieLocation GetFailureLocationFromLocationsSet(IList> locationsSet) + { + Fx.Assert(locationsSet != null, "Shouldn't be called on null set"); + Fx.Assert(locationsSet.Count > 0, "Shouldn't be called on empty set"); + Fx.Assert(locationsSet[0] != null, "Shouldn't be called on a set with null sub-lists"); + Fx.Assert(locationsSet[0].Count > 0, "Shouldn't be called on a set with empty sub-lists"); + + return locationsSet[0][0].node.onFailure; + } + + static void Validate(UriTemplateTrieNode root, bool allowDuplicateEquivalentUriTemplates) + { + // walk the entire tree, and ensure that each PathEquivalentSet is ok (no ambiguous queries), + // verify thst compound segments didn't add potentialy multiple matchs; + // also Assert various data-structure invariants + Queue nodesQueue = new Queue(); + + UriTemplateTrieNode current = root; + while (true) + { + // validate all the PathEquivalentSets that live in this node + Validate(current.endOfPath, allowDuplicateEquivalentUriTemplates); + Validate(current.finalVariableSegment, allowDuplicateEquivalentUriTemplates); + Validate(current.star, allowDuplicateEquivalentUriTemplates); + if (current.finalLiteralSegment != null) + { + foreach (KeyValuePair kvp in current.finalLiteralSegment) + { + Validate(kvp.Value, allowDuplicateEquivalentUriTemplates); + } + } + if (current.finalCompoundSegment != null) + { + IList> pesLists = current.finalCompoundSegment.Values; + for (int i = 0; i < pesLists.Count; i++) + { + if (!allowDuplicateEquivalentUriTemplates && (pesLists[i].Count > 1)) + { + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format( + SR.UTTDuplicate, pesLists[i][0].Items[0].Key.ToString(), pesLists[i][1].Items[0].Key.ToString()))); + } + for (int j = 0; j < pesLists[i].Count; j++) + { + Validate(pesLists[i][j], allowDuplicateEquivalentUriTemplates); + } + } + } + // deal with children of this node + if (current.nextLiteralSegment != null) + { + foreach (KeyValuePair kvp in current.nextLiteralSegment) + { + Fx.Assert(kvp.Value.locationWithin == UriTemplateTrieIntraNodeLocation.BeforeLiteral, "forward-pointers should always point to a BeforeLiteral location"); + Fx.Assert(kvp.Value.node.depth == current.depth + 1, "kvp.Value.node.depth == current.depth + 1"); + Fx.Assert(kvp.Value.node.onFailure.node == current, "back pointer should point back to here"); + Fx.Assert(kvp.Value.node.onFailure.locationWithin == UriTemplateTrieIntraNodeLocation.AfterLiteral, "back-pointer should be AfterLiteral"); + nodesQueue.Enqueue(kvp.Value.node); + } + } + if (current.nextCompoundSegment != null) + { + IList> locations = current.nextCompoundSegment.Values; + for (int i = 0; i < locations.Count; i++) + { + if (!allowDuplicateEquivalentUriTemplates && (locations[i].Count > 1)) + { + // In the future we might ease up the restrictions and verify if there is realy + // a potential multiple match here; for now we are throwing. + UriTemplate firstTemplate = FindAnyUriTemplate(locations[i][0].node); + UriTemplate secondTemplate = FindAnyUriTemplate(locations[i][1].node); + throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.Format( + SR.UTTDuplicate, firstTemplate.ToString(), secondTemplate.ToString()))); + } + for (int j = 0; j < locations[i].Count; j++) + { + UriTemplateTrieLocation location = locations[i][j]; + Fx.Assert(location.locationWithin == UriTemplateTrieIntraNodeLocation.BeforeLiteral, "forward-pointers should always point to a BeforeLiteral location"); + Fx.Assert(location.node.depth == current.depth + 1, "kvp.Value.node.depth == current.depth + 1"); + Fx.Assert(location.node.onFailure.node == current, "back pointer should point back to here"); + Fx.Assert(location.node.onFailure.locationWithin == UriTemplateTrieIntraNodeLocation.AfterCompound, "back-pointer should be AfterCompound"); + nodesQueue.Enqueue(location.node); + } + } + } + if (current.nextVariableSegment != null) + { + Fx.Assert(current.nextVariableSegment.locationWithin == UriTemplateTrieIntraNodeLocation.BeforeLiteral, "forward-pointers should always point to a BeforeLiteral location"); + Fx.Assert(current.nextVariableSegment.node.depth == current.depth + 1, "current.nextVariableSegment.node.depth == current.depth + 1"); + Fx.Assert(current.nextVariableSegment.node.onFailure.node == current, "back pointer should point back to here"); + Fx.Assert(current.nextVariableSegment.node.onFailure.locationWithin == UriTemplateTrieIntraNodeLocation.AfterVariable, "back-pointer should be AfterVariable"); + nodesQueue.Enqueue(current.nextVariableSegment.node); + } + // move on to next bit of work + if (nodesQueue.Count == 0) + { + break; + } + current = nodesQueue.Dequeue(); + } + } + static void Validate(UriTemplatePathPartiallyEquivalentSet pes, bool allowDuplicateEquivalentUriTemplates) + { + // A set with 0 or 1 items is valid by definition + if (pes.Items.Count < 2) + { + return; + } + // Assert all paths are partially-equivalent + for (int i = 0; i < pes.Items.Count - 1; ++i) + { + Fx.Assert(pes.Items[i].Key.IsPathPartiallyEquivalentAt(pes.Items[i + 1].Key, pes.SegmentsCount), + "all elements of a PES must be path partially-equivalent"); + } + // We will check that the queries disambiguate only for templates, which are + // matched completely at the segments count; templates, which are match at + // that point due to terminal defaults, will be ruled out. + UriTemplate[] a = new UriTemplate[pes.Items.Count]; + int arrayIndex = 0; + foreach (KeyValuePair kvp in pes.Items) + { + if (pes.SegmentsCount < kvp.Key.segments.Count) + { + continue; + } + Fx.Assert(arrayIndex < a.Length, "We made enough room for all the items"); + a[arrayIndex++] = kvp.Key; + } + // Ensure that queries disambiguate (if needed) : + if (arrayIndex > 0) + { + UriTemplateHelpers.DisambiguateSamePath(a, 0, arrayIndex, allowDuplicateEquivalentUriTemplates); + } + } + + static UriTemplate FindAnyUriTemplate(UriTemplateTrieNode node) + { + while (node != null) + { + if (node.endOfPath.Items.Count > 0) + { + return node.endOfPath.Items[0].Key; + } + if (node.finalVariableSegment.Items.Count > 0) + { + return node.finalVariableSegment.Items[0].Key; + } + if (node.star.Items.Count > 0) + { + return node.star.Items[0].Key; + } + if (node.finalLiteralSegment != null) + { + UriTemplatePathPartiallyEquivalentSet pes = + GetAnyDictionaryValue(node.finalLiteralSegment); + Fx.Assert(pes.Items.Count > 0, "Otherwise, why creating the dictionary?"); + return pes.Items[0].Key; + } + if (node.finalCompoundSegment != null) + { + UriTemplatePathPartiallyEquivalentSet pes = node.finalCompoundSegment.GetAnyValue(); + Fx.Assert(pes.Items.Count > 0, "Otherwise, why creating the collection?"); + return pes.Items[0].Key; + } + + if (node.nextLiteralSegment != null) + { + UriTemplateTrieLocation location = + GetAnyDictionaryValue(node.nextLiteralSegment); + node = location.node; + } + else if (node.nextCompoundSegment != null) + { + UriTemplateTrieLocation location = node.nextCompoundSegment.GetAnyValue(); + node = location.node; + } + else if (node.nextVariableSegment != null) + { + node = node.nextVariableSegment.node; + } + else + { + node = null; + } + } + Fx.Assert("How did we got here without finding a UriTemplate earlier?"); + return null; + } + static T GetAnyDictionaryValue(IDictionary dictionary) + { + using (IEnumerator valuesEnumerator = dictionary.Values.GetEnumerator()) + { + valuesEnumerator.MoveNext(); + return valuesEnumerator.Current; + } + } + + void AddFinalCompoundSegment(UriTemplateCompoundPathSegment cps, KeyValuePair kvp) + { + Fx.Assert(cps != null, "must be - based on the segment nature"); + if (this.finalCompoundSegment == null) + { + this.finalCompoundSegment = new AscendingSortedCompoundSegmentsCollection(); + } + UriTemplatePathPartiallyEquivalentSet pes = this.finalCompoundSegment.Find(cps); + if (pes == null) + { + pes = new UriTemplatePathPartiallyEquivalentSet(this.depth + 1); + this.finalCompoundSegment.Add(cps, pes); + } + pes.Items.Add(kvp); + } + void AddFinalLiteralSegment(UriTemplateLiteralPathSegment lps, KeyValuePair kvp) + { + Fx.Assert(lps != null, "must be - based on the segment nature"); + if (this.finalLiteralSegment != null && this.finalLiteralSegment.ContainsKey(lps)) + { + this.finalLiteralSegment[lps].Items.Add(kvp); + } + else + { + if (this.finalLiteralSegment == null) + { + this.finalLiteralSegment = new Dictionary(); + } + UriTemplatePathPartiallyEquivalentSet pes = new UriTemplatePathPartiallyEquivalentSet(this.depth + 1); + pes.Items.Add(kvp); + this.finalLiteralSegment.Add(lps, pes); + } + } + UriTemplateTrieNode AddNextCompoundSegment(UriTemplateCompoundPathSegment cps) + { + Fx.Assert(cps != null, "must be - based on the segment nature"); + if (this.nextCompoundSegment == null) + { + this.nextCompoundSegment = new AscendingSortedCompoundSegmentsCollection(); + } + UriTemplateTrieLocation nextLocation = this.nextCompoundSegment.Find(cps); + if (nextLocation == null) + { + UriTemplateTrieNode nextNode = new UriTemplateTrieNode(this.depth + 1); + nextNode.onFailure = new UriTemplateTrieLocation(this, UriTemplateTrieIntraNodeLocation.AfterCompound); + nextLocation = new UriTemplateTrieLocation(nextNode, UriTemplateTrieIntraNodeLocation.BeforeLiteral); + this.nextCompoundSegment.Add(cps, nextLocation); + } + return nextLocation.node; + } + UriTemplateTrieNode AddNextLiteralSegment(UriTemplateLiteralPathSegment lps) + { + Fx.Assert(lps != null, "must be - based on the segment nature"); + if (this.nextLiteralSegment != null && this.nextLiteralSegment.ContainsKey(lps)) + { + return this.nextLiteralSegment[lps].node; + } + else + { + if (this.nextLiteralSegment == null) + { + this.nextLiteralSegment = new Dictionary(); + } + UriTemplateTrieNode newNode = new UriTemplateTrieNode(this.depth + 1); + newNode.onFailure = new UriTemplateTrieLocation(this, UriTemplateTrieIntraNodeLocation.AfterLiteral); + this.nextLiteralSegment.Add(lps, new UriTemplateTrieLocation(newNode, UriTemplateTrieIntraNodeLocation.BeforeLiteral)); + return newNode; + } + } + UriTemplateTrieNode AddNextVariableSegment() + { + if (this.nextVariableSegment != null) + { + return this.nextVariableSegment.node; + } + else + { + UriTemplateTrieNode newNode = new UriTemplateTrieNode(this.depth + 1); + newNode.onFailure = new UriTemplateTrieLocation(this, UriTemplateTrieIntraNodeLocation.AfterVariable); + this.nextVariableSegment = new UriTemplateTrieLocation(newNode, UriTemplateTrieIntraNodeLocation.BeforeLiteral); + return newNode; + } + } + + struct SingleLocationOrLocationsSet + { + readonly bool isSingle; + readonly IList> locationsSet; + readonly UriTemplateTrieLocation singleLocation; + + public SingleLocationOrLocationsSet(UriTemplateTrieLocation singleLocation) + { + this.isSingle = true; + this.singleLocation = singleLocation; + this.locationsSet = null; + } + public SingleLocationOrLocationsSet(IList> locationsSet) + { + this.isSingle = false; + this.singleLocation = null; + this.locationsSet = locationsSet; + } + + public bool IsSingle + { + get + { + return this.isSingle; + } + } + public IList> LocationsSet + { + get + { + Fx.Assert(!this.isSingle, "!this.isSingle"); + return this.locationsSet; + } + } + public UriTemplateTrieLocation SingleLocation + { + get + { + Fx.Assert(this.isSingle, "this.isSingle"); + return this.singleLocation; + } + } + } + + class AscendingSortedCompoundSegmentsCollection + where T : class + { + SortedList> items; + + public AscendingSortedCompoundSegmentsCollection() + { + this.items = new SortedList.CollectionItem>>(); + } + + public IList> Values + { + get + { + IList> results = new List>(this.items.Count); + for (int i = 0; i < this.items.Values.Count; i++) + { + results.Add(new List(this.items.Values[i].Count)); + Fx.Assert(results.Count == i + 1, "We are adding item for each values collection"); + for (int j = 0; j < this.items.Values[i].Count; j++) + { + results[i].Add(this.items.Values[i][j].Value); + Fx.Assert(results[i].Count == j + 1, "We are adding item for each value in the collection"); + } + Fx.Assert(results[i].Count == this.items.Values[i].Count, "We were supposed to add an item for each value in the collection"); + } + Fx.Assert(results.Count == this.items.Values.Count, "We were supposed to add a sub-list for each values collection"); + return results; + } + } + + public void Add(UriTemplateCompoundPathSegment segment, T value) + { + int index = this.items.IndexOfKey(segment); + if (index == -1) + { + Collection subItems = new Collection(); + subItems.Add(new CollectionItem(segment, value)); + this.items.Add(segment, subItems); + } + else + { + Collection subItems = this.items.Values[index]; + subItems.Add(new CollectionItem(segment, value)); + } + } + + public T Find(UriTemplateCompoundPathSegment segment) + { + int index = this.items.IndexOfKey(segment); + if (index == -1) + { + return null; + } + Collection subItems = this.items.Values[index]; + for (int i = 0; i < subItems.Count; i++) + { + if (subItems[i].Segment.IsEquivalentTo(segment, false)) + { + return subItems[i].Value; + } + } + return null; + } + public IList> Find(UriTemplateLiteralPathSegment wireData) + { + IList> results = new List>(); + for (int i = 0; i < this.items.Values.Count; i++) + { + List sameOrderResults = null; + for (int j = 0; j < this.items.Values[i].Count; j++) + { + if (this.items.Values[i][j].Segment.IsMatch(wireData)) + { + if (sameOrderResults == null) + { + sameOrderResults = new List(); + } + sameOrderResults.Add(this.items.Values[i][j].Value); + } + } + if (sameOrderResults != null) + { + results.Add(sameOrderResults); + } + } + return results; + } + + public T GetAnyValue() + { + if (this.items.Values.Count > 0) + { + Fx.Assert(this.items.Values[0].Count > 0, "We are not adding a sub-list unless there is at list one item"); + return this.items.Values[0][0].Value; + } + else + { + return null; + } + } + + public static bool Lookup(AscendingSortedCompoundSegmentsCollection collection, + UriTemplateLiteralPathSegment wireData, out IList> results) + { + results = collection.Find(wireData); + return ((results != null) && (results.Count > 0)); + } + + struct CollectionItem + { + UriTemplateCompoundPathSegment segment; + T value; + + public CollectionItem(UriTemplateCompoundPathSegment segment, T value) + { + this.segment = segment; + this.value = value; + } + + public UriTemplateCompoundPathSegment Segment + { + get + { + return this.segment; + } + } + public T Value + { + get + { + return this.value; + } + } + } + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplateVariablePathSegment.cs b/src/System.ServiceModel.Web/src/System/UriTemplateVariablePathSegment.cs new file mode 100644 index 00000000000..72fc9959355 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplateVariablePathSegment.cs @@ -0,0 +1,68 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + using System.Collections.Specialized; + using System.Runtime; + using System.Text; + + class UriTemplateVariablePathSegment : UriTemplatePathSegment + { + readonly string varName; + + public UriTemplateVariablePathSegment(string originalSegment, bool endsWithSlash, string varName) + : base(originalSegment, UriTemplatePartType.Variable, endsWithSlash) + { + Fx.Assert(!string.IsNullOrEmpty(varName), "bad variable segment"); + this.varName = varName; + } + + public string VarName + { + get + { + return this.varName; + } + } + public override void Bind(string[] values, ref int valueIndex, StringBuilder path) + { + Fx.Assert(valueIndex < values.Length, "Not enough values to bind"); + if (this.EndsWithSlash) + { + path.AppendFormat("{0}/", values[valueIndex++]); + } + else + { + path.Append(values[valueIndex++]); + } + } + + public override bool IsEquivalentTo(UriTemplatePathSegment other, bool ignoreTrailingSlash) + { + if (other == null) + { + Fx.Assert("why would we ever call this?"); + return false; + } + if (!ignoreTrailingSlash && (this.EndsWithSlash != other.EndsWithSlash)) + { + return false; + } + return (other.Nature == UriTemplatePartType.Variable); + } + public override bool IsMatch(UriTemplateLiteralPathSegment segment, bool ignoreTrailingSlash) + { + if (!ignoreTrailingSlash && (this.EndsWithSlash != segment.EndsWithSlash)) + { + return false; + } + return (!segment.IsNullOrEmpty()); + } + public override void Lookup(string segment, NameValueCollection boundParameters) + { + Fx.Assert(!string.IsNullOrEmpty(segment), "How can that be? Lookup is expected to be called after IsMatch"); + boundParameters.Add(this.varName, segment); + } + } +} diff --git a/src/System.ServiceModel.Web/src/System/UriTemplateVariableQueryValue.cs b/src/System.ServiceModel.Web/src/System/UriTemplateVariableQueryValue.cs new file mode 100644 index 00000000000..d493cdc4cc6 --- /dev/null +++ b/src/System.ServiceModel.Web/src/System/UriTemplateVariableQueryValue.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +namespace System +{ + using System.Collections.Specialized; + using System.Runtime; + using System.ServiceModel.Channels; + using System.Text; + + class UriTemplateVariableQueryValue : UriTemplateQueryValue + { + readonly string varName; + + public UriTemplateVariableQueryValue(string varName) + : base(UriTemplatePartType.Variable) + { + Fx.Assert(!string.IsNullOrEmpty(varName), "bad variable segment"); + this.varName = varName; + } + public override void Bind(string keyName, string[] values, ref int valueIndex, StringBuilder query) + { + Fx.Assert(valueIndex < values.Length, "Not enough values to bind"); + if (values[valueIndex] == null) + { + valueIndex++; + } + else + { + query.AppendFormat("&{0}={1}", UrlUtility.UrlEncode(keyName, Encoding.UTF8), UrlUtility.UrlEncode(values[valueIndex++], Encoding.UTF8)); + } + } + + public override bool IsEquivalentTo(UriTemplateQueryValue other) + { + if (other == null) + { + Fx.Assert("why would we ever call this?"); + return false; + } + return (other.Nature == UriTemplatePartType.Variable); + } + public override void Lookup(string value, NameValueCollection boundParameters) + { + boundParameters.Add(this.varName, value); + } + } +} diff --git a/src/System.ServiceModel.Web/tests/System.ServiceModel.Web.Tests.csproj b/src/System.ServiceModel.Web/tests/System.ServiceModel.Web.Tests.csproj new file mode 100644 index 00000000000..55382c2b2ff --- /dev/null +++ b/src/System.ServiceModel.Web/tests/System.ServiceModel.Web.Tests.csproj @@ -0,0 +1,20 @@ + + + $(UnitTestTargetFrameworks) + false + true + false + + $(MSBuildWarningsAsMessages);MSB3243 + + + + + + + + +