├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── SimpleSOAPClient-Logo.pdn ├── SimpleSOAPClient-Logo.png ├── SimpleSOAPClient.sln ├── src └── SimpleSOAPClient │ ├── Constant.cs │ ├── Exceptions │ ├── FaultException.cs │ ├── SoapClientException.cs │ ├── SoapEnvelopeDeserializationException.cs │ └── SoapEnvelopeSerializationException.cs │ ├── Handlers │ ├── DelegatingSoapHandler.cs │ ├── ISoapHandler.cs │ ├── OnHttpRequestArguments.cs │ ├── OnHttpResponseArguments.cs │ ├── OnSoapEnvelopeRequestArguments.cs │ ├── OnSoapEnvelopeResponseArguments.cs │ ├── SoapHandler.cs │ └── SoapHandlerArguments.cs │ ├── Helpers │ ├── ClientFactoryHelpers.cs │ ├── ClientHelpers.cs │ ├── EnvelopeHelpers.cs │ └── XmlHelpers.cs │ ├── HttpClientFactory.cs │ ├── IHttpClientFactory.cs │ ├── ISoapClient.cs │ ├── ISoapClientFactory.cs │ ├── ISoapEnvelopeSerializationProvider.cs │ ├── Models │ ├── Headers │ │ ├── KnownHeader.cs │ │ ├── Microsoft │ │ │ ├── ActionSoapHeader.cs │ │ │ └── ToSoapHeader.cs │ │ └── Oasis │ │ │ └── Security │ │ │ ├── SecuritySoapHeader.cs │ │ │ ├── Timestamp.cs │ │ │ ├── UsernameTokenAndPasswordTextSoapHeader.cs │ │ │ ├── UsernameTokenPasswordText.cs │ │ │ └── UsernameTokenWithPasswordText.cs │ ├── SoapEnvelope.cs │ ├── SoapEnvelopeBody.cs │ ├── SoapEnvelopeHeader.cs │ ├── SoapFault.cs │ └── SoapHeader.cs │ ├── SimpleSOAPClient.csproj │ ├── SoapClient.cs │ ├── SoapClientSettings.cs │ └── SoapEnvelopeSerializationProvider.cs ├── tests └── SimpleSOAPClient.Tests │ ├── DataContractModel.cs │ ├── SimpleSOAPClient.Tests.csproj │ ├── XmlHelpersTests.cs │ ├── XmlModel.cs │ └── XmlNormalizer.cs └── tools ├── SimpleSOAPClient.PublicKey └── SimpleSOAPClient.snk /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 João Simões 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple SOAP Client 2 | Lightweight SOAP client for invoking HTTP SOAP endpoints. 3 | Fluently create SOAP Envelopes, send them through the SOAP Client and extract the needed information from the returned SOAP Envelope. 4 | The client also exposes a range of handler that can be used as a pipeline to work with the SOAP Envelope or the HTTP requests and responses. 5 | 6 | Buy Me A Coffee 7 | 8 | ## Installation 9 | This library can be installed via [NuGet](https://www.nuget.org/packages/SimpleSOAPClient/) package. Just run the following command: 10 | 11 | ```powershell 12 | Install-Package SimpleSOAPClient 13 | ``` 14 | 15 | ## Compatibility 16 | 17 | This library is compatible with the folowing frameworks: 18 | 19 | * .NET Framework 4.5 20 | * .NET Standard 1.1 21 | * .NET Standard 2.0 22 | * UAP 10.0 23 | 24 | ## Usage 25 | 26 | ```csharp 27 | public static async Task MainAsync(string[] args, CancellationToken ct) 28 | { 29 | using (var client = 30 | SoapClient.Prepare() 31 | .WithHandler(new DelegatingSoapHandler 32 | { 33 | OnSoapEnvelopeRequestAsyncAction = async (c, d, cancellationToken) => 34 | { 35 | d.Envelope.WithHeaders( 36 | KnownHeader.Oasis.Security.UsernameTokenAndPasswordText( 37 | "some-user", "some-password")); 38 | }, 39 | OnHttpRequestAsyncAction = async (soapClient, d, cancellationToken) => 40 | { 41 | Logger.LogTrace( 42 | "SOAP Outbound Request -> {0} {1}({2})\n{3}", 43 | d.Request.Method, d.Url, d.Action, await d.Request.Content.ReadAsStringAsync()); 44 | }, 45 | OnHttpResponseAsyncAction = async (soapClient, d, cancellationToken) => 46 | { 47 | Logger.LogTrace( 48 | "SOAP Outbound Response -> {0}({1}) {2} {3}\n{4}", 49 | d.Url, d.Action, (int) d.Response.StatusCode, d.Response.StatusCode, 50 | await d.Response.Content.ReadAsStringAsync()); 51 | }, 52 | OnSoapEnvelopeResponseAsyncAction = async (soapClient, d, cancellationToken) => 53 | { 54 | var header = 55 | d.Envelope.Header( 56 | "{" + Constant.Namespace.OrgOpenOasisDocsWss200401Oasis200401WssWssecuritySecext10 + 57 | "}Security"); 58 | } 59 | })) 60 | { 61 | var requestEnvelope = 62 | SoapEnvelope.Prepare().Body(new IsAliveRequest()); 63 | 64 | SoapEnvelope responseEnvelope; 65 | try 66 | { 67 | responseEnvelope = 68 | await client.SendAsync( 69 | "https://services.company.com/Service.svc", 70 | "http://services.company.com/IService/IsAlive", 71 | requestEnvelope, ct); 72 | } 73 | catch (SoapEnvelopeSerializationException e) 74 | { 75 | Logger.LogError(e, 76 | $"Failed to serialize the SOAP Envelope [Envelope={e.Envelope}]"); 77 | throw; 78 | } 79 | catch (SoapEnvelopeDeserializationException e) 80 | { 81 | Logger.LogError(e, 82 | $"Failed to deserialize the response into a SOAP Envelope [XmlValue={e.XmlValue}]"); 83 | throw; 84 | } 85 | 86 | try 87 | { 88 | var response = responseEnvelope.Body(); 89 | } 90 | catch (FaultException e) 91 | { 92 | Logger.LogError(e, 93 | $"The server returned a fault [Code={e.Code}, String={e.String}, Actor={e.Actor}]"); 94 | throw; 95 | } 96 | } 97 | } 98 | 99 | [XmlRoot("IsAliveRequest", Namespace = "http://services.company.com")] 100 | public class IsAliveRequest 101 | { 102 | 103 | } 104 | 105 | [XmlRoot("IsAliveResponse", Namespace = "http://services.company.com")] 106 | public class IsAliveResponse 107 | { 108 | [XmlElement("IsAliveResult")] 109 | public bool IsAlive { get; set; } 110 | } 111 | ``` 112 | -------------------------------------------------------------------------------- /SimpleSOAPClient-Logo.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity00/SimpleSOAPClient/e41d82d00a6a4338c5943ed125fac5d0dfa2d6dd/SimpleSOAPClient-Logo.pdn -------------------------------------------------------------------------------- /SimpleSOAPClient-Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity00/SimpleSOAPClient/e41d82d00a6a4338c5943ed125fac5d0dfa2d6dd/SimpleSOAPClient-Logo.png -------------------------------------------------------------------------------- /SimpleSOAPClient.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2036 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{68E461E4-64AD-4CC4-959D-613F5C84242B}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{E136A35F-1EC1-4A90-9369-C278E33BA475}" 9 | ProjectSection(SolutionItems) = preProject 10 | tools\SimpleSOAPClient.PublicKey = tools\SimpleSOAPClient.PublicKey 11 | tools\SimpleSOAPClient.snk = tools\SimpleSOAPClient.snk 12 | EndProjectSection 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "other", "other", "{6C152128-CC1B-4140-9FE1-8E86B013AB88}" 15 | ProjectSection(SolutionItems) = preProject 16 | LICENSE = LICENSE 17 | README.md = README.md 18 | SimpleSOAPClient-Logo.pdn = SimpleSOAPClient-Logo.pdn 19 | SimpleSOAPClient-Logo.png = SimpleSOAPClient-Logo.png 20 | EndProjectSection 21 | EndProject 22 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "resources", "resources", "{A2159B1B-25D6-4AFA-A30A-22207B226377}" 23 | EndProject 24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleSOAPClient", "src\SimpleSOAPClient\SimpleSOAPClient.csproj", "{BD232C77-3DEB-4CB1-8BC7-30A4C1A50DEA}" 25 | EndProject 26 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{63D634C9-3F19-4305-8831-D47A380C9EAB}" 27 | EndProject 28 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleSOAPClient.Tests", "tests\SimpleSOAPClient.Tests\SimpleSOAPClient.Tests.csproj", "{07625BFB-1644-415D-B2B8-468152E05C3C}" 29 | EndProject 30 | Global 31 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 32 | Debug|Any CPU = Debug|Any CPU 33 | Release|Any CPU = Release|Any CPU 34 | EndGlobalSection 35 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 36 | {BD232C77-3DEB-4CB1-8BC7-30A4C1A50DEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 37 | {BD232C77-3DEB-4CB1-8BC7-30A4C1A50DEA}.Debug|Any CPU.Build.0 = Debug|Any CPU 38 | {BD232C77-3DEB-4CB1-8BC7-30A4C1A50DEA}.Release|Any CPU.ActiveCfg = Release|Any CPU 39 | {BD232C77-3DEB-4CB1-8BC7-30A4C1A50DEA}.Release|Any CPU.Build.0 = Release|Any CPU 40 | {07625BFB-1644-415D-B2B8-468152E05C3C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {07625BFB-1644-415D-B2B8-468152E05C3C}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {07625BFB-1644-415D-B2B8-468152E05C3C}.Release|Any CPU.ActiveCfg = Release|Any CPU 43 | {07625BFB-1644-415D-B2B8-468152E05C3C}.Release|Any CPU.Build.0 = Release|Any CPU 44 | EndGlobalSection 45 | GlobalSection(SolutionProperties) = preSolution 46 | HideSolutionNode = FALSE 47 | EndGlobalSection 48 | GlobalSection(NestedProjects) = preSolution 49 | {E136A35F-1EC1-4A90-9369-C278E33BA475} = {A2159B1B-25D6-4AFA-A30A-22207B226377} 50 | {6C152128-CC1B-4140-9FE1-8E86B013AB88} = {A2159B1B-25D6-4AFA-A30A-22207B226377} 51 | {BD232C77-3DEB-4CB1-8BC7-30A4C1A50DEA} = {68E461E4-64AD-4CC4-959D-613F5C84242B} 52 | {07625BFB-1644-415D-B2B8-468152E05C3C} = {63D634C9-3F19-4305-8831-D47A380C9EAB} 53 | EndGlobalSection 54 | GlobalSection(ExtensibilityGlobals) = postSolution 55 | SolutionGuid = {B2AD5ABD-A184-4781-910A-F187301694F8} 56 | EndGlobalSection 57 | EndGlobal 58 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Constant.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient 25 | { 26 | /// 27 | /// Class with a wide range of constant values 28 | /// 29 | public static class Constant 30 | { 31 | /// 32 | /// Namespace constants 33 | /// 34 | public static class Namespace 35 | { 36 | /// 37 | /// The SOAP Envelope namespace 38 | /// 39 | public const string OrgXmlSoapSchemasSoapEnvelope = 40 | "http://schemas.xmlsoap.org/soap/envelope/"; 41 | 42 | /// 43 | /// The Microsoft addressing namespace 44 | /// 45 | public const string ComMicrosoftSchemasWs200505AddressingNone = 46 | "http://schemas.microsoft.com/ws/2005/05/addressing/none"; 47 | 48 | /// 49 | /// The Oasis Security namespace 50 | /// 51 | public const string OrgOpenOasisDocsWss200401Oasis200401WssWssecuritySecext10 = 52 | "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; 53 | 54 | /// 55 | /// The Oasis Security Utilities namespace 56 | /// 57 | public const string OrgOpenOasisDocsWss200401Oasis200401WssWssecurityUtility10 = 58 | "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"; 59 | 60 | /// 61 | /// 62 | /// 63 | public const string OrgOpenOasisDocsWss200401Oasis200401WssUsernameTokenProfile10PasswordText = 64 | "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"; 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Exceptions/FaultException.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Exceptions 25 | { 26 | using System; 27 | using System.Xml.Linq; 28 | 29 | /// 30 | /// Exception representing a fault returned by the server 31 | /// 32 | public class FaultException : SoapClientException 33 | { 34 | private const string DefaultErrorMessage = "A fault was returned by the server"; 35 | 36 | /// 37 | /// The fault code 38 | /// 39 | public string Code { get; set; } 40 | 41 | /// 42 | /// The fault string 43 | /// 44 | public string String { get; set; } 45 | 46 | /// 47 | /// The fault actor 48 | /// 49 | public string Actor { get; set; } 50 | 51 | /// 52 | /// The fault detail 53 | /// 54 | public XElement Detail { get; set; } 55 | 56 | /// 57 | /// Initializes a new instance of with 58 | /// a default error message 59 | /// 60 | public FaultException() : base(DefaultErrorMessage) 61 | { 62 | 63 | } 64 | 65 | /// 66 | /// Initializes a new instance of with 67 | /// a specified error message 68 | /// 69 | /// The error message 70 | public FaultException(string message) : base(message) 71 | { 72 | 73 | } 74 | 75 | /// 76 | /// Initializes a new instance of with 77 | /// a specified error message and a reference to the inner exception 78 | /// 79 | /// The error message 80 | /// The inner exception 81 | public FaultException(string message, Exception innerException) : base(message, innerException) 82 | { 83 | 84 | } 85 | 86 | /// 87 | /// Initializes a new instance of with 88 | /// a specified error message and a reference to the inner exception 89 | /// 90 | /// The inner exception 91 | public FaultException(Exception innerException) : base(DefaultErrorMessage, innerException) 92 | { 93 | 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Exceptions/SoapClientException.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 SimplePersistence 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Exceptions 25 | { 26 | using System; 27 | 28 | /// 29 | /// Base class for specialized exceptions thrown by the Simple SOAP Client library 30 | /// 31 | public abstract class SoapClientException : Exception 32 | { 33 | /// 34 | /// Initializes a new instance of 35 | /// 36 | /// The message to be used 37 | protected SoapClientException(string message) : base(message) 38 | { 39 | 40 | } 41 | 42 | /// 43 | /// Initializes a new instance of 44 | /// 45 | /// The message to be used 46 | /// The inner exception 47 | protected SoapClientException(string message, Exception innerException) : base(message, innerException) 48 | { 49 | 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Exceptions/SoapEnvelopeDeserializationException.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 SimplePersistence 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Exceptions 25 | { 26 | using System; 27 | using Models; 28 | 29 | /// 30 | /// Exception thrown when an exception is thrown when deserializing 31 | /// a given XML string to a . 32 | /// 33 | public class SoapEnvelopeDeserializationException : SoapClientException 34 | { 35 | private const string DefaultErrorMessage = "Failed to deserialize the XML string to a SOAP Envelope"; 36 | 37 | /// 38 | /// The XML string that was beeing deserialized 39 | /// 40 | /// 41 | public string XmlValue { get; } 42 | 43 | /// 44 | /// Initializes a new instance of 45 | /// 46 | /// The XML string that was beeing deserialized 47 | /// 48 | public SoapEnvelopeDeserializationException(string xmlValue) : this(xmlValue, DefaultErrorMessage) 49 | { 50 | 51 | } 52 | 53 | /// 54 | /// Initializes a new instance of 55 | /// 56 | /// The XML string that was beeing deserialized 57 | /// The message to be used 58 | /// 59 | public SoapEnvelopeDeserializationException(string xmlValue, string message) : base(message) 60 | { 61 | if (xmlValue == null) throw new ArgumentNullException(nameof(xmlValue)); 62 | 63 | XmlValue = xmlValue; 64 | } 65 | 66 | /// 67 | /// Initializes a new instance of 68 | /// 69 | /// The XML string that was beeing deserialized 70 | /// The message to be used 71 | /// The inner exception 72 | /// 73 | public SoapEnvelopeDeserializationException(string xmlValue, string message, Exception innerException) : base(message, innerException) 74 | { 75 | if (xmlValue == null) throw new ArgumentNullException(nameof(xmlValue)); 76 | 77 | XmlValue = xmlValue; 78 | } 79 | 80 | /// 81 | /// Initializes a new instance of 82 | /// 83 | /// The XML string that was beeing deserialized 84 | /// The inner exception 85 | /// 86 | public SoapEnvelopeDeserializationException(string xmlValue, Exception innerException) : this(xmlValue, DefaultErrorMessage, innerException) 87 | { 88 | 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Exceptions/SoapEnvelopeSerializationException.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 SimplePersistence 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Exceptions 25 | { 26 | using System; 27 | using Models; 28 | 29 | /// 30 | /// Exception thrown when an exception is thrown when serializing 31 | /// a given to a XML string. 32 | /// 33 | public class SoapEnvelopeSerializationException : SoapClientException 34 | { 35 | private const string DefaultErrorMessage = "Failed to serialize the SOAP Envelope"; 36 | 37 | /// 38 | /// The that failed to be serialized 39 | /// 40 | /// 41 | public SoapEnvelope Envelope { get; } 42 | 43 | /// 44 | /// Initializes a new instance of 45 | /// 46 | /// The envelope that failed to serialize 47 | /// 48 | public SoapEnvelopeSerializationException(SoapEnvelope envelope) : this(envelope, DefaultErrorMessage) 49 | { 50 | 51 | } 52 | 53 | /// 54 | /// Initializes a new instance of 55 | /// 56 | /// The envelope that failed to serialize 57 | /// The message to be used 58 | /// 59 | public SoapEnvelopeSerializationException(SoapEnvelope envelope, string message) : base(message) 60 | { 61 | if (envelope == null) throw new ArgumentNullException(nameof(envelope)); 62 | 63 | Envelope = envelope; 64 | } 65 | 66 | /// 67 | /// Initializes a new instance of 68 | /// 69 | /// The envelope that failed to serialize 70 | /// The message to be used 71 | /// The inner exception 72 | /// 73 | public SoapEnvelopeSerializationException(SoapEnvelope envelope, string message, Exception innerException) : base(message, innerException) 74 | { 75 | if (envelope == null) throw new ArgumentNullException(nameof(envelope)); 76 | 77 | Envelope = envelope; 78 | } 79 | 80 | /// 81 | /// Initializes a new instance of 82 | /// 83 | /// The envelope that failed to serialize 84 | /// The inner exception 85 | /// 86 | public SoapEnvelopeSerializationException(SoapEnvelope envelope, Exception innerException) : this(envelope, DefaultErrorMessage, innerException) 87 | { 88 | 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Handlers/DelegatingSoapHandler.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Handlers 25 | { 26 | using System; 27 | using System.Net.Http; 28 | using System.Threading; 29 | using System.Threading.Tasks; 30 | using Models; 31 | 32 | /// 33 | /// SOAP Handler that exposes delegates for each handling operation. 34 | /// 35 | public sealed class DelegatingSoapHandler : ISoapHandler 36 | { 37 | /// 38 | /// Delegate for method. 39 | /// 40 | public Func OnSoapEnvelopeRequestAsyncAction { get; set; } 41 | 42 | /// 43 | /// Delegate for method. 44 | /// 45 | public Func OnHttpRequestAsyncAction { get; set; } 46 | 47 | /// 48 | /// Delegate for method. 49 | /// 50 | public Func OnHttpResponseAsyncAction { get; set; } 51 | 52 | /// 53 | /// Delegate for method. 54 | /// 55 | public Func OnSoapEnvelopeResponseAsyncAction { get; set; } 56 | 57 | #region Implementation of ISoapHandler 58 | 59 | /// 60 | /// The order for which the handler will be executed 61 | /// 62 | public int Order { get; set; } 63 | 64 | /// 65 | /// Method invoked before serializing a . 66 | /// Useful to add properties like . 67 | /// 68 | /// The client sending the request 69 | /// The method arguments 70 | /// The cancellation token 71 | /// Task to be awaited 72 | public async Task OnSoapEnvelopeRequestAsync(ISoapClient client, OnSoapEnvelopeRequestArguments arguments, CancellationToken ct) 73 | { 74 | if (OnSoapEnvelopeRequestAsyncAction != null) 75 | await OnSoapEnvelopeRequestAsyncAction(client, arguments, ct).ConfigureAwait(false); 76 | } 77 | 78 | /// 79 | /// Method invoked before sending the to the server. 80 | /// Useful to log the request or change properties like HTTP headers. 81 | /// 82 | /// The client sending the request 83 | /// The method arguments 84 | /// The cancellation token 85 | /// Task to be awaited 86 | public async Task OnHttpRequestAsync(ISoapClient client, OnHttpRequestArguments arguments, CancellationToken ct) 87 | { 88 | if (OnHttpRequestAsyncAction != null) 89 | await OnHttpRequestAsyncAction(client, arguments, ct).ConfigureAwait(false); 90 | } 91 | 92 | /// 93 | /// Method invoked after receiving a from the server. 94 | /// Useful to log the response or validate HTTP headers. 95 | /// 96 | /// The client sending the request 97 | /// The method arguments 98 | /// The cancellation token 99 | /// Task to be awaited 100 | public async Task OnHttpResponseAsync(ISoapClient client, OnHttpResponseArguments arguments, CancellationToken ct) 101 | { 102 | if (OnHttpResponseAsyncAction != null) 103 | await OnHttpResponseAsyncAction(client, arguments, ct).ConfigureAwait(false); 104 | } 105 | 106 | /// 107 | /// Method invoked after deserializing a from the server response. 108 | /// Useful to validate properties like . 109 | /// 110 | /// The client sending the request 111 | /// The method arguments 112 | /// The cancellation token 113 | /// Task to be awaited 114 | public async Task OnSoapEnvelopeResponseAsync(ISoapClient client, OnSoapEnvelopeResponseArguments arguments, CancellationToken ct) 115 | { 116 | if (OnSoapEnvelopeResponseAsyncAction != null) 117 | await OnSoapEnvelopeResponseAsyncAction(client, arguments, ct).ConfigureAwait(false); 118 | } 119 | 120 | #endregion 121 | } 122 | } -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Handlers/ISoapHandler.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Handlers 25 | { 26 | using System.Net.Http; 27 | using System.Threading; 28 | using System.Threading.Tasks; 29 | using Models; 30 | 31 | /// 32 | /// Represents an handler for SOAP requests and responses. 33 | /// 34 | public interface ISoapHandler 35 | { 36 | /// 37 | /// The order for which the handler will be executed 38 | /// 39 | int Order { get; set; } 40 | 41 | /// 42 | /// Method invoked before serializing a . 43 | /// Useful to add properties like . 44 | /// 45 | /// The client sending the request 46 | /// The method arguments 47 | /// The cancellation token 48 | /// Task to be awaited 49 | Task OnSoapEnvelopeRequestAsync(ISoapClient client, OnSoapEnvelopeRequestArguments arguments, CancellationToken ct); 50 | 51 | /// 52 | /// Method invoked before sending the to the server. 53 | /// Useful to log the request or change properties like HTTP headers. 54 | /// 55 | /// The client sending the request 56 | /// The method arguments 57 | /// The cancellation token 58 | /// Task to be awaited 59 | Task OnHttpRequestAsync(ISoapClient client, OnHttpRequestArguments arguments, CancellationToken ct); 60 | 61 | /// 62 | /// Method invoked after receiving a from the server. 63 | /// Useful to log the response or validate HTTP headers. 64 | /// 65 | /// The client sending the request 66 | /// The method arguments 67 | /// The cancellation token 68 | /// Task to be awaited 69 | Task OnHttpResponseAsync(ISoapClient client, OnHttpResponseArguments arguments, CancellationToken ct); 70 | 71 | /// 72 | /// Method invoked after deserializing a from the server response. 73 | /// Useful to validate properties like . 74 | /// 75 | /// The client sending the request 76 | /// The method arguments 77 | /// The cancellation token 78 | /// Task to be awaited 79 | Task OnSoapEnvelopeResponseAsync(ISoapClient client, OnSoapEnvelopeResponseArguments arguments, CancellationToken ct); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Handlers/OnHttpRequestArguments.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity00/SimpleSOAPClient/e41d82d00a6a4338c5943ed125fac5d0dfa2d6dd/src/SimpleSOAPClient/Handlers/OnHttpRequestArguments.cs -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Handlers/OnHttpResponseArguments.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity00/SimpleSOAPClient/e41d82d00a6a4338c5943ed125fac5d0dfa2d6dd/src/SimpleSOAPClient/Handlers/OnHttpResponseArguments.cs -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Handlers/OnSoapEnvelopeRequestArguments.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity00/SimpleSOAPClient/e41d82d00a6a4338c5943ed125fac5d0dfa2d6dd/src/SimpleSOAPClient/Handlers/OnSoapEnvelopeRequestArguments.cs -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Handlers/OnSoapEnvelopeResponseArguments.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity00/SimpleSOAPClient/e41d82d00a6a4338c5943ed125fac5d0dfa2d6dd/src/SimpleSOAPClient/Handlers/OnSoapEnvelopeResponseArguments.cs -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Handlers/SoapHandler.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Handlers 25 | { 26 | using System.Net.Http; 27 | using System.Threading; 28 | using System.Threading.Tasks; 29 | using Models; 30 | 31 | /// 32 | /// Base SOAP Handler that extending classes can use to override 33 | /// only specific operations. 34 | /// 35 | public class SoapHandler : ISoapHandler 36 | { 37 | private static readonly Task CachedTask = Task.FromResult(true); 38 | 39 | #region Implementation of ISoapHandler 40 | 41 | /// 42 | /// The order for which the handler will be executed 43 | /// 44 | public int Order { get; set; } 45 | 46 | /// 47 | /// Method invoked before serializing a . 48 | /// Useful to add properties like . 49 | /// 50 | /// The client sending the request 51 | /// The method arguments 52 | /// The cancellation token 53 | /// Task to be awaited 54 | public virtual Task OnSoapEnvelopeRequestAsync(ISoapClient client, OnSoapEnvelopeRequestArguments arguments, CancellationToken ct) 55 | { 56 | return CachedTask; 57 | } 58 | 59 | /// 60 | /// Method invoked before sending the to the server. 61 | /// Useful to log the request or change properties like HTTP headers. 62 | /// 63 | /// The client sending the request 64 | /// The method arguments 65 | /// The cancellation token 66 | /// Task to be awaited 67 | public virtual Task OnHttpRequestAsync(ISoapClient client, OnHttpRequestArguments arguments, CancellationToken ct) 68 | { 69 | return CachedTask; 70 | } 71 | 72 | /// 73 | /// Method invoked after receiving a from the server. 74 | /// Useful to log the response or validate HTTP headers. 75 | /// 76 | /// The client sending the request 77 | /// The method arguments 78 | /// The cancellation token 79 | /// Task to be awaited 80 | public virtual Task OnHttpResponseAsync(ISoapClient client, OnHttpResponseArguments arguments, CancellationToken ct) 81 | { 82 | return CachedTask; 83 | } 84 | 85 | /// 86 | /// Method invoked after deserializing a from the server response. 87 | /// Useful to validate properties like . 88 | /// 89 | /// The client sending the request 90 | /// The method arguments 91 | /// The cancellation token 92 | /// Task to be awaited 93 | public virtual Task OnSoapEnvelopeResponseAsync(ISoapClient client, OnSoapEnvelopeResponseArguments arguments, CancellationToken ct) 94 | { 95 | return CachedTask; 96 | } 97 | 98 | #endregion 99 | } 100 | } -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Handlers/SoapHandlerArguments.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Handlers 25 | { 26 | using System; 27 | 28 | /// 29 | /// Base class for SOAP Handler argument classes 30 | /// 31 | public abstract class SoapHandlerArguments 32 | { 33 | /// 34 | /// Creates a new instance 35 | /// 36 | /// The SOAP service url 37 | /// The SOAP action 38 | /// An optional tracking id. If null will be used. 39 | /// 40 | /// 41 | protected SoapHandlerArguments(string url, string action, Guid? trackingId = null) 42 | { 43 | if (url == null) 44 | throw new ArgumentNullException(nameof(url)); 45 | if (action == null) 46 | throw new ArgumentNullException(nameof(action)); 47 | if (string.IsNullOrWhiteSpace(url)) 48 | throw new ArgumentException("Value cannot be null or whitespace.", nameof(url)); 49 | 50 | Url = url; 51 | Action = action; 52 | TrackingId = trackingId ?? Guid.NewGuid(); 53 | } 54 | 55 | #region Implementation of ISoapHandlerArguments 56 | 57 | /// 58 | /// The URL being invoked 59 | /// 60 | public string Url { get; } 61 | 62 | /// 63 | /// The action being invoked 64 | /// 65 | public string Action { get; } 66 | 67 | /// 68 | /// A unique identifier to track the current request 69 | /// 70 | public Guid TrackingId { get; } 71 | 72 | /// 73 | /// An object state that will be passed 74 | /// accross all the handlers 75 | /// 76 | public object State { get; set; } 77 | 78 | #endregion 79 | } 80 | } -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Helpers/ClientFactoryHelpers.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Helpers 25 | { 26 | using System; 27 | using System.Threading; 28 | using System.Threading.Tasks; 29 | 30 | /// 31 | /// Helper methods for working with instances. 32 | /// 33 | public static class ClientFactoryHelpers 34 | { 35 | #region Sync 36 | 37 | /// 38 | /// Gets a instance from the factory and releases 39 | /// when the action completes. 40 | /// 41 | /// The SOAP client type 42 | /// The factory to use 43 | /// The action to execute 44 | /// 45 | public static void GetAndRelease(this ISoapClientFactory factory, Action action) 46 | where TSoapClient : ISoapClient 47 | { 48 | if (factory == null) throw new ArgumentNullException(nameof(factory)); 49 | if (action == null) throw new ArgumentNullException(nameof(action)); 50 | 51 | var client = factory.Get(); 52 | try 53 | { 54 | action(client); 55 | } 56 | finally 57 | { 58 | factory.Release(client); 59 | } 60 | } 61 | 62 | /// 63 | /// Gets a instance from the factory and releases 64 | /// when the action completes. 65 | /// 66 | /// The factory to use 67 | /// The action to execute 68 | /// 69 | public static void GetAndRelease(this ISoapClientFactory factory, Action action) 70 | { 71 | GetAndRelease(factory, action); 72 | } 73 | 74 | /// 75 | /// Gets a instance from the factory and releases 76 | /// when the action completes. 77 | /// 78 | /// The SOAP client type 79 | /// The result type 80 | /// The factory to use 81 | /// The action to execute 82 | /// The action result 83 | /// 84 | public static TResult GetAndRelease(this ISoapClientFactory factory, Func action) 85 | where TSoapClient : ISoapClient 86 | { 87 | if (factory == null) throw new ArgumentNullException(nameof(factory)); 88 | if (action == null) throw new ArgumentNullException(nameof(action)); 89 | 90 | var client = factory.Get(); 91 | try 92 | { 93 | return action(client); 94 | } 95 | finally 96 | { 97 | factory.Release(client); 98 | } 99 | } 100 | 101 | /// 102 | /// Gets a instance from the factory and releases 103 | /// when the action completes. 104 | /// 105 | /// The result type 106 | /// The factory to use 107 | /// The action to execute 108 | /// The action result 109 | /// 110 | public static TResult GetAndRelease(this ISoapClientFactory factory, Func action) 111 | { 112 | return GetAndRelease(factory, action); 113 | } 114 | 115 | #endregion 116 | 117 | #region Async 118 | 119 | /// 120 | /// Gets a instance from the factory and releases 121 | /// when the action completes. 122 | /// 123 | /// The SOAP client type 124 | /// The factory to use 125 | /// The action to execute 126 | /// The cancelattion token 127 | /// A task that can be awaited 128 | /// 129 | public static async Task GetAndReleaseAsync( 130 | this ISoapClientFactory factory, Func action, CancellationToken ct = default(CancellationToken)) 131 | where TSoapClient : ISoapClient 132 | { 133 | if (factory == null) throw new ArgumentNullException(nameof(factory)); 134 | if (action == null) throw new ArgumentNullException(nameof(action)); 135 | 136 | var client = factory.Get(); 137 | try 138 | { 139 | await action(client, ct).ConfigureAwait(false); 140 | } 141 | finally 142 | { 143 | factory.Release(client); 144 | } 145 | } 146 | 147 | /// 148 | /// Gets a instance from the factory and releases 149 | /// when the action completes. 150 | /// 151 | /// The factory to use 152 | /// The action to execute 153 | /// The cancelattion token 154 | /// A task that can be awaited 155 | /// 156 | public static async Task GetAndReleaseAsync( 157 | this ISoapClientFactory factory, Func action, CancellationToken ct = default(CancellationToken)) 158 | { 159 | await GetAndReleaseAsync(factory, action, ct).ConfigureAwait(false); 160 | } 161 | 162 | /// 163 | /// Gets a instance from the factory and releases 164 | /// when the action completes. 165 | /// 166 | /// The SOAP client type 167 | /// The result type 168 | /// The factory to use 169 | /// The action to execute 170 | /// The cancellation token 171 | /// A task that can be awaited for the result 172 | /// 173 | public static async Task GetAndReleaseAsync( 174 | this ISoapClientFactory factory, Func> action, CancellationToken ct = default(CancellationToken)) 175 | where TSoapClient : ISoapClient 176 | { 177 | if (factory == null) throw new ArgumentNullException(nameof(factory)); 178 | if (action == null) throw new ArgumentNullException(nameof(action)); 179 | 180 | var client = factory.Get(); 181 | try 182 | { 183 | return await action(client, ct).ConfigureAwait(false); 184 | } 185 | finally 186 | { 187 | factory.Release(client); 188 | } 189 | } 190 | 191 | /// 192 | /// Gets a instance from the factory and releases 193 | /// when the action completes. 194 | /// 195 | /// The result type 196 | /// The factory to use 197 | /// The action to execute 198 | /// The cancellation token 199 | /// A task that can be awaited for the result 200 | /// 201 | public static async Task GetAndReleaseAsync( 202 | this ISoapClientFactory factory, Func> action, CancellationToken ct = default(CancellationToken)) 203 | { 204 | return await GetAndReleaseAsync(factory, action, ct).ConfigureAwait(false); 205 | } 206 | 207 | #endregion 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Helpers/ClientHelpers.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | 25 | using SimpleSOAPClient.Models; 26 | 27 | namespace SimpleSOAPClient.Helpers 28 | { 29 | using System; 30 | using System.Net.Http; 31 | using System.Threading; 32 | using System.Threading.Tasks; 33 | using Handlers; 34 | 35 | /// 36 | /// Helper methods for working with instances. 37 | /// 38 | public static class ClientHelpers 39 | { 40 | #region Settings 41 | 42 | /// 43 | /// Sets the to be used by the client. 44 | /// 45 | /// The SOAP client type 46 | /// The client to be used 47 | /// The settings to be used 48 | /// The SOAP client after changes 49 | /// 50 | public static TSoapClient UsingSettings( 51 | this TSoapClient client, SoapClientSettings settings) 52 | where TSoapClient : ISoapClient 53 | { 54 | if (client == null) throw new ArgumentNullException(nameof(client)); 55 | if (settings == null) throw new ArgumentNullException(nameof(settings)); 56 | 57 | client.Settings = settings; 58 | return client; 59 | } 60 | 61 | /// 62 | /// Sets the as the settings to be used by the client. 63 | /// 64 | /// The SOAP client type 65 | /// The client to be used 66 | /// The SOAP client after changes 67 | /// 68 | public static TSoapClient UsingDefaultSettings(this TSoapClient client) 69 | where TSoapClient : ISoapClient 70 | { 71 | if (client == null) throw new ArgumentNullException(nameof(client)); 72 | 73 | client.Settings = SoapClientSettings.Default; 74 | return client; 75 | } 76 | 77 | #endregion 78 | 79 | #region Handlers 80 | 81 | /// 82 | /// Adds the given handler to the SOAP client 83 | /// 84 | /// The SOAP client type 85 | /// The client to be used 86 | /// The handler to add 87 | /// The SOAP client after changes 88 | /// 89 | public static TSoapClient WithHandler(this TSoapClient client, ISoapHandler handler) 90 | where TSoapClient : ISoapClient 91 | { 92 | if (client == null) throw new ArgumentNullException(nameof(client)); 93 | if (handler == null) throw new ArgumentNullException(nameof(handler)); 94 | 95 | client.AddHandler(handler); 96 | return client; 97 | } 98 | 99 | #region OnSoapEnvelopeRequest 100 | 101 | /// 102 | /// Assigns the given delegate has an handler for 103 | /// operations using a as a wrapper. 104 | /// 105 | /// The SOAP client type 106 | /// The client to be used 107 | /// The handler action 108 | /// The handler order 109 | /// The SOAP client after changes 110 | /// 111 | public static TSoapClient OnSoapEnvelopeRequest( 112 | this TSoapClient client, Func action, int order = 0) 113 | where TSoapClient : ISoapClient 114 | { 115 | if (client == null) throw new ArgumentNullException(nameof(client)); 116 | if (action == null) throw new ArgumentNullException(nameof(action)); 117 | 118 | client.AddHandler(new DelegatingSoapHandler 119 | { 120 | Order = order, 121 | OnSoapEnvelopeRequestAsyncAction = action 122 | }); 123 | return client; 124 | } 125 | 126 | /// 127 | /// Assigns the given delegate has an handler for 128 | /// operations using a as a wrapper. 129 | /// 130 | /// The SOAP client type 131 | /// The client to be used 132 | /// The handler action 133 | /// The handler order 134 | /// The SOAP client after changes 135 | /// 136 | public static TSoapClient OnSoapEnvelopeRequest( 137 | this TSoapClient client, Func action, int order = 0) 138 | where TSoapClient : ISoapClient 139 | { 140 | if (client == null) throw new ArgumentNullException(nameof(client)); 141 | if (action == null) throw new ArgumentNullException(nameof(action)); 142 | 143 | client.AddHandler(new DelegatingSoapHandler 144 | { 145 | Order = order, 146 | OnSoapEnvelopeRequestAsyncAction = async (c, args, ct) => await action(args, ct) 147 | }); 148 | return client; 149 | } 150 | 151 | #endregion 152 | 153 | #region OnHttpRequest 154 | 155 | /// 156 | /// Assigns the given delegate has an handler for 157 | /// operations using a as a wrapper. 158 | /// 159 | /// The SOAP client type 160 | /// The client to be used 161 | /// The handler action 162 | /// The handler order 163 | /// The SOAP client after changes 164 | /// 165 | public static TSoapClient OnHttpRequest( 166 | this TSoapClient client, Func action, int order = 0) 167 | where TSoapClient : ISoapClient 168 | { 169 | if (client == null) throw new ArgumentNullException(nameof(client)); 170 | if (action == null) throw new ArgumentNullException(nameof(action)); 171 | 172 | client.AddHandler(new DelegatingSoapHandler 173 | { 174 | Order = order, 175 | OnHttpRequestAsyncAction = action 176 | }); 177 | return client; 178 | } 179 | 180 | /// 181 | /// Assigns the given delegate has an handler for 182 | /// operations using a as a wrapper. 183 | /// 184 | /// The SOAP client type 185 | /// The client to be used 186 | /// The handler action 187 | /// The handler order 188 | /// The SOAP client after changes 189 | /// 190 | public static TSoapClient OnHttpRequest( 191 | this TSoapClient client, Func action, int order = 0) 192 | where TSoapClient : ISoapClient 193 | { 194 | if (client == null) throw new ArgumentNullException(nameof(client)); 195 | if (action == null) throw new ArgumentNullException(nameof(action)); 196 | 197 | client.AddHandler(new DelegatingSoapHandler 198 | { 199 | Order = order, 200 | OnHttpRequestAsyncAction = async (c, args, ct) => await action(args, ct) 201 | }); 202 | return client; 203 | } 204 | 205 | #endregion 206 | 207 | #region OnHttpResponse 208 | 209 | /// 210 | /// Assigns the given delegate has an handler for 211 | /// operations using a as a wrapper. 212 | /// 213 | /// The SOAP client type 214 | /// The client to be used 215 | /// The handler action 216 | /// The handler order 217 | /// The SOAP client after changes 218 | /// 219 | public static TSoapClient OnHttpResponse( 220 | this TSoapClient client, Func action, int order = 0) 221 | where TSoapClient : ISoapClient 222 | { 223 | if (client == null) throw new ArgumentNullException(nameof(client)); 224 | if (action == null) throw new ArgumentNullException(nameof(action)); 225 | 226 | client.AddHandler(new DelegatingSoapHandler 227 | { 228 | Order = order, 229 | OnHttpResponseAsyncAction = action 230 | }); 231 | return client; 232 | } 233 | 234 | /// 235 | /// Assigns the given delegate has an handler for 236 | /// operations using a as a wrapper. 237 | /// 238 | /// The SOAP client type 239 | /// The client to be used 240 | /// The handler action 241 | /// The handler order 242 | /// The SOAP client after changes 243 | /// 244 | public static TSoapClient OnHttpResponse( 245 | this TSoapClient client, Func action, int order = 0) 246 | where TSoapClient : ISoapClient 247 | { 248 | if (client == null) throw new ArgumentNullException(nameof(client)); 249 | if (action == null) throw new ArgumentNullException(nameof(action)); 250 | 251 | client.AddHandler(new DelegatingSoapHandler 252 | { 253 | Order = order, 254 | OnHttpResponseAsyncAction = async (c, args, ct) => await action(args, ct) 255 | }); 256 | return client; 257 | } 258 | 259 | #endregion 260 | 261 | #region OnSoapEnvelopeResponse 262 | 263 | /// 264 | /// Assigns the given delegate has an handler for 265 | /// operations using a as a wrapper. 266 | /// 267 | /// The SOAP client type 268 | /// The client to be used 269 | /// The handler action 270 | /// The handler order 271 | /// The SOAP client after changes 272 | /// 273 | public static TSoapClient OnSoapEnvelopeResponse( 274 | this TSoapClient client, Func action, int order = 0) 275 | where TSoapClient : ISoapClient 276 | { 277 | if (client == null) throw new ArgumentNullException(nameof(client)); 278 | if (action == null) throw new ArgumentNullException(nameof(action)); 279 | 280 | client.AddHandler(new DelegatingSoapHandler 281 | { 282 | Order = order, 283 | OnSoapEnvelopeResponseAsyncAction = action 284 | }); 285 | return client; 286 | } 287 | 288 | /// 289 | /// Assigns the given delegate has an handler for 290 | /// operations using a as a wrapper. 291 | /// 292 | /// The SOAP client type 293 | /// The client to be used 294 | /// The handler action 295 | /// The handler order 296 | /// The SOAP client after changes 297 | /// 298 | public static TSoapClient OnSoapEnvelopeResponse( 299 | this TSoapClient client, Func action, int order = 0) 300 | where TSoapClient : ISoapClient 301 | { 302 | if (client == null) throw new ArgumentNullException(nameof(client)); 303 | if (action == null) throw new ArgumentNullException(nameof(action)); 304 | 305 | client.AddHandler(new DelegatingSoapHandler 306 | { 307 | Order = order, 308 | OnSoapEnvelopeResponseAsyncAction = async (c, args, ct) => await action(args, ct) 309 | }); 310 | return client; 311 | } 312 | 313 | #endregion 314 | 315 | #endregion 316 | 317 | #region HttpClient 318 | 319 | /// 320 | /// Allows an handler to configure the instance. 321 | /// 322 | /// The SOAP Client type 323 | /// The client to configure 324 | /// The configuration handler 325 | /// The client after changes 326 | public static TSoapClient UsingClientConfiguration( 327 | this TSoapClient client, Action cfgHandler) 328 | where TSoapClient : SoapClient 329 | { 330 | if (client == null) throw new ArgumentNullException(nameof(client)); 331 | if (cfgHandler == null) throw new ArgumentNullException(nameof(cfgHandler)); 332 | 333 | cfgHandler(client.HttpClient); 334 | 335 | return client; 336 | } 337 | 338 | #endregion 339 | 340 | /// 341 | /// Sends the given into the specified url. 342 | /// 343 | /// The client to be used 344 | /// The url that will receive the request 345 | /// The SOAP Action beeing performed 346 | /// The to be sent 347 | /// The resulting 348 | /// 349 | public static SoapEnvelope Send( 350 | this ISoapClient client, string url, string action, SoapEnvelope requestEnvelope) 351 | { 352 | if (client == null) throw new ArgumentNullException(nameof(client)); 353 | 354 | return client.SendAsync(url, action, requestEnvelope, CancellationToken.None) 355 | .ConfigureAwait(false) 356 | .GetAwaiter() 357 | .GetResult(); 358 | } 359 | } 360 | } 361 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Helpers/EnvelopeHelpers.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Helpers 25 | { 26 | using System; 27 | using System.Collections.Generic; 28 | using System.Linq; 29 | using System.Xml.Linq; 30 | using Exceptions; 31 | using Models; 32 | 33 | /// 34 | /// Helper methods for working with instances. 35 | /// 36 | public static class EnvelopeHelpers 37 | { 38 | private static readonly XName SoapFaultXName = 39 | XName.Get("Fault", Constant.Namespace.OrgXmlSoapSchemasSoapEnvelope); 40 | 41 | #region Body 42 | 43 | /// 44 | /// Sets the given as the envelope body. 45 | /// 46 | /// The to be used. 47 | /// The to set as the body. 48 | /// The after changes. 49 | /// 50 | public static SoapEnvelope Body(this SoapEnvelope envelope, XElement body) 51 | { 52 | if (envelope == null) throw new ArgumentNullException(nameof(envelope)); 53 | 54 | if (envelope.Body == null) 55 | envelope.Body = new SoapEnvelopeBody(); 56 | 57 | envelope.Body.Value = body; 58 | 59 | return envelope; 60 | } 61 | 62 | /// 63 | /// Sets the given entity as the envelope body. 64 | /// 65 | /// The object type 66 | /// The to be used. 67 | /// The entity to set as the body. 68 | /// The after changes. 69 | /// 70 | public static SoapEnvelope Body(this SoapEnvelope envelope, T body) 71 | { 72 | return envelope.Body(body.ToXElement()); 73 | } 74 | 75 | /// 76 | /// Extracts the as an object of the given type. 77 | /// 78 | /// The type do be deserialized. 79 | /// The 80 | /// The deserialized object 81 | /// 82 | /// Thrown if the body contains a fault 83 | public static T Body(this SoapEnvelope envelope) 84 | { 85 | if (envelope == null) throw new ArgumentNullException(nameof(envelope)); 86 | 87 | envelope.ThrowIfFaulted(); 88 | 89 | return envelope.Body.Value.ToObject(); 90 | } 91 | 92 | #endregion 93 | 94 | #region Headers 95 | 96 | /// 97 | /// Appends the received collection to the existing 98 | /// ones in the received . 99 | /// 100 | /// The to append the headers 101 | /// The collection to append 102 | /// The after changes 103 | /// 104 | public static SoapEnvelope WithHeaders( 105 | this SoapEnvelope envelope, params XElement[] headers) 106 | { 107 | if (envelope == null) throw new ArgumentNullException(nameof(envelope)); 108 | if (headers == null) throw new ArgumentNullException(nameof(headers)); 109 | 110 | if (headers.Length == 0) return envelope; 111 | 112 | if (envelope.Header == null) 113 | { 114 | envelope.Header = new SoapEnvelopeHeader 115 | { 116 | Headers = headers 117 | }; 118 | } 119 | else 120 | { 121 | var envelopeHeaders = new List(envelope.Header.Headers); 122 | envelopeHeaders.AddRange(headers); 123 | envelope.Header.Headers = envelopeHeaders.ToArray(); 124 | } 125 | 126 | return envelope; 127 | } 128 | 129 | /// 130 | /// Appends the received collection to the existing 131 | /// ones in the received . 132 | /// 133 | /// The to append the headers 134 | /// The collection to append 135 | /// The after changes 136 | /// 137 | public static SoapEnvelope WithHeaders( 138 | this SoapEnvelope envelope, IEnumerable headers) 139 | { 140 | return envelope.WithHeaders(headers.ToArray()); 141 | } 142 | 143 | /// 144 | /// Appends the received collection to the existing 145 | /// ones in the received . 146 | /// 147 | /// The to append the headers 148 | /// The collection to append 149 | /// The after changes 150 | /// 151 | public static SoapEnvelope WithHeaders( 152 | this SoapEnvelope envelope, params SoapHeader[] headers) 153 | { 154 | if (envelope == null) throw new ArgumentNullException(nameof(envelope)); 155 | if (headers == null) throw new ArgumentNullException(nameof(headers)); 156 | 157 | if (headers.Length == 0) return envelope; 158 | 159 | var xElementHeaders = new XElement[headers.Length]; 160 | for (var i = 0; i < headers.Length; i++) 161 | xElementHeaders[i] = headers[i].ToXElement(); 162 | 163 | return envelope.WithHeaders(xElementHeaders); 164 | } 165 | 166 | /// 167 | /// Appends the received collection to the existing 168 | /// ones in the received . 169 | /// 170 | /// The to append the headers 171 | /// The collection to append 172 | /// The after changes 173 | /// 174 | public static SoapEnvelope WithHeaders( 175 | this SoapEnvelope envelope, IEnumerable headers) 176 | { 177 | return envelope.WithHeaders(headers.ToArray()); 178 | } 179 | 180 | /// 181 | /// Gets a given by its . 182 | /// 183 | /// The with the headers. 184 | /// The to search. 185 | /// The or null if not match is found 186 | /// 187 | public static XElement Header(this SoapEnvelope envelope, XName name) 188 | { 189 | if (envelope == null) throw new ArgumentNullException(nameof(envelope)); 190 | 191 | if (envelope.Header == null || envelope.Header.Headers.Length == 0) 192 | return null; 193 | 194 | return envelope.Header.Headers.FirstOrDefault(xElement => xElement.Name == name); 195 | } 196 | 197 | /// 198 | /// Gets a given by its . 199 | /// 200 | /// The with the headers. 201 | /// The to search. 202 | /// The or null if not match is found 203 | /// 204 | public static T Header(this SoapEnvelope envelope, XName name) 205 | where T: SoapHeader 206 | { 207 | return envelope.Header(name).ToObject(); 208 | } 209 | 210 | #endregion 211 | 212 | #region Faulted 213 | 214 | /// 215 | /// Does the contains a fault? 216 | /// 217 | /// The to validate 218 | /// True if a fault exists 219 | /// 220 | public static bool IsFaulted(this SoapEnvelope envelope) 221 | { 222 | if (envelope == null) throw new ArgumentNullException(nameof(envelope)); 223 | 224 | return envelope.Body?.Value != null && envelope.Body.Value.Name == SoapFaultXName; 225 | } 226 | 227 | /// 228 | /// Checks if the contains a fault 229 | /// and throws an if true. 230 | /// 231 | /// The to validate. 232 | /// 233 | /// Thrown if the body contains a fault 234 | public static void ThrowIfFaulted(this SoapEnvelope envelope) 235 | { 236 | if (envelope == null) throw new ArgumentNullException(nameof(envelope)); 237 | 238 | if (!envelope.IsFaulted()) return; 239 | 240 | var fault = envelope.Fault(); 241 | throw new FaultException 242 | { 243 | Code = fault.Code, 244 | String = fault.String, 245 | Actor = fault.Actor, 246 | Detail = fault.Detail 247 | }; 248 | } 249 | 250 | /// 251 | /// Extracts the as a . 252 | /// It will fail to deserialize if the body is not a fault. Consider to 253 | /// use first. 254 | /// 255 | /// The to be used 256 | /// The 257 | /// 258 | public static SoapFault Fault(this SoapEnvelope envelope) 259 | { 260 | if (envelope == null) throw new ArgumentNullException(nameof(envelope)); 261 | 262 | return envelope.Body?.Value.ToObject(); 263 | } 264 | 265 | #endregion 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Helpers/XmlHelpers.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | 25 | using System.Runtime.CompilerServices; 26 | using System.IO; 27 | using System.Xml; 28 | using System.Xml.Linq; 29 | using System.Xml.Serialization; 30 | using System; 31 | 32 | [assembly: InternalsVisibleTo("SimpleSOAPClient.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e9d4b3865537a3" + 33 | "5aabe1076ab836c58e47a3315970568d17b1d58b6d08a648e6333a714112adeb9481d79cd3a529" + 34 | "ab6ee0e643b9098fa703ca085202968cb4792fc1ccc0d85fff62ed01993ed67f5cf5c2fac83622" + 35 | "e019654eab372c6c4ecefbc8198b267ed757b30da82779857ca6861204961aa175ef48a7e79ad3" + 36 | "b0d754bd")] 37 | namespace SimpleSOAPClient.Helpers 38 | { 39 | 40 | 41 | 42 | 43 | /// 44 | /// Helper class with extensions for XML manipulation 45 | /// 46 | internal static class XmlHelpers 47 | { 48 | private static readonly XmlSerializerNamespaces EmptyXmlSerializerNamespaces; 49 | 50 | static XmlHelpers() 51 | { 52 | EmptyXmlSerializerNamespaces = new XmlSerializerNamespaces(); 53 | EmptyXmlSerializerNamespaces.Add("", ""); 54 | } 55 | 56 | /// 57 | /// Serializes the given object to a XML string 58 | /// 59 | /// The object type 60 | /// The item to serialize 61 | /// Remove the XML declaration 62 | /// The XML string 63 | public static string ToXmlString(this T item, bool removeXmlDeclaration) 64 | { 65 | if (item == null) return null; 66 | 67 | using (var textWriter = new StringWriter()) 68 | using (var xmlWriter = XmlWriter.Create(textWriter, new XmlWriterSettings 69 | { 70 | OmitXmlDeclaration = removeXmlDeclaration, 71 | Indent = false, 72 | NamespaceHandling = NamespaceHandling.OmitDuplicates 73 | })) 74 | { 75 | #if NETSTANDARD2_0 || NET45 76 | if (Attribute.IsDefined(item.GetType(), typeof(System.Runtime.Serialization.DataContractAttribute))) 77 | { 78 | var serializer = new System.Runtime.Serialization.DataContractSerializer(typeof(T)); 79 | serializer.WriteObject(xmlWriter, item); 80 | xmlWriter.Flush(); 81 | return textWriter.ToString(); 82 | } 83 | #endif 84 | new XmlSerializer(item.GetType()) 85 | .Serialize(xmlWriter, item, EmptyXmlSerializerNamespaces); 86 | return textWriter.ToString(); 87 | } 88 | } 89 | 90 | /// 91 | /// Serializes the given object to a XML string 92 | /// 93 | /// The object type 94 | /// The item to serialize 95 | /// The XML string 96 | public static string ToXmlString(this T item) 97 | { 98 | return item.ToXmlString(true); 99 | } 100 | 101 | /// 102 | /// Serializes a given object to XML and returns the representation. 103 | /// 104 | /// The object type 105 | /// The item to convert 106 | /// Remove the XML declaration 107 | /// The object as a 108 | public static XElement ToXElement(this T item, bool removeXmlDeclaration) 109 | { 110 | return item == null ? null : XElement.Parse(item.ToXmlString(removeXmlDeclaration)); 111 | } 112 | 113 | /// 114 | /// Serializes a given object to XML and returns the representation. 115 | /// 116 | /// The object type 117 | /// The item to convert 118 | /// The object as a 119 | public static XElement ToXElement(this T item) 120 | { 121 | return item.ToXElement(false); 122 | } 123 | 124 | /// 125 | /// Deserializes a given XML string to a new object of the expected type. 126 | /// If null or white spaces the default(T) will be returned; 127 | /// 128 | /// The type to be deserializable 129 | /// The XML string to deserialize 130 | /// The deserialized object 131 | public static T ToObject(this string xml) 132 | { 133 | if (string.IsNullOrWhiteSpace(xml)) return default(T); 134 | 135 | using (var stringReader = new StringReader(xml)) 136 | using (var xmlReader = XmlReader.Create(stringReader)) 137 | { 138 | #if NETSTANDARD2_0 || NET45 139 | if (Attribute.IsDefined(typeof(T), typeof(System.Runtime.Serialization.DataContractAttribute))) 140 | { 141 | var serializer = new System.Runtime.Serialization.DataContractSerializer(typeof(T)); 142 | return (T)serializer.ReadObject(xmlReader); 143 | } 144 | #endif 145 | 146 | var result = (T)new XmlSerializer(typeof(T)).Deserialize(xmlReader); 147 | return result; 148 | } 149 | } 150 | 151 | /// 152 | /// Deserializes a given to a new object of the expected type. 153 | /// If null the default(T) will be returned. 154 | /// 155 | /// The type to be deserializable 156 | /// The to deserialize 157 | /// The deserialized object 158 | public static T ToObject(this XElement xml) 159 | { 160 | return xml == null ? default(T) : xml.ToString().ToObject(); 161 | } 162 | } 163 | } -------------------------------------------------------------------------------- /src/SimpleSOAPClient/HttpClientFactory.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient 25 | { 26 | using System; 27 | using System.Collections.Generic; 28 | using System.Linq; 29 | using System.Net.Http; 30 | 31 | /// 32 | /// The factory to be used by 33 | /// when no client is provided. 34 | /// 35 | public class HttpClientFactory : IHttpClientFactory 36 | { 37 | private readonly List>> _defaultRequestHeaders; 38 | 39 | /// 40 | /// Gets or sets the default base address of Uniform Resource Identifier (URI) of the Internet 41 | /// resource used when sending requests. 42 | /// 43 | public Uri DefaultBaseAddress { get; set; } 44 | 45 | /// 46 | /// The default response content buffer size 47 | /// 48 | public long DefaultMaxResponseContentBufferSize { get; set; } 49 | 50 | /// 51 | /// The default request timeout 52 | /// 53 | public TimeSpan DefaultTimeout { get; set; } 54 | 55 | /// 56 | /// The defauld HTTP request headers that should be sent in every request. 57 | /// 58 | public IReadOnlyCollection>> DefaultRequestHeaders => _defaultRequestHeaders; 59 | 60 | /// 61 | /// Creates a new instance 62 | /// 63 | public HttpClientFactory() 64 | { 65 | var httpClient = new HttpClient(); 66 | DefaultBaseAddress = httpClient.BaseAddress; 67 | DefaultMaxResponseContentBufferSize = httpClient.MaxResponseContentBufferSize; 68 | DefaultTimeout = httpClient.Timeout; 69 | 70 | _defaultRequestHeaders = 71 | httpClient.DefaultRequestHeaders.Select( 72 | e => new KeyValuePair>(e.Key, e.Value)).ToList(); 73 | } 74 | 75 | /// 76 | /// Adds the given name avd values to the default request header collection. 77 | /// 78 | /// The header name 79 | /// The header values 80 | public void AddDefaultRequestHeader(string name, IEnumerable values) 81 | { 82 | _defaultRequestHeaders.Add(new KeyValuePair>(name, values)); 83 | } 84 | 85 | /// 86 | /// Adds the given name avd values to the default request header collection. 87 | /// 88 | /// The header name 89 | /// The header values 90 | public void AddDefaultRequestHeader(string name, params string[] values) 91 | { 92 | _defaultRequestHeaders.Add(new KeyValuePair>(name, values)); 93 | } 94 | 95 | #region Implementation of IHttpClientFactory 96 | 97 | /// 98 | /// Returns a new instance. 99 | /// 100 | /// The HTTP client 101 | public HttpClient Get() 102 | { 103 | var client = new HttpClient 104 | { 105 | BaseAddress = DefaultBaseAddress, 106 | MaxResponseContentBufferSize = DefaultMaxResponseContentBufferSize, 107 | Timeout = DefaultTimeout 108 | }; 109 | foreach (var header in DefaultRequestHeaders) 110 | client.DefaultRequestHeaders.Add(header.Key, header.Value); 111 | 112 | return client; 113 | } 114 | 115 | /// 116 | /// Returns a new instance that should used 117 | /// the given . 118 | /// 119 | /// The HTTP message handler 120 | /// The HTTP client 121 | public HttpClient Get(HttpMessageHandler handler) 122 | { 123 | var client = new HttpClient(handler) 124 | { 125 | BaseAddress = DefaultBaseAddress, 126 | MaxResponseContentBufferSize = DefaultMaxResponseContentBufferSize, 127 | Timeout = DefaultTimeout 128 | }; 129 | foreach (var header in DefaultRequestHeaders) 130 | client.DefaultRequestHeaders.Add(header.Key, header.Value); 131 | 132 | return client; 133 | } 134 | 135 | #endregion 136 | } 137 | } -------------------------------------------------------------------------------- /src/SimpleSOAPClient/IHttpClientFactory.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient 25 | { 26 | using System.Net.Http; 27 | 28 | /// 29 | /// The factory to be used by 30 | /// when no client is provided. 31 | /// 32 | public interface IHttpClientFactory 33 | { 34 | /// 35 | /// Returns a new instance. 36 | /// 37 | /// The HTTP client 38 | HttpClient Get(); 39 | 40 | /// 41 | /// Returns a new instance that should used 42 | /// the given . 43 | /// 44 | /// The HTTP message handler 45 | /// The HTTP client 46 | HttpClient Get(HttpMessageHandler handler); 47 | } 48 | } -------------------------------------------------------------------------------- /src/SimpleSOAPClient/ISoapClient.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity00/SimpleSOAPClient/e41d82d00a6a4338c5943ed125fac5d0dfa2d6dd/src/SimpleSOAPClient/ISoapClient.cs -------------------------------------------------------------------------------- /src/SimpleSOAPClient/ISoapClientFactory.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient 25 | { 26 | /// 27 | /// Creates instances 28 | /// 29 | public interface ISoapClientFactory 30 | { 31 | /// 32 | /// Gets an . 33 | /// 34 | /// The SOAP client type 35 | /// 36 | TSoapClient Get() where TSoapClient : ISoapClient; 37 | 38 | /// 39 | /// Indicates to the factory that the given 40 | /// is no longer needed. 41 | /// 42 | /// The SOAP client to release 43 | void Release(ISoapClient client); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/ISoapEnvelopeSerializationProvider.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient 25 | { 26 | using Models; 27 | 28 | /// 29 | /// Provider for serialization and deserialization of instances. 30 | /// 31 | public interface ISoapEnvelopeSerializationProvider 32 | { 33 | /// 34 | /// Serializes a given instance into a XML string. 35 | /// 36 | /// The instance to serialize 37 | /// The resulting XML string 38 | string ToXmlString(SoapEnvelope envelope); 39 | 40 | /// 41 | /// Deserializes a given XML string into a . 42 | /// 43 | /// The XML string do deserialize 44 | /// The resulting 45 | SoapEnvelope ToSoapEnvelope(string xml); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Models/Headers/KnownHeader.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Models.Headers 25 | { 26 | using System; 27 | using Microsoft; 28 | using Oasis.Security; 29 | 30 | /// 31 | /// Class with known builder methods. 32 | /// 33 | public static class KnownHeader 34 | { 35 | /// 36 | /// Class with Microsoft specific builder methods. 37 | /// 38 | public static class Microsoft 39 | { 40 | /// 41 | /// Creates a new Microsoft Action SOAP Header. 42 | /// 43 | /// The action for the header 44 | /// Does the server must understand the header? 45 | /// The new 46 | public static ActionSoapHeader Action(string action, bool mustUnderstand = true) 47 | { 48 | return new ActionSoapHeader 49 | { 50 | Action = action, 51 | MustUnderstand = mustUnderstand ? 1 : 0 52 | }; 53 | } 54 | 55 | /// 56 | /// Creates a new Microsoft To SOAP Header. 57 | /// 58 | /// The action for the header 59 | /// Does the server must understand the header? 60 | /// The new 61 | public static ToSoapHeader To(string to, bool mustUnderstand = true) 62 | { 63 | return new ToSoapHeader 64 | { 65 | To = to, 66 | MustUnderstand = mustUnderstand ? 1 : 0 67 | }; 68 | } 69 | } 70 | 71 | /// 72 | /// Class with Oasis specific builder methods. 73 | /// 74 | public static class Oasis 75 | { 76 | /// 77 | /// Class with Oasis Security specific builder methods. 78 | /// 79 | public static class Security 80 | { 81 | /// 82 | /// Creates a new Oasis Security Username Token with password text SOAP header. 83 | /// 84 | /// The username 85 | /// The password 86 | /// Does the server must understand the header? 87 | /// The new 88 | public static UsernameTokenAndPasswordTextSoapHeader UsernameTokenAndPasswordText( 89 | string username, string password, bool mustUnderstand = true) 90 | { 91 | var randomId = Guid.NewGuid().ToString("N"); 92 | 93 | return new UsernameTokenAndPasswordTextSoapHeader 94 | { 95 | Timestamp = new Timestamp 96 | { 97 | Id = string.Concat("_TS", randomId), 98 | Created = DateTime.UtcNow, 99 | Expires = DateTime.UtcNow.AddMinutes(15) 100 | }, 101 | UsernameToken = new UsernameTokenWithPasswordText 102 | { 103 | Id = string.Concat("_UT", randomId), 104 | Username = username, 105 | Password = new UsernameTokenPasswordText 106 | { 107 | Value = password 108 | } 109 | }, 110 | MustUnderstand = mustUnderstand ? 1 : 0 111 | }; 112 | } 113 | } 114 | } 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Models/Headers/Microsoft/ActionSoapHeader.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity00/SimpleSOAPClient/e41d82d00a6a4338c5943ed125fac5d0dfa2d6dd/src/SimpleSOAPClient/Models/Headers/Microsoft/ActionSoapHeader.cs -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Models/Headers/Microsoft/ToSoapHeader.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Models.Headers.Microsoft 25 | { 26 | using System.Xml.Serialization; 27 | 28 | /// 29 | /// The Microsoft To SOAP Header 30 | /// 31 | [XmlRoot("To", Namespace = Constant.Namespace.ComMicrosoftSchemasWs200505AddressingNone)] 32 | public class ToSoapHeader : SoapHeader 33 | { 34 | /// 35 | /// The header to content 36 | /// 37 | [XmlText] 38 | public string To { get; set; } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Models/Headers/Oasis/Security/SecuritySoapHeader.cs: -------------------------------------------------------------------------------- 1 | namespace SimpleSOAPClient.Models.Headers.Oasis.Security 2 | { 3 | using System.Xml.Serialization; 4 | 5 | /// 6 | /// Represents the SOAP Security Header 7 | /// 8 | [XmlRoot("Security", 9 | Namespace = Constant.Namespace.OrgOpenOasisDocsWss200401Oasis200401WssWssecuritySecext10)] 10 | public class SecuritySoapHeader : SoapHeader 11 | { 12 | /// 13 | /// The header timestamp 14 | /// 15 | [XmlElement("Timestamp", 16 | Namespace = Constant.Namespace.OrgOpenOasisDocsWss200401Oasis200401WssWssecurityUtility10)] 17 | public Timestamp Timestamp { get; set; } 18 | 19 | /// 20 | /// Creates a new instance 21 | /// 22 | public SecuritySoapHeader() 23 | { 24 | MustUnderstand = 1; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Models/Headers/Oasis/Security/Timestamp.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Models.Headers.Oasis.Security 25 | { 26 | using System; 27 | using System.Xml.Serialization; 28 | 29 | /// 30 | /// Represents a SOAP Security timestamp 31 | /// 32 | [XmlType("Timestamp", 33 | Namespace = Constant.Namespace.OrgOpenOasisDocsWss200401Oasis200401WssWssecurityUtility10)] 34 | public class Timestamp 35 | { 36 | /// 37 | /// The timestamp id 38 | /// 39 | [XmlAttribute("Id", 40 | Namespace = Constant.Namespace.OrgOpenOasisDocsWss200401Oasis200401WssWssecurityUtility10)] 41 | public string Id { get; set; } 42 | 43 | /// 44 | /// The date and time when the timestamp was created 45 | /// 46 | [XmlElement("Created", 47 | Namespace = Constant.Namespace.OrgOpenOasisDocsWss200401Oasis200401WssWssecurityUtility10)] 48 | public DateTime Created { get; set; } 49 | 50 | /// 51 | /// The date and time when the timestamp expired 52 | /// 53 | [XmlElement("Expires", 54 | Namespace = Constant.Namespace.OrgOpenOasisDocsWss200401Oasis200401WssWssecurityUtility10)] 55 | public DateTime Expires { get; set; } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Models/Headers/Oasis/Security/UsernameTokenAndPasswordTextSoapHeader.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Models.Headers.Oasis.Security 25 | { 26 | using System.Xml.Serialization; 27 | 28 | /// 29 | /// The SOAP Security header for username and text passwords 30 | /// 31 | [XmlRoot("Security", 32 | Namespace = Constant.Namespace.OrgOpenOasisDocsWss200401Oasis200401WssWssecuritySecext10)] 33 | public class UsernameTokenAndPasswordTextSoapHeader : SecuritySoapHeader 34 | { 35 | /// 36 | /// The username token 37 | /// 38 | [XmlElement("UsernameToken", 39 | Namespace = Constant.Namespace.OrgOpenOasisDocsWss200401Oasis200401WssWssecuritySecext10)] 40 | public UsernameTokenWithPasswordText UsernameToken { get; set; } 41 | 42 | /// 43 | /// Creates a new instance 44 | /// 45 | public UsernameTokenAndPasswordTextSoapHeader() 46 | { 47 | MustUnderstand = 1; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Models/Headers/Oasis/Security/UsernameTokenPasswordText.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Models.Headers.Oasis.Security 25 | { 26 | using System.Xml.Serialization; 27 | 28 | /// 29 | /// Represents the password text 30 | /// 31 | [XmlType("Password", 32 | Namespace = Constant.Namespace.OrgOpenOasisDocsWss200401Oasis200401WssWssecuritySecext10)] 33 | public class UsernameTokenPasswordText 34 | { 35 | /// 36 | /// The password type 37 | /// 38 | [XmlAttribute("Type", Namespace = "")] 39 | public string Type { get; set; } 40 | 41 | /// 42 | /// The password value 43 | /// 44 | [XmlText] 45 | public string Value { get; set; } 46 | 47 | /// 48 | /// Creates a new instance 49 | /// 50 | public UsernameTokenPasswordText() 51 | { 52 | Type = Constant.Namespace.OrgOpenOasisDocsWss200401Oasis200401WssUsernameTokenProfile10PasswordText; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Models/Headers/Oasis/Security/UsernameTokenWithPasswordText.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Models.Headers.Oasis.Security 25 | { 26 | using System.Xml.Serialization; 27 | 28 | /// 29 | /// Represents an username token with a password text 30 | /// 31 | [XmlType("UsernameToken", 32 | Namespace = Constant.Namespace.OrgOpenOasisDocsWss200401Oasis200401WssWssecuritySecext10)] 33 | public class UsernameTokenWithPasswordText 34 | { 35 | /// 36 | /// The token id 37 | /// 38 | [XmlAttribute("Id", 39 | Namespace = Constant.Namespace.OrgOpenOasisDocsWss200401Oasis200401WssWssecurityUtility10)] 40 | public string Id { get; set; } 41 | 42 | /// 43 | /// The username value 44 | /// 45 | [XmlElement("Username", 46 | Namespace = Constant.Namespace.OrgOpenOasisDocsWss200401Oasis200401WssWssecuritySecext10)] 47 | public string Username { get; set; } 48 | 49 | /// 50 | /// The password element 51 | /// 52 | [XmlElement("Password", 53 | Namespace = Constant.Namespace.OrgOpenOasisDocsWss200401Oasis200401WssWssecuritySecext10)] 54 | public UsernameTokenPasswordText Password { get; set; } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Models/SoapEnvelope.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity00/SimpleSOAPClient/e41d82d00a6a4338c5943ed125fac5d0dfa2d6dd/src/SimpleSOAPClient/Models/SoapEnvelope.cs -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Models/SoapEnvelopeBody.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Models 25 | { 26 | using System.Xml.Linq; 27 | using System.Xml.Serialization; 28 | 29 | /// 30 | /// Represents the SOAP Envelope Body section 31 | /// 32 | public class SoapEnvelopeBody 33 | { 34 | /// 35 | /// The body content 36 | /// 37 | [XmlAnyElement] 38 | public XElement Value { get; set; } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Models/SoapEnvelopeHeader.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Models 25 | { 26 | using System.Xml.Linq; 27 | using System.Xml.Serialization; 28 | 29 | /// 30 | /// Represents the SOAP Envelope Header section 31 | /// 32 | public class SoapEnvelopeHeader 33 | { 34 | /// 35 | /// The collection of headers 36 | /// 37 | [XmlAnyElement] 38 | public XElement[] Headers { get; set; } 39 | 40 | /// 41 | /// Initializes a new instance of 42 | /// 43 | public SoapEnvelopeHeader() 44 | { 45 | Headers = new XElement[0]; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Models/SoapFault.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity00/SimpleSOAPClient/e41d82d00a6a4338c5943ed125fac5d0dfa2d6dd/src/SimpleSOAPClient/Models/SoapFault.cs -------------------------------------------------------------------------------- /src/SimpleSOAPClient/Models/SoapHeader.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient.Models 25 | { 26 | using System; 27 | using System.Xml.Serialization; 28 | 29 | /// 30 | /// Base classe for SOAP Headers 31 | /// 32 | public abstract class SoapHeader 33 | { 34 | private int _mustUnderstand; 35 | 36 | /// 37 | /// Does the header must be understand? 38 | /// 39 | [XmlAttribute("mustUnderstand", Namespace = Constant.Namespace.OrgXmlSoapSchemasSoapEnvelope)] 40 | public int MustUnderstand 41 | { 42 | get { return _mustUnderstand; } 43 | set 44 | { 45 | if (value < 0 || value > 1) 46 | throw new ArgumentOutOfRangeException(nameof(value), "Must understand must be 0 or 1"); 47 | _mustUnderstand = value; 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/SimpleSOAPClient.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | SimpleSOAPClient 5 | SimpleSOAPClient 6 | SimpleSOAPClient 7 | Lightweight SOAP client for invoking HTTP SOAP endpoints. 8 | SimpleSOAPClient 9 | Net.JoaoSimoes 10 | Copyright © 2018 João Simões 11 | João Simões 12 | 13 | 14 | 15 | ../../tools/SimpleSOAPClient.snk 16 | true 17 | true 18 | true 19 | true 20 | true 21 | netstandard1.1;netstandard2.0;net4.5;uap10.0 22 | 23 | 24 | 25 | SimpleSOAPClient 26 | SOAP;HTTP 27 | https://raw.githubusercontent.com/gravity00/SimpleSOAPClient/master/SimpleSOAPClient-Logo.png 28 | https://github.com/gravity00/SimpleSOAPClient 29 | https://github.com/gravity00/SimpleSOAPClient/blob/master/LICENSE 30 | git 31 | https://github.com/gravity00/SimpleSOAPClient 32 | true 33 | 34 | 35 | 36 | 2.0.0 37 | 2.1.0.18177 38 | 2.1.0 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/SoapClient.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient 25 | { 26 | using System; 27 | using System.Collections.Generic; 28 | using System.Linq; 29 | using System.Net.Http; 30 | using System.Text; 31 | using System.Threading; 32 | using System.Threading.Tasks; 33 | using Exceptions; 34 | using Handlers; 35 | using Models; 36 | 37 | /// 38 | /// The SOAP client that can be used to invoke SOAP Endpoints 39 | /// 40 | public class SoapClient : ISoapClient, IDisposable 41 | { 42 | private readonly bool _disposeHttpClient = true; 43 | private readonly List _handlers = new List(); 44 | private SoapClientSettings _settings; 45 | private bool _disposed; 46 | 47 | /// 48 | /// The used HTTP client 49 | /// 50 | public HttpClient HttpClient { get; private set; } 51 | 52 | #region Constructors 53 | 54 | /// 55 | /// Creates a new SOAP Client 56 | /// 57 | /// The settings to be used 58 | /// 59 | public SoapClient(SoapClientSettings settings) 60 | { 61 | if (settings == null) throw new ArgumentNullException(nameof(settings)); 62 | 63 | _settings = settings; 64 | HttpClient = _settings.HttpClientFactory.Get(); 65 | } 66 | 67 | /// 68 | /// Creates a new SOAP Client 69 | /// 70 | /// The settings to be used 71 | /// The handler to be used by the 72 | /// 73 | public SoapClient(SoapClientSettings settings, HttpMessageHandler handler) 74 | { 75 | if (settings == null) throw new ArgumentNullException(nameof(settings)); 76 | if (handler == null) throw new ArgumentNullException(nameof(handler)); 77 | 78 | _settings = settings; 79 | HttpClient = _settings.HttpClientFactory.Get(handler); 80 | } 81 | 82 | /// 83 | /// Creates a new SOAP Client 84 | /// 85 | /// The settings to be used 86 | /// The to be used 87 | /// Should the client also be disposed 88 | /// 89 | public SoapClient(SoapClientSettings settings, HttpClient httpClient, bool disposeHttpClient = true) 90 | { 91 | if (settings == null) throw new ArgumentNullException(nameof(settings)); 92 | if (httpClient == null) throw new ArgumentNullException(nameof(httpClient)); 93 | 94 | _settings = settings; 95 | HttpClient = httpClient; 96 | _disposeHttpClient = disposeHttpClient; 97 | } 98 | 99 | /// 100 | /// Creates a new SOAP Client 101 | /// 102 | public SoapClient() 103 | : this(SoapClientSettings.Default) 104 | { 105 | 106 | } 107 | 108 | /// 109 | /// Creates a new SOAP Client 110 | /// 111 | /// The handler to be used by the 112 | public SoapClient(HttpMessageHandler handler) 113 | : this(SoapClientSettings.Default, handler) 114 | { 115 | 116 | } 117 | 118 | /// 119 | /// Creates a new SOAP Client 120 | /// 121 | /// The to be used 122 | /// Should the client also be disposed 123 | public SoapClient(HttpClient httpClient, bool disposeHttpClient = true) 124 | : this(SoapClientSettings.Default, httpClient, disposeHttpClient) 125 | { 126 | 127 | } 128 | 129 | /// Allows an object to try to free resources and perform other cleanup operations before it is reclaimed by garbage collection. 130 | ~SoapClient() 131 | { 132 | Dispose(false); 133 | } 134 | 135 | #endregion 136 | 137 | #region Implementation of ISoapClient 138 | 139 | /// 140 | /// The handler 141 | /// 142 | public IReadOnlyCollection Handlers => _handlers; 143 | 144 | /// 145 | /// The client settings 146 | /// 147 | public SoapClientSettings Settings 148 | { 149 | get { return _settings; } 150 | set 151 | { 152 | if(value == null) throw new ArgumentNullException(nameof(value)); 153 | _settings = value; 154 | } 155 | } 156 | 157 | #region Send 158 | 159 | /// 160 | /// Sends the given into the specified url. 161 | /// 162 | /// The url that will receive the request 163 | /// The SOAP action beeing performed 164 | /// The to be sent 165 | /// The cancellation token 166 | /// A task to be awaited for the result 167 | /// 168 | /// 169 | public virtual async Task SendAsync( 170 | string url, string action, SoapEnvelope requestEnvelope, CancellationToken ct = default(CancellationToken)) 171 | { 172 | if (_disposed) 173 | throw new ObjectDisposedException(nameof(SoapClient)); 174 | 175 | var trackingId = Guid.NewGuid(); 176 | var handlersOrderedAsc = _handlers.OrderBy(e => e.Order).ToList(); 177 | 178 | var beforeSoapEnvelopeSerializationHandlersResult = 179 | await RunBeforeSoapEnvelopeSerializationHandlers( 180 | requestEnvelope, url, action, trackingId, handlersOrderedAsc, ct); 181 | 182 | string requestXml; 183 | try 184 | { 185 | requestXml = 186 | Settings.SerializationProvider.ToXmlString(beforeSoapEnvelopeSerializationHandlersResult.Envelope); 187 | } 188 | catch (SoapEnvelopeSerializationException) 189 | { 190 | throw; 191 | } 192 | catch (Exception e) 193 | { 194 | throw new SoapEnvelopeSerializationException(requestEnvelope, e); 195 | } 196 | 197 | var beforeHttpRequestHandlersResult = 198 | await RunBeforeHttpRequestHandlers( 199 | requestXml, url, action, trackingId, 200 | beforeSoapEnvelopeSerializationHandlersResult.State, handlersOrderedAsc, ct); 201 | 202 | var response = 203 | await HttpClient.SendAsync(beforeHttpRequestHandlersResult.Request, ct).ConfigureAwait(false); 204 | 205 | var handlersOrderedDesc = _handlers.OrderByDescending(e => e.Order).ToList(); 206 | 207 | var afterHttpResponseHandlersResult = 208 | await RunAfterHttpResponseHandlers( 209 | response, url, action, trackingId, beforeHttpRequestHandlersResult.State, handlersOrderedDesc, ct); 210 | 211 | var responseXml = 212 | await afterHttpResponseHandlersResult.Response.Content.ReadAsStringAsync().ConfigureAwait(false); 213 | 214 | if (string.IsNullOrWhiteSpace(responseXml)) 215 | throw new SoapEnvelopeDeserializationException(responseXml, "The response content is empty."); 216 | SoapEnvelope responseEnvelope; 217 | try 218 | { 219 | responseEnvelope = 220 | Settings.SerializationProvider.ToSoapEnvelope(responseXml); 221 | } 222 | catch (SoapEnvelopeDeserializationException) 223 | { 224 | throw; 225 | } 226 | catch (Exception e) 227 | { 228 | throw new SoapEnvelopeDeserializationException(responseXml, e); 229 | } 230 | 231 | var afterSoapEnvelopeDeserializationHandlerResult = 232 | await RunAfterSoapEnvelopeDeserializationHandler( 233 | responseEnvelope, url, action, trackingId, 234 | afterHttpResponseHandlersResult.State, handlersOrderedDesc, ct); 235 | 236 | return afterSoapEnvelopeDeserializationHandlerResult.Envelope; 237 | } 238 | 239 | #endregion 240 | 241 | /// 242 | /// Adds the to the collection. 243 | /// 244 | /// The handler to add 245 | /// 246 | public void AddHandler(ISoapHandler handler) 247 | { 248 | if (handler == null) throw new ArgumentNullException(nameof(handler)); 249 | 250 | _handlers.Add(handler); 251 | } 252 | 253 | #endregion 254 | 255 | #region Implementation of IDisposable 256 | 257 | /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. 258 | public void Dispose() 259 | { 260 | Dispose(true); 261 | GC.SuppressFinalize(this); 262 | } 263 | 264 | /// 265 | /// Disposes the underline 266 | /// 267 | /// 268 | protected virtual void Dispose(bool disposing) 269 | { 270 | if (_disposed) 271 | return; 272 | 273 | if (disposing && _disposeHttpClient) 274 | HttpClient.Dispose(); 275 | 276 | HttpClient = null; 277 | _handlers.Clear(); 278 | 279 | _disposed = true; 280 | } 281 | 282 | #endregion 283 | 284 | #region Prepare 285 | 286 | /// 287 | /// Prepares a new instance to be configured. 288 | /// 289 | /// The SOAP client to be configured 290 | public static SoapClient Prepare() 291 | { 292 | return new SoapClient(); 293 | } 294 | 295 | /// 296 | /// Prepares a new instance to be configured. 297 | /// 298 | /// The handler to be used by the 299 | /// The SOAP client to be configured 300 | public static SoapClient Prepare(HttpMessageHandler handler) 301 | { 302 | return new SoapClient(handler); 303 | } 304 | 305 | /// 306 | /// Prepares a new instance to be configured. 307 | /// 308 | /// The to be used 309 | /// Should the client also be disposed 310 | /// The SOAP client to be configured 311 | public static SoapClient Prepare(HttpClient httpClient, bool disposeHttpClient = true) 312 | { 313 | return new SoapClient(httpClient, disposeHttpClient); 314 | } 315 | 316 | #endregion 317 | 318 | #region Private 319 | 320 | private async Task RunBeforeSoapEnvelopeSerializationHandlers( 321 | SoapEnvelope envelope, string url, string action, Guid trackingId, IEnumerable handlers, CancellationToken ct) 322 | { 323 | var beforeSoapEnvelopeSerializationArg = 324 | new OnSoapEnvelopeRequestArguments(envelope, url, action, trackingId); 325 | foreach (var handler in handlers) 326 | await handler.OnSoapEnvelopeRequestAsync(this, beforeSoapEnvelopeSerializationArg, ct); 327 | 328 | return beforeSoapEnvelopeSerializationArg; 329 | } 330 | 331 | private async Task RunBeforeHttpRequestHandlers( 332 | string xml, string url, string action, Guid trackingId, object state, IEnumerable handlers, CancellationToken ct) 333 | { 334 | var beforeHttpRequestArguments = 335 | new OnHttpRequestArguments(new HttpRequestMessage(HttpMethod.Post, url) 336 | { 337 | Content = new StringContent(xml, Encoding.UTF8, "text/xml"), 338 | Headers = 339 | { 340 | {"SOAPAction", action} 341 | } 342 | }, url, action, trackingId) 343 | { 344 | State = state 345 | }; 346 | foreach (var handler in handlers) 347 | await handler.OnHttpRequestAsync(this, beforeHttpRequestArguments, ct); 348 | 349 | return beforeHttpRequestArguments; 350 | } 351 | 352 | private async Task RunAfterHttpResponseHandlers( 353 | HttpResponseMessage response, string url, string action, Guid trackingId, object state, IEnumerable handlers, CancellationToken ct) 354 | { 355 | var afterHttpResponseArguments = 356 | new OnHttpResponseArguments(response, url, action, trackingId) 357 | { 358 | State = state 359 | }; 360 | foreach (var handler in handlers) 361 | await handler.OnHttpResponseAsync(this, afterHttpResponseArguments, ct); 362 | 363 | return afterHttpResponseArguments; 364 | } 365 | 366 | private async Task RunAfterSoapEnvelopeDeserializationHandler( 367 | SoapEnvelope envelope, string url, string action, Guid trackingId, object state, IEnumerable handlers, CancellationToken ct) 368 | { 369 | var afterSoapEnvelopeDeserializationArguments = 370 | new OnSoapEnvelopeResponseArguments(envelope, url, action, trackingId) 371 | { 372 | State = state 373 | }; 374 | foreach (var handler in handlers) 375 | await handler.OnSoapEnvelopeResponseAsync(this, afterSoapEnvelopeDeserializationArguments, ct); 376 | 377 | return afterSoapEnvelopeDeserializationArguments; 378 | } 379 | 380 | #endregion 381 | } 382 | } 383 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/SoapClientSettings.cs: -------------------------------------------------------------------------------- 1 | #region License 2 | // The MIT License (MIT) 3 | // 4 | // Copyright (c) 2016 João Simões 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | // 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | #endregion 24 | namespace SimpleSOAPClient 25 | { 26 | using System; 27 | 28 | /// 29 | /// Represents settings to be used by SOAP clients 30 | /// 31 | public sealed class SoapClientSettings 32 | { 33 | #region Statics 34 | 35 | private static SoapClientSettings _default; 36 | 37 | /// 38 | /// The default to be used. 39 | /// 40 | public static SoapClientSettings Default 41 | { 42 | get { return _default; } 43 | set 44 | { 45 | if (value == null) throw new ArgumentNullException(nameof(value)); 46 | _default = value; 47 | } 48 | } 49 | 50 | static SoapClientSettings() 51 | { 52 | _default = new SoapClientSettings(); 53 | } 54 | 55 | #endregion 56 | 57 | private ISoapEnvelopeSerializationProvider _serializationProvider; 58 | private IHttpClientFactory _httpClientFactory; 59 | 60 | /// 61 | /// The SOAP Envelope serialization provider 62 | /// 63 | public ISoapEnvelopeSerializationProvider SerializationProvider 64 | { 65 | get { return _serializationProvider; } 66 | set 67 | { 68 | if (value == null) throw new ArgumentNullException(nameof(value)); 69 | _serializationProvider = value; 70 | } 71 | } 72 | 73 | /// 74 | /// The HTTP client factory 75 | /// 76 | public IHttpClientFactory HttpClientFactory 77 | { 78 | get { return _httpClientFactory; } 79 | set 80 | { 81 | if (value == null) throw new ArgumentNullException(nameof(value)); 82 | _httpClientFactory = value; 83 | } 84 | } 85 | 86 | /// 87 | /// Creates a new instance with default values 88 | /// 89 | public SoapClientSettings() 90 | { 91 | _serializationProvider = new SoapEnvelopeSerializationProvider(); 92 | _httpClientFactory = new HttpClientFactory(); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/SimpleSOAPClient/SoapEnvelopeSerializationProvider.cs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity00/SimpleSOAPClient/e41d82d00a6a4338c5943ed125fac5d0dfa2d6dd/src/SimpleSOAPClient/SoapEnvelopeSerializationProvider.cs -------------------------------------------------------------------------------- /tests/SimpleSOAPClient.Tests/DataContractModel.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.Serialization; 2 | 3 | namespace SimpleSOAPClient.Tests 4 | { 5 | [DataContract(Name = "DataContractModel", Namespace ="urn:simplesoapclient:test")] 6 | public class DataContractModel 7 | { 8 | [DataMember(Order = 0)] 9 | public string String { get; set; } 10 | 11 | [DataMember(Order = 1)] 12 | public int Int { get; set; } 13 | 14 | [DataMember(Order = 2)] 15 | public bool Bool { get; set; } 16 | 17 | [DataMember(Order = 3)] 18 | public string[] Array { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/SimpleSOAPClient.Tests/SimpleSOAPClient.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ../../tools/SimpleSOAPClient.snk 5 | true 6 | true 7 | 8 | netcoreapp2.0 9 | 10 | false 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /tests/SimpleSOAPClient.Tests/XmlHelpersTests.cs: -------------------------------------------------------------------------------- 1 | using SimpleSOAPClient.Helpers; 2 | using System.Collections.Generic; 3 | using System.Xml.Linq; 4 | using Xunit; 5 | 6 | namespace SimpleSOAPClient.Tests 7 | { 8 | public class XmlHelpersTests 9 | { 10 | const string SERIALIZED_XML = @"foo42trueOneTwoThree"; 11 | const string SERIALIZED_DATACONTRACT = @"foo42trueOneTwoThree"; 12 | 13 | readonly XmlModel _xmlModel = new XmlModel 14 | { 15 | String = "foo", 16 | Bool = true, 17 | Int = 42, 18 | Array = new[] { "One", "Two", "Three" } 19 | }; 20 | 21 | readonly DataContractModel _dataContractModel = new DataContractModel 22 | { 23 | String = "foo", 24 | Bool = true, 25 | Int = 42, 26 | Array = new[] { "One", "Two", "Three" } 27 | }; 28 | 29 | [Fact] 30 | public void ToObject_XmlSerializer() 31 | { 32 | var result = XmlHelpers.ToObject(SERIALIZED_XML); 33 | Assert.Equal("foo", result.String); 34 | Assert.True(result.Bool); 35 | Assert.Equal(42, result.Int); 36 | Assert.Equal(3, result.Array.Length); 37 | } 38 | 39 | [Fact] 40 | public void ToObject_DataContractSerializer() 41 | { 42 | var result = XmlHelpers.ToObject(SERIALIZED_DATACONTRACT); 43 | Assert.Equal("foo", result.String); 44 | Assert.True(result.Bool); 45 | Assert.Equal(42, result.Int); 46 | Assert.Equal(3, result.Array.Length); 47 | } 48 | 49 | 50 | [Fact] 51 | public void ToXElement_XmlSerializer() 52 | { 53 | var result = XmlHelpers.ToXElement(_xmlModel); 54 | var actualXml = result.ToString(); 55 | Assert.Equal(SERIALIZED_XML, actualXml, new XmlEqualityComparer()); 56 | } 57 | 58 | [Fact] 59 | public void ToXElement_DataContractSerializer() 60 | { 61 | var result = XmlHelpers.ToXElement(_dataContractModel); 62 | var actualXml = result.ToString(); 63 | Assert.Equal(SERIALIZED_DATACONTRACT, actualXml, new XmlEqualityComparer()); 64 | } 65 | 66 | [Fact] 67 | public void ToXmlString_XmlSerializer() 68 | { 69 | var result = XmlHelpers.ToXmlString(_xmlModel); 70 | Assert.Equal(SERIALIZED_XML, result, new XmlEqualityComparer()); 71 | } 72 | 73 | [Fact] 74 | public void ToXmlString_DataContractSerializer() 75 | { 76 | var result = XmlHelpers.ToXmlString(_dataContractModel); 77 | Assert.Equal(SERIALIZED_DATACONTRACT, result, new XmlEqualityComparer()); 78 | } 79 | 80 | class XmlEqualityComparer : IEqualityComparer 81 | { 82 | public bool Equals(string x, string y) => XmlNormalizer.DeepEqualsWithNormalization(XDocument.Parse(x), XDocument.Parse(y), null); 83 | 84 | public int GetHashCode(string obj) => XmlNormalizer.Normalize(XDocument.Parse(obj), null).GetHashCode(); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /tests/SimpleSOAPClient.Tests/XmlModel.cs: -------------------------------------------------------------------------------- 1 | using System.Xml.Serialization; 2 | 3 | namespace SimpleSOAPClient.Tests 4 | { 5 | [XmlRoot(Namespace = "urn:simplesoapclient:test")] 6 | public class XmlModel 7 | { 8 | [XmlElement(Order = 0)] 9 | public string String { get; set; } 10 | 11 | [XmlElement(Order = 1)] 12 | public int Int { get; set; } 13 | 14 | [XmlElement(Order = 2)] 15 | public bool Bool { get; set; } 16 | 17 | [XmlArray(Order = 3)] 18 | public string[] Array { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/SimpleSOAPClient.Tests/XmlNormalizer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Xml; 6 | using System.Xml.Linq; 7 | using System.Xml.Schema; 8 | 9 | namespace SimpleSOAPClient.Tests 10 | { 11 | // From https://blogs.msdn.microsoft.com/xmlteam/2009/02/16/equality-semantics-of-linq-to-xml-trees/ 12 | public class XmlNormalizer 13 | { 14 | private static class Xsi 15 | { 16 | public static XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance"; 17 | 18 | public static XName schemaLocation = xsi + "schemaLocation"; 19 | public static XName noNamespaceSchemaLocation = xsi + "noNamespaceSchemaLocation"; 20 | } 21 | 22 | public static XDocument Normalize(XDocument source, XmlSchemaSet schema) 23 | { 24 | bool havePSVI = false; 25 | // validate, throw errors, add PSVI information 26 | if (schema != null) 27 | { 28 | source.Validate(schema, null, true); 29 | havePSVI = true; 30 | } 31 | return new XDocument( 32 | source.Declaration, 33 | source.Nodes().Select(n => 34 | { 35 | // Remove comments, processing instructions, and text nodes that are 36 | // children of XDocument. Only white space text nodes are allowed as 37 | // children of a document, so we can remove all text nodes. 38 | if (n is XComment || n is XProcessingInstruction || n is XText) 39 | return null; 40 | XElement e = n as XElement; 41 | if (e != null) 42 | return NormalizeElement(e, havePSVI); 43 | return n; 44 | } 45 | ) 46 | ); 47 | } 48 | 49 | public static bool DeepEqualsWithNormalization(XDocument doc1, XDocument doc2, 50 | XmlSchemaSet schemaSet) 51 | { 52 | XDocument d1 = Normalize(doc1, schemaSet); 53 | XDocument d2 = Normalize(doc2, schemaSet); 54 | return XNode.DeepEquals(d1, d2); 55 | } 56 | 57 | private static IEnumerable NormalizeAttributes(XElement element, 58 | bool havePSVI) 59 | { 60 | return element.Attributes() 61 | .Where(a => !a.IsNamespaceDeclaration && 62 | a.Name != Xsi.schemaLocation && 63 | a.Name != Xsi.noNamespaceSchemaLocation) 64 | .OrderBy(a => a.Name.NamespaceName) 65 | .ThenBy(a => a.Name.LocalName) 66 | .Select( 67 | a => 68 | { 69 | if (havePSVI) 70 | { 71 | var dt = a.GetSchemaInfo().SchemaType.TypeCode; 72 | switch (dt) 73 | { 74 | case XmlTypeCode.Boolean: 75 | return new XAttribute(a.Name, (bool)a); 76 | case XmlTypeCode.DateTime: 77 | return new XAttribute(a.Name, (DateTime)a); 78 | case XmlTypeCode.Decimal: 79 | return new XAttribute(a.Name, (decimal)a); 80 | case XmlTypeCode.Double: 81 | return new XAttribute(a.Name, (double)a); 82 | case XmlTypeCode.Float: 83 | return new XAttribute(a.Name, (float)a); 84 | case XmlTypeCode.HexBinary: 85 | case XmlTypeCode.Language: 86 | return new XAttribute(a.Name, 87 | ((string)a).ToLower()); 88 | } 89 | } 90 | return a; 91 | } 92 | ); 93 | } 94 | 95 | private static XNode NormalizeNode(XNode node, bool havePSVI) 96 | { 97 | // trim comments and processing instructions from normalized tree 98 | if (node is XComment || node is XProcessingInstruction) 99 | return null; 100 | XElement e = node as XElement; 101 | if (e != null) 102 | return NormalizeElement(e, havePSVI); 103 | // Only thing left is XCData and XText, so clone them 104 | return node; 105 | } 106 | 107 | private static XElement NormalizeElement(XElement element, bool havePSVI) 108 | { 109 | if (havePSVI) 110 | { 111 | var dt = element.GetSchemaInfo(); 112 | switch (dt.SchemaType.TypeCode) 113 | { 114 | case XmlTypeCode.Boolean: 115 | return new XElement(element.Name, 116 | NormalizeAttributes(element, havePSVI), 117 | (bool)element); 118 | case XmlTypeCode.DateTime: 119 | return new XElement(element.Name, 120 | NormalizeAttributes(element, havePSVI), 121 | (DateTime)element); 122 | case XmlTypeCode.Decimal: 123 | return new XElement(element.Name, 124 | NormalizeAttributes(element, havePSVI), 125 | (decimal)element); 126 | case XmlTypeCode.Double: 127 | return new XElement(element.Name, 128 | NormalizeAttributes(element, havePSVI), 129 | (double)element); 130 | case XmlTypeCode.Float: 131 | return new XElement(element.Name, 132 | NormalizeAttributes(element, havePSVI), 133 | (float)element); 134 | case XmlTypeCode.HexBinary: 135 | case XmlTypeCode.Language: 136 | return new XElement(element.Name, 137 | NormalizeAttributes(element, havePSVI), 138 | ((string)element).ToLower()); 139 | default: 140 | return new XElement(element.Name, 141 | NormalizeAttributes(element, havePSVI), 142 | element.Nodes().Select(n => NormalizeNode(n, havePSVI)), 143 | (!element.IsEmpty && !element.Nodes().OfType().Any()) ? 144 | "" : null 145 | ); 146 | } 147 | } 148 | else 149 | { 150 | return new XElement(element.Name, 151 | NormalizeAttributes(element, havePSVI), 152 | element.Nodes().Select(n => NormalizeNode(n, havePSVI)), 153 | (!element.IsEmpty && !element.Nodes().OfType().Any()) ? 154 | "" : null 155 | ); 156 | } 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /tools/SimpleSOAPClient.PublicKey: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity00/SimpleSOAPClient/e41d82d00a6a4338c5943ed125fac5d0dfa2d6dd/tools/SimpleSOAPClient.PublicKey -------------------------------------------------------------------------------- /tools/SimpleSOAPClient.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gravity00/SimpleSOAPClient/e41d82d00a6a4338c5943ed125fac5d0dfa2d6dd/tools/SimpleSOAPClient.snk --------------------------------------------------------------------------------