mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-02-01 16:13:43 +01:00
Compare commits
55 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f73bd5fc4f | ||
|
|
702e156ddc | ||
|
|
317fcb1b30 | ||
|
|
4b602dd777 | ||
|
|
4525c61847 | ||
|
|
abe996671e | ||
|
|
9f819de696 | ||
|
|
f5d53453e5 | ||
|
|
0e60e3f3f9 | ||
|
|
9cee6dde00 | ||
|
|
c88e7378a7 | ||
|
|
b090296559 | ||
|
|
e5afd69f7c | ||
|
|
f38133d7a4 | ||
|
|
597c95000e | ||
|
|
4617b99c30 | ||
|
|
ffd4d89946 | ||
|
|
2d46c86f47 | ||
|
|
75f4fbe9d0 | ||
|
|
16e3872402 | ||
|
|
4c797c328f | ||
|
|
a5e75a7278 | ||
|
|
56f65c19e2 | ||
|
|
6aef4816a5 | ||
|
|
197a211a52 | ||
|
|
3cfeec6035 | ||
|
|
b57d5e7548 | ||
|
|
36b89afce5 | ||
|
|
e2acac55a4 | ||
|
|
ceabd27ce0 | ||
|
|
f8e2c7ee90 | ||
|
|
c25d8f33d2 | ||
|
|
6da190e596 | ||
|
|
44388ce80d | ||
|
|
5e25ca767d | ||
|
|
0cc583a4a3 | ||
|
|
f9633adac1 | ||
|
|
37bad618a3 | ||
|
|
8e69f36f04 | ||
|
|
21601889e0 | ||
|
|
dfeabf228e | ||
|
|
1feb0ade70 | ||
|
|
8b1bd1b21b | ||
|
|
c1b23b615e | ||
|
|
5885324dfb | ||
|
|
e3f3e0a8f2 | ||
|
|
685d28db0b | ||
|
|
f6c5225fe0 | ||
|
|
b9019a2f61 | ||
|
|
b82dad2563 | ||
|
|
45d4e7077d | ||
|
|
19e95325fa | ||
|
|
371bfdc160 | ||
|
|
5c5e104f2c | ||
|
|
068fdf33e3 |
36
.github/workflows/copilot-setup-steps.yml
vendored
Normal file
36
.github/workflows/copilot-setup-steps.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: "Copilot Setup Steps"
|
||||
|
||||
# Automatically run the setup steps when they are changed to allow for easy validation, and
|
||||
# allow manual testing through the repository's "Actions" tab
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
paths:
|
||||
- .github/workflows/copilot-setup-steps.yml
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/copilot-setup-steps.yml
|
||||
|
||||
jobs:
|
||||
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
|
||||
copilot-setup-steps:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Set the permissions to the lowest permissions possible needed for your steps.
|
||||
# Copilot will be given its own token for its operations.
|
||||
permissions:
|
||||
# If you want to clone the repository as part of your setup steps, for example to install dependencies, you'll need the `contents: read` permission. If you don't clone the repository in your setup steps, Copilot will do this for you automatically after the steps complete.
|
||||
contents: read
|
||||
|
||||
# You can define any steps you want, and they will run before the agent starts.
|
||||
# If you do not check out your code, Copilot will do this for you.
|
||||
steps:
|
||||
- name: Install .NET 10.x
|
||||
uses: actions/setup-dotnet@v5
|
||||
with:
|
||||
dotnet-version: |
|
||||
10.x
|
||||
dotnet-quality: preview
|
||||
|
||||
- name: dotnet --info
|
||||
run: dotnet --info
|
||||
74
CHANGELOG.md
74
CHANGELOG.md
@@ -1,3 +1,77 @@
|
||||
# 1.25.0 (25 January 2026)
|
||||
- [#1389](https://github.com/wiremock/WireMock.Net/pull/1389) - Fix MimePartMatcher and add more tests [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1371](https://github.com/wiremock/WireMock.Net/issues/1371) - MimePartMatcher does not match multipart/form-data request body (possible bug?) [bug]
|
||||
|
||||
# 1.24.0 (18 January 2026)
|
||||
- [#1417](https://github.com/wiremock/WireMock.Net/pull/1417) - Update aspire to 13.1 (examples + code) [feature] contributed by [petrroll](https://github.com/petrroll)
|
||||
- [#1418](https://github.com/wiremock/WireMock.Net/pull/1418) - Add OTEL tracing support for Wiremock + automatic OTEL for Aspire integration [feature] contributed by [petrroll](https://github.com/petrroll)
|
||||
- [#1214](https://github.com/wiremock/WireMock.Net/issues/1214) - OpenTelemetry Support for .NET Aspire [feature]
|
||||
|
||||
# 1.23.0 (05 January 2026)
|
||||
- [#1414](https://github.com/wiremock/WireMock.Net/pull/1414) - Pass the parameter matchOperator in Request.WithPath to its inner calls [bug] contributed by [gbamqzkdyg](https://github.com/gbamqzkdyg)
|
||||
- [#1416](https://github.com/wiremock/WireMock.Net/pull/1416) - Fix: Pass AllowedHandlebarsHelpers configuration to Handlebars.Net.Helpers library contributed by [samlatham](https://github.com/samlatham)
|
||||
- [#1413](https://github.com/wiremock/WireMock.Net/issues/1413) - Parameter `matchOperator` is not respected in the method Request.WithPath [bug]
|
||||
- [#1415](https://github.com/wiremock/WireMock.Net/issues/1415) - HandlebarsSettings AllowedHandlebarsHelpers Configuration Not Applied [bug]
|
||||
|
||||
# 1.22.0 (02 January 2026)
|
||||
- [#1412](https://github.com/wiremock/WireMock.Net/pull/1412) - chore(testcontainers): bump up Testcontainers to version 4.10.0 [feature] contributed by [vhatsura](https://github.com/vhatsura)
|
||||
- [#1411](https://github.com/wiremock/WireMock.Net/issues/1411) - WireMock.Net.Testcontainers isn't compatible with Testcontainers 4.10.0 [bug]
|
||||
|
||||
# 1.21.0 (25 December 2025)
|
||||
- [#1408](https://github.com/wiremock/WireMock.Net/pull/1408) - Fix readyness-check for Testcontainers [bug] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.20.0 (24 December 2025)
|
||||
- [#1399](https://github.com/wiremock/WireMock.Net/pull/1399) - Upgrade RamlToOpenApiConverter and YamlDotNet [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1400](https://github.com/wiremock/WireMock.Net/pull/1400) - Add WireMock.Net.NUnit project [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1405](https://github.com/wiremock/WireMock.Net/pull/1405) - Fix Testcontainers AddProtoDefinition [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1398](https://github.com/wiremock/WireMock.Net/issues/1398) - Upgrade YamlDotNet dependency [feature]
|
||||
- [#1404](https://github.com/wiremock/WireMock.Net/issues/1404) - An exception occurs when adding multiple proto definitions in the TestContainer. [bug]
|
||||
|
||||
# 1.19.0 (12 December 2025)
|
||||
- [#1391](https://github.com/wiremock/WireMock.Net/pull/1391) - Update WireMockContainerBuilder (WithImage and WithCustomImage) [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1392](https://github.com/wiremock/WireMock.Net/pull/1392) - WireMockContainerBuilder: allow all docker images named wiremock [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1390](https://github.com/wiremock/WireMock.Net/issues/1390) - Unable to build WireMockContainerBuilder with custom image [feature]
|
||||
|
||||
# 1.18.0 (09 December 2025)
|
||||
- [#1388](https://github.com/wiremock/WireMock.Net/pull/1388) - Add WithBodyAsType to RequestMatcher [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.17.0 (07 December 2025)
|
||||
- [#1383](https://github.com/wiremock/WireMock.Net/pull/1383) - Aspire: Add WithProtoDefinition to support proto definition at server level [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1386](https://github.com/wiremock/WireMock.Net/pull/1386) - Fix random delay in mapping json file [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1274](https://github.com/wiremock/WireMock.Net/issues/1274) - .WithMappings to mount volume is not working for GRPC [bug]
|
||||
- [#1381](https://github.com/wiremock/WireMock.Net/issues/1381) - Downstream dependencies missing after 1.16.0 release [bug]
|
||||
- [#1382](https://github.com/wiremock/WireMock.Net/issues/1382) - Does Aspire support enabling HTTP/2? [feature]
|
||||
- [#1385](https://github.com/wiremock/WireMock.Net/issues/1385) - Do delays and probabilities show in saved static mappings? [bug]
|
||||
- [#1387](https://github.com/wiremock/WireMock.Net/issues/1387) - Tests failing with TaskCanceledException on Windows Server 2025 Build 7171 [bug]
|
||||
|
||||
# 1.16.0 (18 November 2025)
|
||||
- [#1366](https://github.com/wiremock/WireMock.Net/pull/1366) - WireMock.Net.OpenApiParser : support Examples [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1375](https://github.com/wiremock/WireMock.Net/pull/1375) - Add WireMockHealthCheck in WireMock.Net.Aspire [feature] contributed by [Zguy](https://github.com/Zguy)
|
||||
- [#1377](https://github.com/wiremock/WireMock.Net/pull/1377) - Check if the path is valid when using WithPath(...) [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1380](https://github.com/wiremock/WireMock.Net/pull/1380) - Add WireMock.Net.xUnit.v3 project [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1364](https://github.com/wiremock/WireMock.Net/issues/1364) - Choosing examples from open api specification for responses. [feature]
|
||||
- [#1376](https://github.com/wiremock/WireMock.Net/issues/1376) - AdminApiMappingBuilder `WithPath` should add the starting `/` if missing [feature]
|
||||
- [#1379](https://github.com/wiremock/WireMock.Net/issues/1379) - xUnit v3 [feature]
|
||||
|
||||
# 1.15.0 (22 October 2025)
|
||||
- [#1367](https://github.com/wiremock/WireMock.Net/pull/1367) - Fix WithProbability logic [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1370](https://github.com/wiremock/WireMock.Net/pull/1370) - Support Testcontainers 4.8.0 [bug] contributed by [MD-V](https://github.com/MD-V)
|
||||
- [#1126](https://github.com/wiremock/WireMock.Net/issues/1126) - Request matching WithProbability strange behaviour [bug]
|
||||
|
||||
# 1.14.0 (06 October 2025)
|
||||
- [#1362](https://github.com/wiremock/WireMock.Net/pull/1362) - Update ProxyUrlReplaceSettingsModel with TransformTemplate property [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1363](https://github.com/wiremock/WireMock.Net/pull/1363) - Add Tls13 [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1342](https://github.com/wiremock/WireMock.Net/issues/1342) - Facing SSL certificate validation error when using .NET 5 and above framework for some http services during recording [bug]
|
||||
- [#1360](https://github.com/wiremock/WireMock.Net/issues/1360) - ProxyURL path configuration [feature]
|
||||
|
||||
# 1.13.0 (28 September 2025)
|
||||
- [#1358](https://github.com/wiremock/WireMock.Net/pull/1358) - TypeLoader: implement Try methods [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1361](https://github.com/wiremock/WireMock.Net/pull/1361) - ProxyUrlTransformer [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.12.0 (30 August 2025)
|
||||
- [#1357](https://github.com/wiremock/WireMock.Net/pull/1357) - Upgrade Testcontainers to 4.7.0 [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1356](https://github.com/wiremock/WireMock.Net/issues/1356) - WireMock.Net 1.11.2 is not compatible with TestContainers 4.7.0 [bug]
|
||||
|
||||
# 1.11.2 (27 August 2025)
|
||||
- [#1352](https://github.com/wiremock/WireMock.Net/pull/1352) - Add additional try-catch to TypeLoader logic [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1354](https://github.com/wiremock/WireMock.Net/pull/1354) - Add System.Net.Http again to solve CVE warning [bug] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>1.11.2</Version>
|
||||
<VersionPrefix>1.25.0</VersionPrefix>
|
||||
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
||||
<PackageProjectUrl>https://github.com/wiremock/WireMock.Net</PackageProjectUrl>
|
||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
rem https://github.com/StefH/GitHubReleaseNotes
|
||||
|
||||
SET version=1.11.2
|
||||
SET version=1.25.0
|
||||
|
||||
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels wontfix test question invalid doc duplicate example environment --version %version% --token %GH_TOKEN%
|
||||
|
||||
|
||||
@@ -15,48 +15,48 @@ Lightweight Http Mocking Server for .NET, inspired by WireMock.org (from the Jav
|
||||
|
||||
### :star: Stubbing
|
||||
A core feature of WireMock.Net is the ability to return predefined HTTP responses for requests matching criteria.
|
||||
See [Wiki : Stubbing](https://github.com/wiremock/WireMock.Net/wiki/Stubbing).
|
||||
See [Stubbing](https://wiremock.org/dotnet/stubbing).
|
||||
|
||||
### :star: Request Matching
|
||||
WireMock.Net support advanced request-matching logic, see [Wiki : Request Matching](https://github.com/wiremock/WireMock.Net/wiki/Request-Matching).
|
||||
WireMock.Net support advanced request-matching logic, see [Request Matching](https://wiremock.org/dotnet/request-matching).
|
||||
|
||||
### :star: Response Templating
|
||||
The response which is returned WireMock.Net can be changed using templating. This is described here [Wiki : Response Templating](https://github.com/wiremock/WireMock.Net/wiki/Response-Templating).
|
||||
The response which is returned WireMock.Net can be changed using templating. This is described here [Response Templating](https://wiremock.org/dotnet/response-templating).
|
||||
|
||||
### :star: Admin API Reference
|
||||
The WireMock admin API provides functionality to define the mappings via a http interface see [Wiki : Admin API Reference](https://github.com/StefH/WireMock.Net/wiki/Admin-API-Reference).
|
||||
The WireMock admin API provides functionality to define the mappings via a http interface see [Admin API Reference](https://wiremock.org/dotnet/admin-api-reference).
|
||||
|
||||
### :star: Using
|
||||
WireMock.Net can be used in several ways:
|
||||
|
||||
#### UnitTesting
|
||||
You can use your favorite test framework and use WireMock within your tests, see
|
||||
[Wiki : UnitTesting](https://github.com/StefH/WireMock.Net/wiki/Using-WireMock-in-UnitTests).
|
||||
[UnitTesting](https://wiremock.org/dotnet/using-wiremock-in-unittests).
|
||||
|
||||
### Unit/Integration Testing using Testcontainers.DotNet
|
||||
See [Wiki : WireMock.Net.Testcontainers](https://github.com/wiremock/WireMock.Net/wiki/Using-WireMock.Net.Testcontainers) on how to build a WireMock.Net Docker container which can be used in Unit/Integration testing.
|
||||
See [WireMock.Net.Testcontainers](https://wiremock.org/dotnet/using-wiremock-net-testcontainers/) on how to build a WireMock.Net Docker container which can be used in Unit/Integration testing.
|
||||
|
||||
### Unit/Integration Testing using an an Aspire Distributed Application
|
||||
See [Wiki : WireMock.Net.Aspire](https://github.com/wiremock/WireMock.Net/wiki/Using-WireMock.Net.Aspire) on how to use WireMock.Net as an Aspire Hosted application to do Unit/Integration testing.
|
||||
See [WireMock.Net.Aspire](https://wiremock.org/dotnet/using-wiremock-net-Aspire) on how to use WireMock.Net as an Aspire Hosted application to do Unit/Integration testing.
|
||||
|
||||
#### As a dotnet tool
|
||||
It's simple to install WireMock.Net as (global) dotnet tool, see [Wiki : dotnet tool](https://github.com/StefH/WireMock.Net/wiki/WireMock-as-dotnet-tool).
|
||||
It's simple to install WireMock.Net as (global) dotnet tool, see [dotnet tool](https://wiremock.org/dotnet/wiremock-as-dotnet-tool).
|
||||
|
||||
#### As standalone process / console application
|
||||
This is quite straight forward to launch a mock server within a console application, see [Wiki : Standalone Process](https://github.com/StefH/WireMock.Net/wiki/WireMock-as-a-standalone-process).
|
||||
This is quite straight forward to launch a mock server within a console application, see [Standalone Process](https://wiremock.org/dotnet/wiremock-as-a-standalone-process).
|
||||
|
||||
#### As a Windows Service
|
||||
You can also run WireMock.Net as a Windows Service, follow this [WireMock-as-a-Windows-Service](https://github.com/wiremock/WireMock.Net/wiki/WireMock-as-a-Windows-Service).
|
||||
You can also run WireMock.Net as a Windows Service, follow this [Windows Service](https://wiremock.org/dotnet/wiremock-as-a-windows-service).
|
||||
|
||||
#### As a Web Job in Azure or application in IIS
|
||||
See this link [WireMock-as-a-(Azure)-Web-App](https://github.com/wiremock/WireMock.Net/wiki/WireMock-as-a-(Azure)-Web-App)
|
||||
See this link [WireMock-as-a-(Azure)-Web-App](https://wiremock.org/dotnet/wiremock-as-a-azure-web-app/)
|
||||
|
||||
#### In a docker container
|
||||
There is also a Linux and Windows-Nano container available at [hub.docker.com](https://hub.docker.com/r/sheyenrath).
|
||||
For more details see also [Docker](https://github.com/wiremock/WireMock.Net-docker).
|
||||
|
||||
#### HTTPS / SSL
|
||||
More details on using HTTPS (SSL) can be found here [Wiki : HTTPS](https://github.com/wiremock/WireMock.Net/wiki/Using-HTTPS-(SSL))
|
||||
More details on using HTTPS (SSL) can be found here [HTTPS](https://wiremock.org/dotnet/using-https-ssl/)
|
||||
|
||||
## :books: Documentation
|
||||
For more info, see also this WIKI page: [What is WireMock.Net](https://github.com/wiremock/WireMock.Net/wiki/What-Is-WireMock.Net).
|
||||
For more info, see also this documentation page: [What is WireMock.Net](https://wiremock.org/dotnet/what-is-wiremock-net/).
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
# 1.11.2 (27 August 2025)
|
||||
- #1352 Add additional try-catch to TypeLoader logic [feature]
|
||||
- #1354 Add System.Net.Http again to solve CVE warning [bug]
|
||||
- #1355 Revert JetBrains.Annotations and add System.Text.RegularExpressions t… [bug]
|
||||
- #1071 Split WireMock into multiple nuget packages depending on features [feature]
|
||||
- #1351 Version 1.11.0 seems to have a dependency to non-existing version of JetBrans.Annotations [bug]
|
||||
- #1353 1.11.0: NU1903: Warning As Error: Package 'System.Net.Http' 4.3.0 has a known high severity vulnerability, https://github.com/advisories/GHSA-7jgj-8wvc-jh57 [bug]
|
||||
# 1.25.0 (25 January 2026)
|
||||
- #1389 Fix MimePartMatcher and add more tests [bug]
|
||||
- #1371 MimePartMatcher does not match multipart/form-data request body (possible bug?) [bug]
|
||||
|
||||
The full release notes can be found here: https://github.com/wiremock/WireMock.Net/blob/master/CHANGELOG.md
|
||||
48
README.md
48
README.md
@@ -1,7 +1,11 @@
|
||||
#  WireMock.Net
|
||||
A C# .NET version based on [mock4net](https://github.com/alexvictoor/mock4net) which mimics the functionality from the JAVA based [WireMock](http://wiremock.org).
|
||||
A C# .NET version based on [mock4net](https://github.com/alexvictoor/mock4net) which mimics functionality from the original Java based WireMock.
|
||||
|
||||
For more info, see also this WIKI page: [What is WireMock.Net](https://github.com/wiremock/WireMock.Net/wiki/What-Is-WireMock.Net).
|
||||
---
|
||||
|
||||
### :books: Full documentation can now be found at [wiremock.org](https://wiremock.org/dotnet)
|
||||
|
||||
---
|
||||
|
||||
## :star: Key Features
|
||||
* HTTP response stubbing, matchable on URL/Path, headers, cookies and body content patterns
|
||||
@@ -29,7 +33,7 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
|
||||
| **Issues** | [](https://github.com/wiremock/WireMock.Net/issues) |
|
||||
| | |
|
||||
| ***Quality*** | |
|
||||
| **Build Azure** | [](https://stef.visualstudio.com/WireMock.Net/_build/latest?definitionId=7) |
|
||||
| **Build Azure** | [](https://stef.visualstudio.com/WireMock.Net/_build/latest?definitionId=61) |
|
||||
| **Quality** | [](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net) [](https://www.codefactor.io/repository/github/wiremock/wiremock.net) |
|
||||
| **Sonar Bugs** | [](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net&resolved=false&types=BUG) [](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net&resolved=false&types=CODE_SMELL) |
|
||||
| **Coverage** | [](https://sonarcloud.io/component_measures?id=WireMock-Net_WireMock.Net&metric=coverage) [](https://codecov.io/gh/wiremock/WireMock.Net)|
|
||||
@@ -37,7 +41,7 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
|
||||
|
||||
### :package: NuGet packages
|
||||
|
||||
| | Official | Preview [:information_source:](https://github.com/wiremock/WireMock.Net/wiki/MyGet-preview-versions) |
|
||||
| | Official | Preview [:information_source:](https://wiremock.org/dotnet/MyGet-preview-versions) |
|
||||
| - | - | - |
|
||||
| **WireMock.Net** | [](https://www.nuget.org/packages/WireMock.Net) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net)
|
||||
| **WireMock.Net.Minimal** 🔺| [](https://www.nuget.org/packages/WireMock.Net.Minimal) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Minimal)
|
||||
@@ -49,7 +53,9 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
|
||||
| **WireMock.Net.AwesomeAssertions** | [](https://www.nuget.org/packages/WireMock.Net.AwesomeAssertions) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.AwesomeAssertions)
|
||||
| **WireMock.Net.FluentAssertions** | [](https://www.nuget.org/packages/WireMock.Net.FluentAssertions) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.FluentAssertions)
|
||||
| **WireMock.Net.xUnit** | [](https://www.nuget.org/packages/WireMock.Net.xUnit) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.xUnit)
|
||||
| **WireMock.Net.xUnit.v3** | [](https://www.nuget.org/packages/WireMock.Net.xUnit.v3) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.xUnit.v3)
|
||||
| **WireMock.Net.TUnit** | [](https://www.nuget.org/packages/WireMock.Net.TUnit) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.TUnit)
|
||||
| **WireMock.Net.NUnit** | [](https://www.nuget.org/packages/WireMock.Net.NUnit) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.NUnit)
|
||||
| | | |
|
||||
| **WireMock.Net.Extensions.Routing** | [](https://www.nuget.org/packages/WireMock.Net.Extensions.Routing) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Extensions.Routing)
|
||||
| **WireMock.Net.Matchers.CSharpCode** | [](https://www.nuget.org/packages/WireMock.Net.Matchers.CSharpCode) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Matchers.CSharpCode)
|
||||
@@ -57,13 +63,14 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
|
||||
| **WireMock.Net.MimePart** | [](https://www.nuget.org/packages/WireMock.Net.MimePart) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.MimePart)
|
||||
| **WireMock.Net.GraphQL** | [](https://www.nuget.org/packages/WireMock.Net.GraphQL) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.GraphQL)
|
||||
| **WireMock.Net.ProtoBuf** | [](https://www.nuget.org/packages/WireMock.Net.ProtoBuf) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.ProtoBuf)
|
||||
| **WireMock.Net.OpenTelemetry** | [](https://www.nuget.org/packages/WireMock.Net.ProtoBuf) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.OpenTelemetry)
|
||||
| | | |
|
||||
| **WireMock.Net.RestClient** | [](https://www.nuget.org/packages/WireMock.Net.RestClient) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.RestClient)
|
||||
| **WireMock.Org.RestClient** | [](https://www.nuget.org/packages/WireMock.Org.RestClient) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Org.RestClient)
|
||||
|
||||
<br />
|
||||
|
||||
🔺 **WireMock.Net.Minimal** does not include *WireMock.Net.MimePart*, *WireMock.Net.GraphQL* and *WireMock.Net.ProtoBuf*.
|
||||
🔺 **WireMock.Net.Minimal** does not include *WireMock.Net.MimePart*, *WireMock.Net.GraphQL*, *WireMock.Net.ProtoBuf* and *WireMock.Net.OpenTelemetry*.
|
||||
|
||||
---
|
||||
|
||||
@@ -89,52 +96,55 @@ To still enable this feature, you need to add the `Environment` category to the
|
||||
---
|
||||
|
||||
## :memo: Development
|
||||
For the supported frameworks and build information, see [this](https://github.com/wiremock/WireMock.Net/wiki/Development-Information) page.
|
||||
For the supported frameworks and build information, see [this](https://wiremock.org/dotnet/development-information) page.
|
||||
|
||||
## :star: Stubbing
|
||||
A core feature of WireMock.Net is the ability to return predefined HTTP responses for requests matching criteria.
|
||||
See [Wiki : Stubbing](https://github.com/wiremock/WireMock.Net/wiki/Stubbing).
|
||||
See [Stubbing](https://wiremock.org/dotnet/stubbing).
|
||||
|
||||
## :star: Request Matching
|
||||
WireMock.Net support advanced request-matching logic, see [Wiki : Request Matching](https://github.com/wiremock/WireMock.Net/wiki/Request-Matching).
|
||||
WireMock.Net support advanced request-matching logic, see [Request Matching](https://wiremock.org/dotnet/request-matching).
|
||||
|
||||
## :star: Response Templating
|
||||
The response which is returned WireMock.Net can be changed using templating. This is described here [Wiki : Response Templating](https://github.com/wiremock/WireMock.Net/wiki/Response-Templating).
|
||||
The response which is returned WireMock.Net can be changed using templating. This is described here [Response Templating](https://wiremock.org/dotnet/response-templating).
|
||||
|
||||
## :star: Admin API Reference
|
||||
The WireMock admin API provides functionality to define the mappings via a http interface see [Wiki : Admin API Reference](https://github.com/StefH/WireMock.Net/wiki/Admin-API-Reference).
|
||||
The WireMock admin API provides functionality to define the mappings via a http interface see [Admin API Reference](https://wiremock.org/dotnet/admin-api-reference).
|
||||
|
||||
## :star: Using
|
||||
WireMock.Net can be used in several ways:
|
||||
|
||||
### UnitTesting
|
||||
You can use your favorite test framework and use WireMock within your tests, see
|
||||
[Wiki : UnitTesting](https://github.com/StefH/WireMock.Net/wiki/Using-WireMock-in-UnitTests).
|
||||
[UnitTesting](https://wiremock.org/dotnet/using-wiremock-in-unittests).
|
||||
|
||||
### Unit/Integration Testing using Testcontainers.DotNet
|
||||
See [Wiki : WireMock.Net.Testcontainers](https://github.com/wiremock/WireMock.Net/wiki/Using-WireMock.Net.Testcontainers) on how to build a WireMock.Net Docker container which can be used in Unit/Integration testing.
|
||||
See [WireMock.Net.Testcontainers](https://wiremock.org/dotnet/using-wiremock-net-testcontainers/) on how to build a WireMock.Net Docker container which can be used in Unit/Integration testing.
|
||||
|
||||
### Unit/Integration Testing using an an Aspire Distributed Application
|
||||
See [Wiki : WireMock.Net.Aspire](https://github.com/wiremock/WireMock.Net/wiki/Using-WireMock.Net.Aspire) on how to use WireMock.Net as an Aspire Hosted application to do Unit/Integration testing.
|
||||
See [WireMock.Net.Aspire](https://wiremock.org/dotnet/using-wiremock-net-Aspire) on how to use WireMock.Net as an Aspire Hosted application to do Unit/Integration testing.
|
||||
|
||||
### As a dotnet tool
|
||||
It's simple to install WireMock.Net as (global) dotnet tool, see [Wiki : dotnet tool](https://github.com/StefH/WireMock.Net/wiki/WireMock-as-dotnet-tool).
|
||||
It's simple to install WireMock.Net as (global) dotnet tool, see [dotnet tool](https://wiremock.org/dotnet/wiremock-as-dotnet-tool).
|
||||
|
||||
### As standalone process / console application
|
||||
This is quite straight forward to launch a mock server within a console application, see [Wiki : Standalone Process](https://github.com/StefH/WireMock.Net/wiki/WireMock-as-a-standalone-process).
|
||||
This is quite straight forward to launch a mock server within a console application, see [Standalone Process](https://wiremock.org/dotnet/wiremock-as-a-standalone-process).
|
||||
|
||||
### As a Windows Service
|
||||
You can also run WireMock.Net as a Windows Service, follow this [WireMock-as-a-Windows-Service](https://github.com/wiremock/WireMock.Net/wiki/WireMock-as-a-Windows-Service).
|
||||
You can also run WireMock.Net as a Windows Service, follow this [Windows Service](https://wiremock.org/dotnet/wiremock-as-a-windows-service).
|
||||
|
||||
### As a Web Job in Azure or application in IIS
|
||||
See this link [WireMock-as-a-(Azure)-Web-App](https://github.com/wiremock/WireMock.Net/wiki/WireMock-as-a-(Azure)-Web-App)
|
||||
See this link [WireMock-as-a-(Azure)-Web-App](https://wiremock.org/dotnet/wiremock-as-a-azure-web-app/)
|
||||
|
||||
### In a docker container
|
||||
There is also a Linux and Windows-Nano container available at [hub.docker.com](https://hub.docker.com/r/sheyenrath).
|
||||
For more details see also [Docker](https://github.com/wiremock/WireMock.Net-docker).
|
||||
|
||||
#### HTTPS / SSL
|
||||
More details on using HTTPS (SSL) can be found here [Wiki : HTTPS](https://github.com/wiremock/WireMock.Net/wiki/Using-HTTPS-(SSL))
|
||||
### HTTPS / SSL
|
||||
More details on using HTTPS (SSL) can be found here [HTTPS](https://wiremock.org/dotnet/using-https-ssl/)
|
||||
|
||||
## :books: Documentation
|
||||
For more info, see also this documentation page: [What is WireMock.Net](https://wiremock.org/dotnet/what-is-wiremock-net/).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.0.31521.260
|
||||
# Visual Studio Version 18
|
||||
VisualStudioVersion = 18.0.11205.157
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{8F890C6F-9ACC-438D-928A-AD61CDA862F2}"
|
||||
EndProject
|
||||
@@ -144,212 +144,686 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Extensions.Rou
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.ProtoBuf", "src\WireMock.Net.ProtoBuf\WireMock.Net.ProtoBuf.csproj", "{B47413AA-55D3-49A7-896A-17ADBFF72407}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.xUnit.v3", "src\WireMock.Net.xUnit.v3\WireMock.Net.xUnit.v3.csproj", "{4F46BD02-BEBC-4B2D-B857-4169AD1FB067}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.NUnit", "src\WireMock.Net.NUnit\WireMock.Net.NUnit.csproj", "{2DBBD70D-8051-441F-92BB-FF9B8B4B4982}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.OpenTelemetry", "src\WireMock.Net.OpenTelemetry\WireMock.Net.OpenTelemetry.csproj", "{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.OpenTelemetryDemo", "examples\WireMock.Net.OpenTelemetryDemo\WireMock.Net.OpenTelemetryDemo.csproj", "{9957038D-F9C3-CA5D-E8AE-BE188E512635}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.MimePart", "examples\WireMock.Net.Console.MimePart\WireMock.Net.Console.MimePart.csproj", "{4005E20C-D42B-138A-79BE-B3F5420C563F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{D3804228-91F4-4502-9595-39584E5A01AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A01AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A01AD}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A01AD}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A01AD}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A01AD}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A01AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A01AD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A01AD}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A01AD}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A01AD}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A01AD}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A94}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-43D6-8B9A-579DED3D9A96}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-43D5-8B9A-579DED3D9A95}.Release|x86.Build.0 = Release|Any CPU
|
||||
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Release|x64.Build.0 = Release|Any CPU
|
||||
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Release|x86.Build.0 = Release|Any CPU
|
||||
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Release|x86.Build.0 = Release|Any CPU
|
||||
{5C09FB93-1535-4F92-AF26-21E8A061EE4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5C09FB93-1535-4F92-AF26-21E8A061EE4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5C09FB93-1535-4F92-AF26-21E8A061EE4A}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{5C09FB93-1535-4F92-AF26-21E8A061EE4A}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{5C09FB93-1535-4F92-AF26-21E8A061EE4A}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{5C09FB93-1535-4F92-AF26-21E8A061EE4A}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{5C09FB93-1535-4F92-AF26-21E8A061EE4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5C09FB93-1535-4F92-AF26-21E8A061EE4A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5C09FB93-1535-4F92-AF26-21E8A061EE4A}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{5C09FB93-1535-4F92-AF26-21E8A061EE4A}.Release|x64.Build.0 = Release|Any CPU
|
||||
{5C09FB93-1535-4F92-AF26-21E8A061EE4A}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{5C09FB93-1535-4F92-AF26-21E8A061EE4A}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95}.Release|x86.Build.0 = Release|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Release|x64.Build.0 = Release|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A44}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A44}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A44}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A44}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A44}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A44}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A44}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A44}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A44}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A44}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A44}.Release|x86.Build.0 = Release|Any CPU
|
||||
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Release|x86.Build.0 = Release|Any CPU
|
||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|x86.Build.0 = Release|Any CPU
|
||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Release|x64.Build.0 = Release|Any CPU
|
||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Release|x86.Build.0 = Release|Any CPU
|
||||
{670C7562-C154-442E-A249-7D26849BCD13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{670C7562-C154-442E-A249-7D26849BCD13}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{670C7562-C154-442E-A249-7D26849BCD13}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{670C7562-C154-442E-A249-7D26849BCD13}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{670C7562-C154-442E-A249-7D26849BCD13}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{670C7562-C154-442E-A249-7D26849BCD13}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{670C7562-C154-442E-A249-7D26849BCD13}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{670C7562-C154-442E-A249-7D26849BCD13}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{670C7562-C154-442E-A249-7D26849BCD13}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{670C7562-C154-442E-A249-7D26849BCD13}.Release|x64.Build.0 = Release|Any CPU
|
||||
{670C7562-C154-442E-A249-7D26849BCD13}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{670C7562-C154-442E-A249-7D26849BCD13}.Release|x86.Build.0 = Release|Any CPU
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|x64.Build.0 = Release|Any CPU
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|x86.Build.0 = Release|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|x86.Build.0 = Release|Any CPU
|
||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}.Release|x86.Build.0 = Release|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Release|x64.Build.0 = Release|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Release|x86.Build.0 = Release|Any CPU
|
||||
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}.Release|x64.Build.0 = Release|Any CPU
|
||||
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}.Release|x86.Build.0 = Release|Any CPU
|
||||
{7FC0B409-2682-40EE-B3B9-3930D6769D01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7FC0B409-2682-40EE-B3B9-3930D6769D01}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7FC0B409-2682-40EE-B3B9-3930D6769D01}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7FC0B409-2682-40EE-B3B9-3930D6769D01}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7FC0B409-2682-40EE-B3B9-3930D6769D01}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{7FC0B409-2682-40EE-B3B9-3930D6769D01}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{7FC0B409-2682-40EE-B3B9-3930D6769D01}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7FC0B409-2682-40EE-B3B9-3930D6769D01}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7FC0B409-2682-40EE-B3B9-3930D6769D01}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7FC0B409-2682-40EE-B3B9-3930D6769D01}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7FC0B409-2682-40EE-B3B9-3930D6769D01}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7FC0B409-2682-40EE-B3B9-3930D6769D01}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B1580A38-84E7-44BE-8FE7-3EE5031D74A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B1580A38-84E7-44BE-8FE7-3EE5031D74A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B1580A38-84E7-44BE-8FE7-3EE5031D74A1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B1580A38-84E7-44BE-8FE7-3EE5031D74A1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B1580A38-84E7-44BE-8FE7-3EE5031D74A1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B1580A38-84E7-44BE-8FE7-3EE5031D74A1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B1580A38-84E7-44BE-8FE7-3EE5031D74A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B1580A38-84E7-44BE-8FE7-3EE5031D74A1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B1580A38-84E7-44BE-8FE7-3EE5031D74A1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B1580A38-84E7-44BE-8FE7-3EE5031D74A1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B1580A38-84E7-44BE-8FE7-3EE5031D74A1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B1580A38-84E7-44BE-8FE7-3EE5031D74A1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{CAB42D88-B4E4-4887-B684-9F3E09D085A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CAB42D88-B4E4-4887-B684-9F3E09D085A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CAB42D88-B4E4-4887-B684-9F3E09D085A1}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{CAB42D88-B4E4-4887-B684-9F3E09D085A1}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{CAB42D88-B4E4-4887-B684-9F3E09D085A1}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{CAB42D88-B4E4-4887-B684-9F3E09D085A1}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{CAB42D88-B4E4-4887-B684-9F3E09D085A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CAB42D88-B4E4-4887-B684-9F3E09D085A1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CAB42D88-B4E4-4887-B684-9F3E09D085A1}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CAB42D88-B4E4-4887-B684-9F3E09D085A1}.Release|x64.Build.0 = Release|Any CPU
|
||||
{CAB42D88-B4E4-4887-B684-9F3E09D085A1}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{CAB42D88-B4E4-4887-B684-9F3E09D085A1}.Release|x86.Build.0 = Release|Any CPU
|
||||
{42113E6B-DC43-4E80-9967-1E4233568E87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{42113E6B-DC43-4E80-9967-1E4233568E87}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{42113E6B-DC43-4E80-9967-1E4233568E87}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{42113E6B-DC43-4E80-9967-1E4233568E87}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{42113E6B-DC43-4E80-9967-1E4233568E87}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{42113E6B-DC43-4E80-9967-1E4233568E87}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{42113E6B-DC43-4E80-9967-1E4233568E87}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{42113E6B-DC43-4E80-9967-1E4233568E87}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{42113E6B-DC43-4E80-9967-1E4233568E87}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{42113E6B-DC43-4E80-9967-1E4233568E87}.Release|x64.Build.0 = Release|Any CPU
|
||||
{42113E6B-DC43-4E80-9967-1E4233568E87}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{42113E6B-DC43-4E80-9967-1E4233568E87}.Release|x86.Build.0 = Release|Any CPU
|
||||
{84624E1F-DF07-4315-89B0-51776BE99E13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{84624E1F-DF07-4315-89B0-51776BE99E13}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{84624E1F-DF07-4315-89B0-51776BE99E13}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{84624E1F-DF07-4315-89B0-51776BE99E13}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{84624E1F-DF07-4315-89B0-51776BE99E13}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{84624E1F-DF07-4315-89B0-51776BE99E13}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{84624E1F-DF07-4315-89B0-51776BE99E13}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{84624E1F-DF07-4315-89B0-51776BE99E13}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{84624E1F-DF07-4315-89B0-51776BE99E13}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{84624E1F-DF07-4315-89B0-51776BE99E13}.Release|x64.Build.0 = Release|Any CPU
|
||||
{84624E1F-DF07-4315-89B0-51776BE99E13}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{84624E1F-DF07-4315-89B0-51776BE99E13}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A34F1575-7C33-4548-8CEF-8D8D8B84153C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A34F1575-7C33-4548-8CEF-8D8D8B84153C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A34F1575-7C33-4548-8CEF-8D8D8B84153C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A34F1575-7C33-4548-8CEF-8D8D8B84153C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A34F1575-7C33-4548-8CEF-8D8D8B84153C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A34F1575-7C33-4548-8CEF-8D8D8B84153C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A34F1575-7C33-4548-8CEF-8D8D8B84153C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A34F1575-7C33-4548-8CEF-8D8D8B84153C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A34F1575-7C33-4548-8CEF-8D8D8B84153C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A34F1575-7C33-4548-8CEF-8D8D8B84153C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A34F1575-7C33-4548-8CEF-8D8D8B84153C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A34F1575-7C33-4548-8CEF-8D8D8B84153C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{7373B7DC-47ED-45A5-969D-D7DDBA529B53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7373B7DC-47ED-45A5-969D-D7DDBA529B53}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7373B7DC-47ED-45A5-969D-D7DDBA529B53}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7373B7DC-47ED-45A5-969D-D7DDBA529B53}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7373B7DC-47ED-45A5-969D-D7DDBA529B53}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{7373B7DC-47ED-45A5-969D-D7DDBA529B53}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{7373B7DC-47ED-45A5-969D-D7DDBA529B53}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7373B7DC-47ED-45A5-969D-D7DDBA529B53}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7373B7DC-47ED-45A5-969D-D7DDBA529B53}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7373B7DC-47ED-45A5-969D-D7DDBA529B53}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7373B7DC-47ED-45A5-969D-D7DDBA529B53}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7373B7DC-47ED-45A5-969D-D7DDBA529B53}.Release|x86.Build.0 = Release|Any CPU
|
||||
{CE602F57-FEF8-4559-A9E0-6200BE1BF398}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{CE602F57-FEF8-4559-A9E0-6200BE1BF398}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{CE602F57-FEF8-4559-A9E0-6200BE1BF398}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{CE602F57-FEF8-4559-A9E0-6200BE1BF398}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{CE602F57-FEF8-4559-A9E0-6200BE1BF398}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{CE602F57-FEF8-4559-A9E0-6200BE1BF398}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{CE602F57-FEF8-4559-A9E0-6200BE1BF398}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{CE602F57-FEF8-4559-A9E0-6200BE1BF398}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{CE602F57-FEF8-4559-A9E0-6200BE1BF398}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{CE602F57-FEF8-4559-A9E0-6200BE1BF398}.Release|x64.Build.0 = Release|Any CPU
|
||||
{CE602F57-FEF8-4559-A9E0-6200BE1BF398}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{CE602F57-FEF8-4559-A9E0-6200BE1BF398}.Release|x86.Build.0 = Release|Any CPU
|
||||
{F1B5999D-D22E-48A6-AB86-18A7876BD32E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F1B5999D-D22E-48A6-AB86-18A7876BD32E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F1B5999D-D22E-48A6-AB86-18A7876BD32E}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{F1B5999D-D22E-48A6-AB86-18A7876BD32E}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{F1B5999D-D22E-48A6-AB86-18A7876BD32E}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{F1B5999D-D22E-48A6-AB86-18A7876BD32E}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{F1B5999D-D22E-48A6-AB86-18A7876BD32E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F1B5999D-D22E-48A6-AB86-18A7876BD32E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F1B5999D-D22E-48A6-AB86-18A7876BD32E}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{F1B5999D-D22E-48A6-AB86-18A7876BD32E}.Release|x64.Build.0 = Release|Any CPU
|
||||
{F1B5999D-D22E-48A6-AB86-18A7876BD32E}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{F1B5999D-D22E-48A6-AB86-18A7876BD32E}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9}.Release|x86.Build.0 = Release|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|x86.Build.0 = Release|Any CPU
|
||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Release|x64.Build.0 = Release|Any CPU
|
||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Release|x86.Build.0 = Release|Any CPU
|
||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Release|x64.Build.0 = Release|Any CPU
|
||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Release|x86.Build.0 = Release|Any CPU
|
||||
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{7753670F-7C7F-44BF-8BC7-08325588E60C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{E5B03EEF-822C-4295-952B-4479AD30082B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E5B03EEF-822C-4295-952B-4479AD30082B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E5B03EEF-822C-4295-952B-4479AD30082B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{E5B03EEF-822C-4295-952B-4479AD30082B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{E5B03EEF-822C-4295-952B-4479AD30082B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{E5B03EEF-822C-4295-952B-4479AD30082B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{E5B03EEF-822C-4295-952B-4479AD30082B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E5B03EEF-822C-4295-952B-4479AD30082B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E5B03EEF-822C-4295-952B-4479AD30082B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{E5B03EEF-822C-4295-952B-4479AD30082B}.Release|x64.Build.0 = Release|Any CPU
|
||||
{E5B03EEF-822C-4295-952B-4479AD30082B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{E5B03EEF-822C-4295-952B-4479AD30082B}.Release|x86.Build.0 = Release|Any CPU
|
||||
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A0177}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A0177}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A0177}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A0177}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A0177}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A0177}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A0177}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A0177}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A0177}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A0177}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A0177}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D3804228-91F4-4502-9595-39584E5A0177}.Release|x86.Build.0 = Release|Any CPU
|
||||
{BFEF8990-65B3-4274-310F-7355F0B84035}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BFEF8990-65B3-4274-310F-7355F0B84035}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BFEF8990-65B3-4274-310F-7355F0B84035}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BFEF8990-65B3-4274-310F-7355F0B84035}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{BFEF8990-65B3-4274-310F-7355F0B84035}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{BFEF8990-65B3-4274-310F-7355F0B84035}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{BFEF8990-65B3-4274-310F-7355F0B84035}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BFEF8990-65B3-4274-310F-7355F0B84035}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BFEF8990-65B3-4274-310F-7355F0B84035}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BFEF8990-65B3-4274-310F-7355F0B84035}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BFEF8990-65B3-4274-310F-7355F0B84035}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{BFEF8990-65B3-4274-310F-7355F0B84035}.Release|x86.Build.0 = Release|Any CPU
|
||||
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Release|x86.Build.0 = Release|Any CPU
|
||||
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Release|x64.Build.0 = Release|Any CPU
|
||||
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-444DED3D9A45}.Release|x86.Build.0 = Release|Any CPU
|
||||
{3FCBCA9C-9DB0-4A96-B47E-30470764CC9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3FCBCA9C-9DB0-4A96-B47E-30470764CC9C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3FCBCA9C-9DB0-4A96-B47E-30470764CC9C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{3FCBCA9C-9DB0-4A96-B47E-30470764CC9C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{3FCBCA9C-9DB0-4A96-B47E-30470764CC9C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{3FCBCA9C-9DB0-4A96-B47E-30470764CC9C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{3FCBCA9C-9DB0-4A96-B47E-30470764CC9C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3FCBCA9C-9DB0-4A96-B47E-30470764CC9C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3FCBCA9C-9DB0-4A96-B47E-30470764CC9C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{3FCBCA9C-9DB0-4A96-B47E-30470764CC9C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{3FCBCA9C-9DB0-4A96-B47E-30470764CC9C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{3FCBCA9C-9DB0-4A96-B47E-30470764CC9C}.Release|x86.Build.0 = Release|Any CPU
|
||||
{1E874C8F-08A2-493B-8421-619F9A6E9E77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1E874C8F-08A2-493B-8421-619F9A6E9E77}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1E874C8F-08A2-493B-8421-619F9A6E9E77}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{1E874C8F-08A2-493B-8421-619F9A6E9E77}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{1E874C8F-08A2-493B-8421-619F9A6E9E77}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{1E874C8F-08A2-493B-8421-619F9A6E9E77}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{1E874C8F-08A2-493B-8421-619F9A6E9E77}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1E874C8F-08A2-493B-8421-619F9A6E9E77}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1E874C8F-08A2-493B-8421-619F9A6E9E77}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{1E874C8F-08A2-493B-8421-619F9A6E9E77}.Release|x64.Build.0 = Release|Any CPU
|
||||
{1E874C8F-08A2-493B-8421-619F9A6E9E77}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{1E874C8F-08A2-493B-8421-619F9A6E9E77}.Release|x86.Build.0 = Release|Any CPU
|
||||
{B47413AA-55D3-49A7-896A-17ADBFF72407}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B47413AA-55D3-49A7-896A-17ADBFF72407}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B47413AA-55D3-49A7-896A-17ADBFF72407}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{B47413AA-55D3-49A7-896A-17ADBFF72407}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{B47413AA-55D3-49A7-896A-17ADBFF72407}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{B47413AA-55D3-49A7-896A-17ADBFF72407}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{B47413AA-55D3-49A7-896A-17ADBFF72407}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B47413AA-55D3-49A7-896A-17ADBFF72407}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B47413AA-55D3-49A7-896A-17ADBFF72407}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{B47413AA-55D3-49A7-896A-17ADBFF72407}.Release|x64.Build.0 = Release|Any CPU
|
||||
{B47413AA-55D3-49A7-896A-17ADBFF72407}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{B47413AA-55D3-49A7-896A-17ADBFF72407}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4F46BD02-BEBC-4B2D-B857-4169AD1FB067}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4F46BD02-BEBC-4B2D-B857-4169AD1FB067}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4F46BD02-BEBC-4B2D-B857-4169AD1FB067}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4F46BD02-BEBC-4B2D-B857-4169AD1FB067}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4F46BD02-BEBC-4B2D-B857-4169AD1FB067}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4F46BD02-BEBC-4B2D-B857-4169AD1FB067}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4F46BD02-BEBC-4B2D-B857-4169AD1FB067}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4F46BD02-BEBC-4B2D-B857-4169AD1FB067}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4F46BD02-BEBC-4B2D-B857-4169AD1FB067}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4F46BD02-BEBC-4B2D-B857-4169AD1FB067}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4F46BD02-BEBC-4B2D-B857-4169AD1FB067}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4F46BD02-BEBC-4B2D-B857-4169AD1FB067}.Release|x86.Build.0 = Release|Any CPU
|
||||
{2DBBD70D-8051-441F-92BB-FF9B8B4B4982}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{2DBBD70D-8051-441F-92BB-FF9B8B4B4982}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{2DBBD70D-8051-441F-92BB-FF9B8B4B4982}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{2DBBD70D-8051-441F-92BB-FF9B8B4B4982}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{2DBBD70D-8051-441F-92BB-FF9B8B4B4982}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{2DBBD70D-8051-441F-92BB-FF9B8B4B4982}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{2DBBD70D-8051-441F-92BB-FF9B8B4B4982}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{2DBBD70D-8051-441F-92BB-FF9B8B4B4982}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{2DBBD70D-8051-441F-92BB-FF9B8B4B4982}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{2DBBD70D-8051-441F-92BB-FF9B8B4B4982}.Release|x64.Build.0 = Release|Any CPU
|
||||
{2DBBD70D-8051-441F-92BB-FF9B8B4B4982}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{2DBBD70D-8051-441F-92BB-FF9B8B4B4982}.Release|x86.Build.0 = Release|Any CPU
|
||||
{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F}.Release|x86.Build.0 = Release|Any CPU
|
||||
{9957038D-F9C3-CA5D-E8AE-BE188E512635}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9957038D-F9C3-CA5D-E8AE-BE188E512635}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9957038D-F9C3-CA5D-E8AE-BE188E512635}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{9957038D-F9C3-CA5D-E8AE-BE188E512635}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{9957038D-F9C3-CA5D-E8AE-BE188E512635}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{9957038D-F9C3-CA5D-E8AE-BE188E512635}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{9957038D-F9C3-CA5D-E8AE-BE188E512635}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9957038D-F9C3-CA5D-E8AE-BE188E512635}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9957038D-F9C3-CA5D-E8AE-BE188E512635}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9957038D-F9C3-CA5D-E8AE-BE188E512635}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9957038D-F9C3-CA5D-E8AE-BE188E512635}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9957038D-F9C3-CA5D-E8AE-BE188E512635}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -407,6 +881,11 @@ Global
|
||||
{3FCBCA9C-9DB0-4A96-B47E-30470764CC9C} = {0BB8B634-407A-4610-A91F-11586990767A}
|
||||
{1E874C8F-08A2-493B-8421-619F9A6E9E77} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||
{B47413AA-55D3-49A7-896A-17ADBFF72407} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||
{4F46BD02-BEBC-4B2D-B857-4169AD1FB067} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||
{2DBBD70D-8051-441F-92BB-FF9B8B4B4982} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||
{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||
{9957038D-F9C3-CA5D-E8AE-BE188E512635} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{4005E20C-D42B-138A-79BE-B3F5420C563F} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
|
||||
|
||||
@@ -100,7 +100,7 @@ jobs:
|
||||
- job: Windows_Build_Test
|
||||
|
||||
pool:
|
||||
vmImage: 'windows-2022'
|
||||
vmImage: 'windows-2025'
|
||||
|
||||
steps:
|
||||
- task: UseDotNet@2
|
||||
@@ -141,9 +141,13 @@ jobs:
|
||||
dependsOn: Windows_Build_Test
|
||||
|
||||
pool:
|
||||
vmImage: 'windows-2022'
|
||||
vmImage: 'windows-2025'
|
||||
|
||||
steps:
|
||||
- script: |
|
||||
echo "BuildId = $(buildId)"
|
||||
displayName: 'Print buildId'
|
||||
|
||||
- task: UseDotNet@2
|
||||
displayName: Use .NET 8.0
|
||||
inputs:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
pool:
|
||||
vmImage: 'windows-2022'
|
||||
vmImage: 'windows-2025'
|
||||
|
||||
variables:
|
||||
Prerelease: ''
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Sdk Name="Aspire.AppHost.Sdk" Version="9.2.0" />
|
||||
<Sdk Name="Aspire.AppHost.Sdk" Version="13.1.0" />
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -18,7 +18,16 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="9.2.0" />
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="13.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
<ItemGroup>
|
||||
<None Update="__admin\mappings\*.proto">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\*.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -4,14 +4,28 @@ var builder = DistributedApplication.CreateBuilder(args);
|
||||
|
||||
// IResourceBuilder<ProjectResource> apiService = builder.AddProject<Projects.AspireApp1_ApiService>("apiservice");
|
||||
|
||||
var mappingsPath = Path.Combine(Directory.GetCurrentDirectory(), "WireMockMappings");
|
||||
var mappingsPath = Path.Combine(Directory.GetCurrentDirectory(), "__admin", "mappings");
|
||||
|
||||
IResourceBuilder<WireMockServerResource> apiService = builder
|
||||
.AddWireMock("apiservice", WireMockServerArguments.DefaultPort)
|
||||
//IResourceBuilder<WireMockServerResource> apiService1 = builder
|
||||
// //.AddWireMock("apiservice", WireMockServerArguments.DefaultPort)
|
||||
// .AddWireMock("apiservice1", "http://*:8081", "grpc://*:9091")
|
||||
// .AsHttp2Service()
|
||||
// .WithMappingsPath(mappingsPath)
|
||||
// .WithReadStaticMappings()
|
||||
// .WithWatchStaticMappings()
|
||||
// .WithApiMappingBuilder(WeatherForecastApiMock.BuildAsync);
|
||||
|
||||
IResourceBuilder<WireMockServerResource> apiService2 = builder
|
||||
.AddWireMock("apiservice", async args =>
|
||||
{
|
||||
args.WithAdditionalUrls("http://*:8081", "grpc://*:9093");
|
||||
args.WithProtoDefinition("my-greeter", await File.ReadAllTextAsync(Path.Combine(mappingsPath, "greet.proto")));
|
||||
})
|
||||
.AsHttp2Service()
|
||||
.WithMappingsPath(mappingsPath)
|
||||
.WithReadStaticMappings()
|
||||
.WithWatchStaticMappings()
|
||||
.WithApiMappingBuilder(WeatherForecastApiMock.BuildAsync);
|
||||
.WithApiMappingBuilder(WeatherForecastApiMock.BuildAsync)
|
||||
.WithOpenTelemetry(); // Enable OpenTelemetry tracing for Aspire dashboard
|
||||
|
||||
//var apiServiceUsedForDocs = builder
|
||||
// .AddWireMock("apiservice1", WireMockServerArguments.DefaultPort)
|
||||
@@ -45,6 +59,7 @@ IResourceBuilder<WireMockServerResource> apiService = builder
|
||||
|
||||
builder.AddProject<Projects.AspireApp1_Web>("webfrontend")
|
||||
.WithExternalHttpEndpoints()
|
||||
.WithReference(apiService);
|
||||
.WithReference(apiService2)
|
||||
.WaitFor(apiService2);
|
||||
|
||||
builder.Build().Run();
|
||||
await builder.Build().RunAsync();
|
||||
@@ -0,0 +1,21 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package greet;
|
||||
|
||||
service Greeter {
|
||||
rpc SayHello (HelloRequest) returns (HelloReply);
|
||||
}
|
||||
|
||||
message HelloRequest {
|
||||
string name = 1;
|
||||
}
|
||||
|
||||
message HelloReply {
|
||||
string message = 1;
|
||||
enum PhoneType {
|
||||
none = 0;
|
||||
mobile = 1;
|
||||
home = 2;
|
||||
}
|
||||
PhoneType phoneType = 2;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"Guid": "351f0240-bba0-4bcb-93c6-1feba0fe0004",
|
||||
"Title": "ProtoBuf Mapping 4",
|
||||
"Request": {
|
||||
"Path": {
|
||||
"Matchers": [
|
||||
{
|
||||
"Name": "WildcardMatcher",
|
||||
"Pattern": "/greet.Greeter/SayHello",
|
||||
"IgnoreCase": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"Methods": [
|
||||
"POST"
|
||||
],
|
||||
"Body": {
|
||||
"Matcher": {
|
||||
"Name": "ProtoBufMatcher",
|
||||
"ProtoBufMessageType": "greet.HelloRequest"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Response": {
|
||||
"BodyAsJson": {
|
||||
"message": "hello {{request.BodyAsJson.name}} {{request.method}}"
|
||||
},
|
||||
"UseTransformer": true,
|
||||
"TransformerType": "Handlebars",
|
||||
"TransformerReplaceNodeOptions": "EvaluateAndTryToConvert",
|
||||
"Headers": {
|
||||
"Content-Type": "application/grpc"
|
||||
},
|
||||
"TrailingHeaders": {
|
||||
"grpc-status": "0"
|
||||
},
|
||||
"ProtoBufMessageType": "greet.HelloReply"
|
||||
},
|
||||
"ProtoDefinition": "my-greeter"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Sdk Name="Aspire.AppHost.Sdk" Version="9.2.0" />
|
||||
<Sdk Name="Aspire.AppHost.Sdk" Version="13.1.0" />
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -15,7 +15,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="9.2.0" />
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="13.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -6,4 +6,4 @@ builder.AddProject<Projects.AspireApp1_Web>("webfrontend")
|
||||
.WithExternalHttpEndpoints()
|
||||
.WithReference(apiService);
|
||||
|
||||
builder.Build().Run();
|
||||
await builder.Build().RunAsync();
|
||||
@@ -9,7 +9,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.Testing" Version="8.0.0" />
|
||||
<PackageReference Include="Aspire.Hosting.Testing" Version="13.1.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||
<PackageReference Include="xunit" Version="2.5.3" />
|
||||
|
||||
82
examples/WireMock.Net.Console.MimePart/MainApp.cs
Normal file
82
examples/WireMock.Net.Console.MimePart/MainApp.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.Net.Console.MimePart;
|
||||
|
||||
// Test this CURL:
|
||||
// curl -X POST http://localhost:9091/multipart -F "plainText=This is some plain text;type=text/plain" -F "jsonData={ `"Key`": `"Value`" };type=application/json" -F "image=@image.png;type=image/png"
|
||||
//
|
||||
// curl -X POST http://localhost:9091/multipart2 -F "plainText=This is some plain text;type=text/plain" -F "jsonData={ `"Key`": `"Value`" };type=application/json" -F "image=@image.png;type=image/png"
|
||||
|
||||
public static class MainApp
|
||||
{
|
||||
public static async Task RunAsync()
|
||||
{
|
||||
using var server = WireMockServer.Start(new WireMockServerSettings
|
||||
{
|
||||
Port = 9091,
|
||||
StartAdminInterface = true,
|
||||
|
||||
ReadStaticMappings = true,
|
||||
//WatchStaticMappings = true,
|
||||
//WatchStaticMappingsInSubdirectories = true,
|
||||
|
||||
Logger = new WireMockConsoleLogger()
|
||||
});
|
||||
System.Console.WriteLine("WireMockServer listening at {0}", string.Join(",", server.Urls));
|
||||
|
||||
var textPlainContentTypeMatcher = new ContentTypeMatcher("text/plain");
|
||||
var textPlainContentMatcher = new ExactMatcher("This is some plain text");
|
||||
var textPlainMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textPlainContentTypeMatcher, null, null, textPlainContentMatcher);
|
||||
|
||||
var textJsonContentTypeMatcher = new ContentTypeMatcher("application/json");
|
||||
var textJsonContentMatcher = new JsonMatcher(new { Key = "Value" }, true);
|
||||
var textJsonMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textJsonContentTypeMatcher, null, null, textJsonContentMatcher);
|
||||
|
||||
var imagePngContentTypeMatcher = new ContentTypeMatcher("image/png");
|
||||
var imagePngContentDispositionMatcher = new ExactMatcher("form-data; name=\"image\"; filename=\"image.png\"");
|
||||
var imagePngContentTransferEncodingMatcher = new ExactMatcher("default");
|
||||
var imagePngContentMatcher = new ExactObjectMatcher(Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAgMAAAAP2OW3AAAADFBMVEX/tID/vpH/pWX/sHidUyjlAAAADElEQVR4XmMQYNgAAADkAMHebX3mAAAAAElFTkSuQmCC"));
|
||||
var imagePngMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, imagePngContentTypeMatcher, imagePngContentDispositionMatcher, imagePngContentTransferEncodingMatcher, imagePngContentMatcher);
|
||||
|
||||
var matchers = new IMatcher[]
|
||||
{
|
||||
textPlainMatcher,
|
||||
textJsonMatcher,
|
||||
imagePngMatcher
|
||||
};
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/multipart")
|
||||
.UsingPost()
|
||||
.WithMultiPart(matchers)
|
||||
)
|
||||
.WithGuid("b9c82182-e469-41da-bcaf-b6e3157fefdb")
|
||||
.RespondWith(Response.Create()
|
||||
.WithBody("MultiPart is ok")
|
||||
);
|
||||
|
||||
// server.SaveStaticMappings();
|
||||
|
||||
System.Console.WriteLine(JsonConvert.SerializeObject(server.MappingModels, Formatting.Indented));
|
||||
|
||||
System.Console.WriteLine("Press any key to stop the server");
|
||||
System.Console.ReadKey();
|
||||
server.Stop();
|
||||
|
||||
System.Console.WriteLine("Displaying all requests");
|
||||
var allRequests = server.LogEntries;
|
||||
System.Console.WriteLine(JsonConvert.SerializeObject(allRequests, Formatting.Indented));
|
||||
|
||||
System.Console.WriteLine("Press any key to quit");
|
||||
System.Console.ReadKey();
|
||||
}
|
||||
}
|
||||
23
examples/WireMock.Net.Console.MimePart/Program.cs
Normal file
23
examples/WireMock.Net.Console.MimePart/Program.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System.Reflection;
|
||||
using log4net;
|
||||
using log4net.Config;
|
||||
using log4net.Repository;
|
||||
|
||||
namespace WireMock.Net.Console.MimePart;
|
||||
|
||||
static class Program
|
||||
{
|
||||
private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
|
||||
|
||||
static async Task Main(params string[] args)
|
||||
{
|
||||
Log.Info("Starting WireMock.Net.Console.MimePart...");
|
||||
|
||||
XmlConfigurator.Configure(LogRepository, new FileInfo("log4net.config"));
|
||||
|
||||
await MainApp.RunAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<DefineConstants>$(DefineConstants);GRAPHQL;MIMEKIT;PROTOBUF</DefineConstants>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="__admin\mappings\*.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
<PackageReference Include="log4net" Version="2.0.15" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="log4net.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,79 @@
|
||||
{
|
||||
"Guid": "b9c82182-e469-41da-bcaf-b6e3157fefdc",
|
||||
"UpdatedAt": "2025-12-18T17:21:57.3879723Z",
|
||||
"Request": {
|
||||
"Path": {
|
||||
"Matchers": [
|
||||
{
|
||||
"Name": "WildcardMatcher",
|
||||
"Pattern": "/multipart2",
|
||||
"IgnoreCase": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"Methods": [
|
||||
"POST"
|
||||
],
|
||||
"Body": {
|
||||
"MatcherName": "MultiPartMatcher",
|
||||
"Matchers": [
|
||||
{
|
||||
"Name": "MimePartMatcher",
|
||||
"ContentTypeMatcher": {
|
||||
"Name": "ContentTypeMatcher",
|
||||
"Pattern": "text/plain",
|
||||
"IgnoreCase": false
|
||||
},
|
||||
"ContentMatcher": {
|
||||
"Name": "ExactMatcher",
|
||||
"Pattern": "This is some plain text",
|
||||
"IgnoreCase": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "MimePartMatcher",
|
||||
"ContentTypeMatcher": {
|
||||
"Name": "ContentTypeMatcher",
|
||||
"Pattern": "application/json",
|
||||
"IgnoreCase": false
|
||||
},
|
||||
"ContentMatcher": {
|
||||
"Name": "JsonMatcher",
|
||||
"Pattern": {
|
||||
"Key": "Value"
|
||||
},
|
||||
"IgnoreCase": true,
|
||||
"Regex": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "MimePartMatcher",
|
||||
"ContentTypeMatcher": {
|
||||
"Name": "ContentTypeMatcher",
|
||||
"Pattern": "image/png",
|
||||
"IgnoreCase": false
|
||||
},
|
||||
"ContentDispositionMatcher": {
|
||||
"Name": "ExactMatcher",
|
||||
"Pattern": "form-data; name=\"image\"; filename=\"image.png\"",
|
||||
"IgnoreCase": false
|
||||
},
|
||||
"ContentTransferEncodingMatcher": {
|
||||
"Name": "ExactMatcher",
|
||||
"Pattern": "default",
|
||||
"IgnoreCase": false
|
||||
},
|
||||
"ContentMatcher": {
|
||||
"Name": "ExactObjectMatcher",
|
||||
"Pattern": "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAgMAAAAP2OW3AAAADFBMVEX/tID/vpH/pWX/sHidUyjlAAAADElEQVR4XmMQYNgAAADkAMHebX3mAAAAAElFTkSuQmCC"
|
||||
}
|
||||
}
|
||||
],
|
||||
"MatchOperator": "Or"
|
||||
}
|
||||
},
|
||||
"Response": {
|
||||
"BodyDestination": "SameAsSource",
|
||||
"Body": "MultiPart2 is ok"
|
||||
}
|
||||
}
|
||||
20
examples/WireMock.Net.Console.MimePart/log4net.config
Normal file
20
examples/WireMock.Net.Console.MimePart/log4net.config
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<configSections>
|
||||
<section name="log4net" type="System.Configuration.IgnoreSectionHandler" />
|
||||
</configSections>
|
||||
<appSettings>
|
||||
<add key="log4net.Internal.Debug" value="true"/>
|
||||
</appSettings>
|
||||
<log4net>
|
||||
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<conversionPattern value="%date [%thread] %-5level %logger{1} - %message%newline" />
|
||||
</layout>
|
||||
</appender>
|
||||
<root>
|
||||
<level value="DEBUG" />
|
||||
<appender-ref ref="ConsoleAppender" />
|
||||
</root>
|
||||
</log4net>
|
||||
</configuration>
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -267,7 +267,7 @@ namespace WireMock.Net.ConsoleApplication
|
||||
}
|
||||
}
|
||||
|
||||
public static void Run()
|
||||
public static async Task RunAsync()
|
||||
{
|
||||
//RunSse();
|
||||
//RunOnLocal();
|
||||
@@ -290,25 +290,56 @@ namespace WireMock.Net.ConsoleApplication
|
||||
|
||||
var server = WireMockServer.Start();
|
||||
|
||||
//server
|
||||
// .Given(Request.Create()
|
||||
// .WithPath("todos")
|
||||
// .UsingGet()
|
||||
// )
|
||||
// .RespondWith(Response.Create()
|
||||
// .WithBodyAsJson(todos.Values)
|
||||
// );
|
||||
|
||||
//server
|
||||
// .Given(Request.Create()
|
||||
// .UsingGet()
|
||||
// .WithPath("todos")
|
||||
// .WithParam("id")
|
||||
// )
|
||||
// .RespondWith(Response.Create()
|
||||
// .WithBodyAsJson(rm => todos[int.Parse(rm.Query!["id"].ToString())])
|
||||
// );
|
||||
|
||||
var pX = 0.80;
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.WithPath("todos")
|
||||
.UsingGet()
|
||||
)
|
||||
.RespondWith(Response.Create()
|
||||
.WithBodyAsJson(todos.Values)
|
||||
);
|
||||
.Given(Request.Create().UsingGet().WithPath("/p"))
|
||||
.WithProbability(pX)
|
||||
.RespondWith(Response.Create().WithStatusCode(200).WithBody("X"));
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.UsingGet()
|
||||
.WithPath("todos")
|
||||
.WithParam("id")
|
||||
)
|
||||
.RespondWith(Response.Create()
|
||||
.WithBodyAsJson(rm => todos[int.Parse(rm.Query!["id"].ToString())])
|
||||
);
|
||||
.Given(Request.Create().UsingGet().WithPath("/p"))
|
||||
.RespondWith(Response.Create().WithStatusCode(200).WithBody("default"));
|
||||
|
||||
// Act
|
||||
var requestUri = new Uri($"http://localhost:{server.Port}/p");
|
||||
var c = server.CreateClient();
|
||||
var xCount = 0;
|
||||
var defaultCount = 0;
|
||||
var tot = 1000;
|
||||
for (var i = 0; i < tot; i++)
|
||||
{
|
||||
var response = await c.GetAsync(requestUri);
|
||||
var value = await response.Content.ReadAsStringAsync();
|
||||
if (value == "X")
|
||||
{
|
||||
xCount++;
|
||||
}
|
||||
else if (value == "default")
|
||||
{
|
||||
defaultCount++;
|
||||
}
|
||||
}
|
||||
System.Console.WriteLine("X = {0} ; default = {1} ; pX = {2:0.00} ; valueX = {3:0.00}", xCount, defaultCount, pX, 1.0 * xCount / tot);
|
||||
|
||||
using var httpAndHttpsWithPort = WireMockServer.Start(new WireMockServerSettings
|
||||
{
|
||||
HostingScheme = HostingScheme.HttpAndHttps,
|
||||
@@ -525,39 +556,6 @@ namespace WireMock.Net.ConsoleApplication
|
||||
);
|
||||
#endif
|
||||
|
||||
#if MIMEKIT
|
||||
var textPlainContentTypeMatcher = new ContentTypeMatcher("text/plain");
|
||||
var textPlainContentMatcher = new ExactMatcher("This is some plain text");
|
||||
var textPlainMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textPlainContentTypeMatcher, null, null, textPlainContentMatcher);
|
||||
|
||||
var textJsonContentTypeMatcher = new ContentTypeMatcher("text/json");
|
||||
var textJsonContentMatcher = new JsonMatcher(new { Key = "Value" }, true);
|
||||
var textJsonMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textJsonContentTypeMatcher, null, null, textJsonContentMatcher);
|
||||
|
||||
var imagePngContentTypeMatcher = new ContentTypeMatcher("image/png");
|
||||
var imagePngContentDispositionMatcher = new ExactMatcher("attachment; filename=\"image.png\"");
|
||||
var imagePngContentTransferEncodingMatcher = new ExactMatcher("base64");
|
||||
var imagePngContentMatcher = new ExactObjectMatcher(Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAgMAAAAP2OW3AAAADFBMVEX/tID/vpH/pWX/sHidUyjlAAAADElEQVR4XmMQYNgAAADkAMHebX3mAAAAAElFTkSuQmCC"));
|
||||
var imagePngMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, imagePngContentTypeMatcher, imagePngContentDispositionMatcher, imagePngContentTransferEncodingMatcher, imagePngContentMatcher);
|
||||
|
||||
var matchers = new IMatcher[]
|
||||
{
|
||||
textPlainMatcher,
|
||||
textJsonMatcher,
|
||||
imagePngMatcher
|
||||
};
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/multipart")
|
||||
.UsingPost()
|
||||
.WithMultiPart(matchers)
|
||||
)
|
||||
.WithGuid("b9c82182-e469-41da-bcaf-b6e3157fefdb")
|
||||
.RespondWith(Response.Create()
|
||||
.WithBody("MultiPart is ok")
|
||||
);
|
||||
#endif
|
||||
// 400 ms
|
||||
server
|
||||
.Given(Request.Create()
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using log4net;
|
||||
using log4net.Config;
|
||||
using log4net.Repository;
|
||||
@@ -14,10 +15,10 @@ static class Program
|
||||
private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
|
||||
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
|
||||
|
||||
static void Main(params string[] args)
|
||||
static async Task Main(params string[] args)
|
||||
{
|
||||
XmlConfigurator.Configure(LogRepository, new FileInfo("log4net.config"));
|
||||
|
||||
MainApp.Run();
|
||||
await MainApp.RunAsync();
|
||||
}
|
||||
}
|
||||
142
examples/WireMock.Net.OpenTelemetryDemo/Program.cs
Normal file
142
examples/WireMock.Net.OpenTelemetryDemo/Program.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
// Copyright © WireMock.Net
|
||||
// OpenTelemetry Tracing Demo for WireMock.Net
|
||||
// This demo uses the Console Exporter to visualize traces in the terminal.
|
||||
|
||||
using OpenTelemetry;
|
||||
using OpenTelemetry.Trace;
|
||||
using WireMock.OpenTelemetry;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
|
||||
Console.WriteLine("=== WireMock.Net OpenTelemetry Tracing Demo ===\n");
|
||||
|
||||
// WireMock.Net creates Activity objects using System.Diagnostics.Activity (built into .NET).
|
||||
// These activities are automatically created when ActivityTracingEnabled is set to true.
|
||||
//
|
||||
// To export these traces, you have two options:
|
||||
//
|
||||
// Option 1: Configure your own TracerProvider (shown below)
|
||||
// - Full control over exporters (Console, OTLP, Jaeger, etc.)
|
||||
// - Add additional instrumentation (HttpClient, database, etc.)
|
||||
// - Recommended for most applications
|
||||
//
|
||||
// Option 2: Use WireMock.Net.OpenTelemetry package
|
||||
// - Reference the WireMock.Net.OpenTelemetry NuGet package
|
||||
// - Use services.AddWireMockOpenTelemetry(openTelemetryOptions)
|
||||
// - Adds WireMock + ASP.NET Core instrumentation and OTLP exporter
|
||||
// - Good for quick setup with all-in-one configuration
|
||||
|
||||
// Option 1: Custom TracerProvider with Console exporter for this demo
|
||||
using var tracerProvider = Sdk.CreateTracerProviderBuilder()
|
||||
.AddWireMockInstrumentation(new OpenTelemetryOptions() { ExcludeAdminRequests = true })
|
||||
.AddHttpClientInstrumentation() // HTTP client traces (for our test requests)
|
||||
.AddConsoleExporter() // Export traces to console for demo purposes
|
||||
.AddOtlpExporter() // Export to real OTLP collector (e.g. Jaeger, Tempo, etc.)
|
||||
.Build();
|
||||
|
||||
Console.WriteLine("Console Exporter configured to visualize:");
|
||||
Console.WriteLine(" - WireMock.Net traces (wiremock.* tags)");
|
||||
Console.WriteLine(" - ASP.NET Core server traces");
|
||||
Console.WriteLine(" - HTTP client traces\n");
|
||||
|
||||
// Start WireMock server with OpenTelemetry enabled (ActivityTracingOptions != null enables tracing)
|
||||
var server = WireMockServer.Start(new WireMockServerSettings
|
||||
{
|
||||
StartAdminInterface = true,
|
||||
ActivityTracingOptions = new ActivityTracingOptions
|
||||
{
|
||||
ExcludeAdminRequests = true
|
||||
}
|
||||
});
|
||||
|
||||
Console.WriteLine($"WireMock server started at: {string.Join(", ", server.Urls)}\n");
|
||||
|
||||
// Configure some mock mappings
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/api/hello")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode(200)
|
||||
.WithBody("Hello from WireMock!"));
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/api/user/*")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode(200)
|
||||
.WithHeader("Content-Type", "application/json")
|
||||
.WithBody(@"{""name"": ""John Doe"", ""email"": ""john@example.com""}"));
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.WithPath("/api/error")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode(500)
|
||||
.WithBody("Internal Server Error"));
|
||||
|
||||
Console.WriteLine("Mock mappings configured:");
|
||||
Console.WriteLine(" GET /api/hello -> 200 OK");
|
||||
Console.WriteLine(" GET /api/user/* -> 200 OK (JSON)");
|
||||
Console.WriteLine(" GET /api/error -> 500 Error");
|
||||
Console.WriteLine();
|
||||
|
||||
// Make some test requests to generate traces
|
||||
using var httpClient = server.CreateClient();
|
||||
|
||||
Console.WriteLine("Making test requests to generate traces...\n");
|
||||
Console.WriteLine("─────────────────────────────────────────────────────────────────");
|
||||
|
||||
// Request 1: Successful request
|
||||
Console.WriteLine("\n>>> Request 1: GET /api/hello");
|
||||
var response1 = await httpClient.GetAsync("/api/hello");
|
||||
Console.WriteLine($"<<< Response: {(int)response1.StatusCode} {response1.StatusCode}");
|
||||
Console.WriteLine($" Body: {await response1.Content.ReadAsStringAsync()}");
|
||||
|
||||
await Task.Delay(500); // Small delay to let trace export complete
|
||||
|
||||
// Request 2: Another successful request with path parameter
|
||||
Console.WriteLine("\n>>> Request 2: GET /api/user/123");
|
||||
var response2 = await httpClient.GetAsync("/api/user/123");
|
||||
Console.WriteLine($"<<< Response: {(int)response2.StatusCode} {response2.StatusCode}");
|
||||
Console.WriteLine($" Body: {await response2.Content.ReadAsStringAsync()}");
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
// Request 3: Error response
|
||||
Console.WriteLine("\n>>> Request 3: GET /api/error");
|
||||
var response3 = await httpClient.GetAsync("/api/error");
|
||||
Console.WriteLine($"<<< Response: {(int)response3.StatusCode} {response3.StatusCode}");
|
||||
Console.WriteLine($" Body: {await response3.Content.ReadAsStringAsync()}");
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
// Request 4: No matching mapping (404)
|
||||
Console.WriteLine("\n>>> Request 4: GET /api/notfound");
|
||||
var response4 = await httpClient.GetAsync("/api/notfound");
|
||||
Console.WriteLine($"<<< Response: {(int)response4.StatusCode} {response4.StatusCode}");
|
||||
|
||||
await Task.Delay(500);
|
||||
|
||||
// Request 5: Admin API request (should be excluded from tracing)
|
||||
Console.WriteLine("\n>>> Request 5: GET /__admin/health");
|
||||
var response5 = await httpClient.GetAsync("/__admin/health");
|
||||
Console.WriteLine($"<<< Admin Health Status: {response5.StatusCode}");
|
||||
|
||||
Console.WriteLine("\n─────────────────────────────────────────────────────────────────");
|
||||
Console.WriteLine("\nTraces above show OpenTelemetry activities from WireMock.Net!");
|
||||
Console.WriteLine("Look for 'Activity.TraceId', 'Activity.SpanId', and custom tags like:");
|
||||
Console.WriteLine(" - http.request.method");
|
||||
Console.WriteLine(" - url.path");
|
||||
Console.WriteLine(" - http.response.status_code");
|
||||
Console.WriteLine(" - wiremock.mapping.matched");
|
||||
Console.WriteLine(" - wiremock.mapping.guid");
|
||||
Console.WriteLine();
|
||||
|
||||
// Cleanup
|
||||
server.Stop();
|
||||
Console.WriteLine("WireMock server stopped. Demo complete!");
|
||||
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.14.0" />
|
||||
<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.14.0" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.14.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.OpenTelemetry\WireMock.Net.OpenTelemetry.csproj" />
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -8,6 +8,12 @@ namespace WireMock.Admin.Mappings;
|
||||
[FluentBuilder.AutoGenerateBuilder]
|
||||
public class BodyModel
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the body matcher.
|
||||
/// Currently only "MultiPartMatcher" is supported.
|
||||
/// </summary>
|
||||
public string? MatcherName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the matcher.
|
||||
/// </summary>
|
||||
|
||||
@@ -22,7 +22,7 @@ public class MatcherModel
|
||||
public object? Pattern { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the patterns. Can be array of strings (default) or an array of objects.
|
||||
/// Gets or sets the patterns. Can be an array of strings (default) or an array of objects.
|
||||
/// </summary>
|
||||
public object[]? Patterns { get; set; }
|
||||
|
||||
|
||||
@@ -24,4 +24,13 @@ public class StatusModel
|
||||
/// The error message.
|
||||
/// </summary>
|
||||
public string? Error { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a string that represents the current status model, including its unique identifier, status, and error information.
|
||||
/// </summary>
|
||||
/// <returns>A string containing the values of the Guid, Status, and Error properties formatted for display.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"StatusModel [Guid={Guid}, Status={Status}, Error={Error}]";
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System.Collections.Generic;
|
||||
using WireMock.Matchers.Request;
|
||||
|
||||
namespace WireMock.Admin.Requests;
|
||||
|
||||
@@ -47,5 +48,5 @@ public class LogRequestMatchModel
|
||||
/// <value>
|
||||
/// The match details.
|
||||
/// </value>
|
||||
public IList<object> MatchDetails { get; set; }
|
||||
public IList<MatchDetail> MatchDetails { get; set; } = [];
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.Admin.Settings;
|
||||
|
||||
/// <summary>
|
||||
@@ -11,15 +13,25 @@ public class ProxyUrlReplaceSettingsModel
|
||||
/// <summary>
|
||||
/// The old path value to be replaced by the new path value
|
||||
/// </summary>
|
||||
public string OldValue { get; set; } = null!;
|
||||
public string? OldValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The new path value to replace the old value with
|
||||
/// </summary>
|
||||
public string NewValue { get; set; } = null!;
|
||||
public string? NewValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines if the case should be ignore when replacing.
|
||||
/// Defines if the case should be ignored when replacing.
|
||||
/// </summary>
|
||||
public bool IgnoreCase { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Holds the transformation template.
|
||||
/// </summary>
|
||||
public string? TransformTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The transformer type.
|
||||
/// </summary>
|
||||
public TransformerType TransformerType { get; set; } = TransformerType.Handlebars;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using WireMock.Validators;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace WireMock.Admin.Mappings;
|
||||
@@ -94,9 +95,14 @@ public partial class RequestModelBuilder
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the Path.
|
||||
/// Set the Path. Must start with a forward slash (/).
|
||||
/// </summary>
|
||||
public RequestModelBuilder WithPath(string value) => WithPath(() => value);
|
||||
public RequestModelBuilder WithPath(string value)
|
||||
{
|
||||
PathValidator.ValidateAndThrow(value);
|
||||
|
||||
return WithPath(() => value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the Path.
|
||||
|
||||
@@ -55,4 +55,11 @@ public interface IRequestMatchResult : IComparable
|
||||
/// <param name="exception">The exception [Optional].</param>
|
||||
/// <returns>The score.</returns>
|
||||
double AddScore(Type matcherType, double score, Exception? exception);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the score.
|
||||
/// </summary>
|
||||
/// <param name="matchDetail">The matchDetail.</param>
|
||||
/// <returns>The score.</returns>
|
||||
double AddMatchDetail(MatchDetail matchDetail);
|
||||
}
|
||||
@@ -12,7 +12,12 @@ public class MatchDetail
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the matcher.
|
||||
/// </summary>
|
||||
public Type MatcherType { get; set; } = null!;
|
||||
public required Type MatcherType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the matcher.
|
||||
/// </summary>
|
||||
public required string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the score between 0.0 and 1.0
|
||||
@@ -24,4 +29,9 @@ public class MatchDetail
|
||||
/// [Optional]
|
||||
/// </summary>
|
||||
public Exception? Exception { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The child MatchResults in case of multiple matchers.
|
||||
/// </summary>
|
||||
public MatchDetail[]? MatchDetails { get; set; }
|
||||
}
|
||||
19
src/WireMock.Net.Abstractions/Validators/PathValidator.cs
Normal file
19
src/WireMock.Net.Abstractions/Validators/PathValidator.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
|
||||
namespace WireMock.Validators;
|
||||
|
||||
public static class PathValidator
|
||||
{
|
||||
/// <summary>
|
||||
/// A valid path must start with a '/' and cannot be null, empty or whitespace.
|
||||
/// </summary>
|
||||
public static void ValidateAndThrow(string? path, string? paramName = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path) || path?.StartsWith("/") == false)
|
||||
{
|
||||
throw new ArgumentException("Path must start with a '/' and cannot be null, empty or whitespace.", paramName ?? nameof(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\WireMock.Net.Minimal\Util\EnhancedFileSystemWatcher.cs" Link="Utils\EnhancedFileSystemWatcher.cs" />
|
||||
<Compile Include="..\WireMock.Net.Minimal\Util\EnhancedFileSystemWatcher.cs" Link="Util\EnhancedFileSystemWatcher.cs" />
|
||||
<Compile Include="..\WireMock.Net.Minimal\Constants\WireMockConstants.cs" Link="Constants\WireMockConstants.cs" />
|
||||
<Compile Include="..\WireMock.Net.Shared\Constants\RegexConstants.cs" Link="Constants\RegexConstants.cs" />
|
||||
<Compile Include="..\WireMock.Net.Minimal\Util\PortUtils.cs" Link="Util\PortUtils.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
|
||||
@@ -42,7 +45,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting" Version="9.2.0" />
|
||||
<PackageReference Include="Aspire.Hosting" Version="13.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
44
src/WireMock.Net.Aspire/WireMockHealthCheck.cs
Normal file
44
src/WireMock.Net.Aspire/WireMockHealthCheck.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using Aspire.Hosting.ApplicationModel;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using WireMock.Client;
|
||||
|
||||
namespace WireMock.Net.Aspire;
|
||||
|
||||
/// <summary>
|
||||
/// WireMockHealthCheck
|
||||
/// </summary>
|
||||
public class WireMockHealthCheck(WireMockServerResource resource) : IHealthCheck
|
||||
{
|
||||
private const string HealthStatusHealthy = "Healthy";
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (!await IsHealthyAsync(resource.AdminApi.Value, cancellationToken))
|
||||
{
|
||||
return HealthCheckResult.Unhealthy("WireMock.Net is not healthy");
|
||||
}
|
||||
|
||||
if (resource.ApiMappingState == WireMockMappingState.NotSubmitted)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy("WireMock.Net has not received mappings");
|
||||
}
|
||||
|
||||
return HealthCheckResult.Healthy();
|
||||
}
|
||||
|
||||
private static async Task<bool> IsHealthyAsync(IWireMockAdminApi adminApi, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
var status = await adminApi.GetHealthAsync(cancellationToken);
|
||||
return string.Equals(status, HealthStatusHealthy, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
src/WireMock.Net.Aspire/WireMockMappingState.cs
Normal file
12
src/WireMock.Net.Aspire/WireMockMappingState.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
namespace WireMock.Net.Aspire;
|
||||
|
||||
internal enum WireMockMappingState
|
||||
{
|
||||
NoMappings = 0,
|
||||
|
||||
NotSubmitted = 1,
|
||||
|
||||
Submitted = 2
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Stef.Validation;
|
||||
using WireMock.Client.Builders;
|
||||
using WireMock.Util;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Aspire.Hosting;
|
||||
@@ -21,10 +23,15 @@ public class WireMockServerArguments
|
||||
private const string DefaultLogger = "WireMockConsoleLogger";
|
||||
|
||||
/// <summary>
|
||||
/// The HTTP port where WireMock.Net is listening.
|
||||
/// The HTTP ports where WireMock.Net is listening on.
|
||||
/// If not defined, .NET Aspire automatically assigns a random port.
|
||||
/// </summary>
|
||||
public int? HttpPort { get; set; }
|
||||
public List<int> HttpPorts { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Additional Urls on which WireMock listens.
|
||||
/// </summary>
|
||||
public List<string> AdditionalUrls { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// The admin username.
|
||||
@@ -67,6 +74,58 @@ public class WireMockServerArguments
|
||||
/// </summary>
|
||||
public Func<AdminApiMappingBuilder, CancellationToken, Task>? ApiMappingBuilder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Grpc ProtoDefinitions.
|
||||
/// </summary>
|
||||
public Dictionary<string, string[]> ProtoDefinitions { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether OpenTelemetry tracing is enabled.
|
||||
/// When enabled, WireMock.Net will emit distributed traces for request processing.
|
||||
/// Default value is <c>false</c>.
|
||||
/// </summary>
|
||||
public bool OpenTelemetryEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the OTLP exporter endpoint URL.
|
||||
/// When set, traces will be exported to this endpoint using the OTLP protocol.
|
||||
/// Example: "http://localhost:4317" for gRPC or "http://localhost:4318" for HTTP.
|
||||
/// If not set, the OTLP exporter will use the <c>OTEL_EXPORTER_OTLP_ENDPOINT</c> environment variable,
|
||||
/// or fall back to the default endpoint (<c>http://localhost:4317</c> for gRPC).
|
||||
/// </summary>
|
||||
public string? OpenTelemetryOtlpExporterEndpoint { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Add an additional Urls on which WireMock should listen.
|
||||
/// </summary>
|
||||
/// <param name="additionalUrls">The additional urls which the WireMock Server should listen on.</param>
|
||||
public void WithAdditionalUrls(params string[] additionalUrls)
|
||||
{
|
||||
foreach (var url in additionalUrls)
|
||||
{
|
||||
if (!PortUtils.TryExtract(Guard.NotNullOrEmpty(url), out _, out _, out _, out _, out var port))
|
||||
{
|
||||
throw new ArgumentException($"The URL '{url}' is not valid.");
|
||||
}
|
||||
|
||||
AdditionalUrls.Add(Guard.NotNullOrWhiteSpace(url));
|
||||
HttpPorts.Add(port);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a Grpc ProtoDefinition at server-level.
|
||||
/// </summary>
|
||||
/// <param name="id">Unique identifier for the ProtoDefinition.</param>
|
||||
/// <param name="protoDefinitions">The ProtoDefinition as text.</param>
|
||||
public void WithProtoDefinition(string id, params string[] protoDefinitions)
|
||||
{
|
||||
Guard.NotNullOrWhiteSpace(id);
|
||||
Guard.NotNullOrEmpty(protoDefinitions);
|
||||
|
||||
ProtoDefinitions[id] = protoDefinitions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the current instance's properties to an array of command-line arguments for starting the WireMock.Net server.
|
||||
/// </summary>
|
||||
@@ -95,6 +154,25 @@ public class WireMockServerArguments
|
||||
Add(args, "--WatchStaticMappingsInSubdirectories", "true");
|
||||
}
|
||||
|
||||
if (OpenTelemetryEnabled)
|
||||
{
|
||||
// Enable activity tracing (creates System.Diagnostics.Activity objects)
|
||||
Add(args, "--ActivityTracingEnabled", "true");
|
||||
|
||||
// Enable OpenTelemetry exporter
|
||||
Add(args, "--OpenTelemetryEnabled", "true");
|
||||
|
||||
if (!string.IsNullOrEmpty(OpenTelemetryOtlpExporterEndpoint))
|
||||
{
|
||||
Add(args, "--OpenTelemetryOtlpExporterEndpoint", OpenTelemetryOtlpExporterEndpoint);
|
||||
}
|
||||
}
|
||||
|
||||
if (AdditionalUrls.Count > 0)
|
||||
{
|
||||
Add(args, "--Urls", $"http://*:{HttpContainerPort} {string.Join(' ', AdditionalUrls)}");
|
||||
}
|
||||
|
||||
return args
|
||||
.SelectMany(k => new[] { k.Key, k.Value })
|
||||
.ToArray();
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
using Aspire.Hosting.ApplicationModel;
|
||||
using Aspire.Hosting.Lifecycle;
|
||||
using Aspire.Hosting.WireMock;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Stef.Validation;
|
||||
using WireMock.Client.Builders;
|
||||
using WireMock.Net.Aspire;
|
||||
using WireMock.Util;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace Aspire.Hosting;
|
||||
@@ -33,9 +35,31 @@ public static class WireMockServerBuilderExtensions
|
||||
Guard.NotNullOrWhiteSpace(name);
|
||||
Guard.Condition(port, p => p is null or > 0 and <= ushort.MaxValue);
|
||||
|
||||
return builder.AddWireMock(name, callback =>
|
||||
return builder.AddWireMock(name, serverArguments =>
|
||||
{
|
||||
callback.HttpPort = port;
|
||||
if (port != null)
|
||||
{
|
||||
serverArguments.HttpPorts = [port.Value];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a WireMock.Net Server resource to the application model.
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param>
|
||||
/// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param>
|
||||
/// <param name="additionalUrls">The additional urls which the WireMock Server should listen on.</param>
|
||||
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
||||
public static IResourceBuilder<WireMockServerResource> AddWireMock(this IDistributedApplicationBuilder builder, string name, params string[] additionalUrls)
|
||||
{
|
||||
Guard.NotNull(builder);
|
||||
Guard.NotNullOrWhiteSpace(name);
|
||||
Guard.NotNull(additionalUrls);
|
||||
|
||||
return builder.AddWireMock(name, serverArguments =>
|
||||
{
|
||||
serverArguments.WithAdditionalUrls(additionalUrls);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -53,13 +77,50 @@ public static class WireMockServerBuilderExtensions
|
||||
Guard.NotNull(arguments);
|
||||
|
||||
var wireMockContainerResource = new WireMockServerResource(name, arguments);
|
||||
|
||||
var healthCheckKey = $"{name}_check";
|
||||
var healthCheckRegistration = new HealthCheckRegistration(
|
||||
healthCheckKey,
|
||||
_ => new WireMockHealthCheck(wireMockContainerResource),
|
||||
failureStatus: null,
|
||||
tags: null);
|
||||
builder.Services.AddHealthChecks().Add(healthCheckRegistration);
|
||||
|
||||
var resourceBuilder = builder
|
||||
.AddResource(wireMockContainerResource)
|
||||
.WithImage(DefaultLinuxImage)
|
||||
.WithEnvironment(ctx => ctx.EnvironmentVariables.Add("DOTNET_USE_POLLING_FILE_WATCHER", "1")) // https://khalidabuhakmeh.com/aspnet-docker-gotchas-and-workarounds#configuration-reloads-and-filesystemwatcher
|
||||
.WithHttpEndpoint(port: arguments.HttpPort, targetPort: WireMockServerArguments.HttpContainerPort)
|
||||
.WithHealthCheck(healthCheckKey)
|
||||
.WithWireMockInspectorCommand();
|
||||
|
||||
if (arguments.HttpPorts.Count == 0)
|
||||
{
|
||||
resourceBuilder = resourceBuilder.WithHttpEndpoint(port: null, targetPort: WireMockServerArguments.HttpContainerPort);
|
||||
}
|
||||
else if (arguments.HttpPorts.Count == 1)
|
||||
{
|
||||
resourceBuilder = resourceBuilder.WithHttpEndpoint(port: arguments.HttpPorts[0], targetPort: WireMockServerArguments.HttpContainerPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Required for the default admin endpoint and health checks
|
||||
resourceBuilder = resourceBuilder.WithHttpEndpoint(port: null, targetPort: WireMockServerArguments.HttpContainerPort);
|
||||
|
||||
var anyIsHttp2 = false;
|
||||
foreach (var url in arguments.AdditionalUrls)
|
||||
{
|
||||
PortUtils.TryExtract(url, out _, out var isHttp2, out var scheme, out _, out var httpPort);
|
||||
anyIsHttp2 |= isHttp2;
|
||||
|
||||
resourceBuilder = resourceBuilder.WithEndpoint(port: httpPort, targetPort: httpPort, scheme: scheme, name: $"{scheme}-{httpPort}");
|
||||
}
|
||||
|
||||
if (anyIsHttp2)
|
||||
{
|
||||
resourceBuilder = resourceBuilder.AsHttp2Service();
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(arguments.MappingsPath))
|
||||
{
|
||||
resourceBuilder = resourceBuilder.WithBindMount(arguments.MappingsPath, DefaultLinuxMappingsPath);
|
||||
@@ -73,6 +134,9 @@ public static class WireMockServerBuilderExtensions
|
||||
}
|
||||
});
|
||||
|
||||
// Always add the lifecycle hook to support dynamic mappings and proto definitions
|
||||
resourceBuilder.ApplicationBuilder.Services.TryAddLifecycleHook<WireMockServerLifecycleHook>();
|
||||
|
||||
return resourceBuilder;
|
||||
}
|
||||
|
||||
@@ -83,7 +147,10 @@ public static class WireMockServerBuilderExtensions
|
||||
/// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param>
|
||||
/// <param name="callback">A callback that allows for setting the <see cref="WireMockServerArguments"/>.</param>
|
||||
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
||||
public static IResourceBuilder<WireMockServerResource> AddWireMock(this IDistributedApplicationBuilder builder, string name, Action<WireMockServerArguments> callback)
|
||||
public static IResourceBuilder<WireMockServerResource> AddWireMock(
|
||||
this IDistributedApplicationBuilder builder,
|
||||
string name,
|
||||
Action<WireMockServerArguments> callback)
|
||||
{
|
||||
Guard.NotNull(builder);
|
||||
Guard.NotNullOrWhiteSpace(name);
|
||||
@@ -154,7 +221,7 @@ public static class WireMockServerBuilderExtensions
|
||||
/// </summary>
|
||||
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param>
|
||||
/// <param name="configure">Delegate that will be invoked to configure the WireMock.Net resource.</param>
|
||||
/// <returns></returns>
|
||||
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
||||
public static IResourceBuilder<WireMockServerResource> WithApiMappingBuilder(this IResourceBuilder<WireMockServerResource> wiremock, Func<AdminApiMappingBuilder, Task> configure)
|
||||
{
|
||||
return wiremock.WithApiMappingBuilder((adminApiMappingBuilder, _) => configure.Invoke(adminApiMappingBuilder));
|
||||
@@ -165,13 +232,27 @@ public static class WireMockServerBuilderExtensions
|
||||
/// </summary>
|
||||
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param>
|
||||
/// <param name="configure">Delegate that will be invoked to configure the WireMock.Net resource.</param>
|
||||
/// <returns></returns>
|
||||
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
||||
public static IResourceBuilder<WireMockServerResource> WithApiMappingBuilder(this IResourceBuilder<WireMockServerResource> wiremock, Func<AdminApiMappingBuilder, CancellationToken, Task> configure)
|
||||
{
|
||||
Guard.NotNull(wiremock);
|
||||
|
||||
wiremock.ApplicationBuilder.Services.TryAddLifecycleHook<WireMockServerLifecycleHook>();
|
||||
wiremock.Resource.Arguments.ApiMappingBuilder = configure;
|
||||
wiremock.Resource.ApiMappingState = WireMockMappingState.NotSubmitted;
|
||||
|
||||
return wiremock;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a Grpc ProtoDefinition at server-level.
|
||||
/// </summary>
|
||||
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param>
|
||||
/// <param name="id">Unique identifier for the ProtoDefinition.</param>
|
||||
/// <param name="protoDefinitions">The ProtoDefinition as text.</param>
|
||||
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
||||
public static IResourceBuilder<WireMockServerResource> WithProtoDefinition(this IResourceBuilder<WireMockServerResource> wiremock, string id, params string[] protoDefinitions)
|
||||
{
|
||||
Guard.NotNull(wiremock).Resource.Arguments.WithProtoDefinition(id, protoDefinitions);
|
||||
|
||||
return wiremock;
|
||||
}
|
||||
@@ -183,11 +264,11 @@ public static class WireMockServerBuilderExtensions
|
||||
/// dotnet tool install WireMockInspector --global --no-cache --ignore-failed-sources
|
||||
/// </code>
|
||||
/// </summary>
|
||||
/// <param name="builder">The <see cref="IResourceBuilder{WireMockNetResource}"/>.</param>
|
||||
/// <returns></returns>
|
||||
public static IResourceBuilder<WireMockServerResource> WithWireMockInspectorCommand(this IResourceBuilder<WireMockServerResource> builder)
|
||||
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockNetResource}"/>.</param>
|
||||
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
||||
public static IResourceBuilder<WireMockServerResource> WithWireMockInspectorCommand(this IResourceBuilder<WireMockServerResource> wiremock)
|
||||
{
|
||||
Guard.NotNull(builder);
|
||||
Guard.NotNull(wiremock);
|
||||
|
||||
CommandOptions commandOptions = new()
|
||||
{
|
||||
@@ -197,13 +278,47 @@ public static class WireMockServerBuilderExtensions
|
||||
IconVariant = IconVariant.Filled
|
||||
};
|
||||
|
||||
builder.WithCommand(
|
||||
wiremock.WithCommand(
|
||||
name: "wiremock-inspector",
|
||||
displayName: "WireMock Inspector",
|
||||
executeCommand: _ => OnRunOpenInspectorCommandAsync(builder),
|
||||
executeCommand: _ => OnRunOpenInspectorCommandAsync(wiremock),
|
||||
commandOptions: commandOptions);
|
||||
|
||||
return builder;
|
||||
return wiremock;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures OpenTelemetry distributed tracing for the WireMock.Net server.
|
||||
/// This enables automatic trace export to the Aspire dashboard.
|
||||
/// </summary>
|
||||
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param>
|
||||
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
||||
/// <remarks>
|
||||
/// When enabled, WireMock.Net will emit distributed traces for each request processed,
|
||||
/// including information about:
|
||||
/// <list type="bullet">
|
||||
/// <item>HTTP method, URL, and status code</item>
|
||||
/// <item>Mapping match results and scores</item>
|
||||
/// <item>Request processing duration</item>
|
||||
/// </list>
|
||||
/// The traces will automatically appear in the Aspire dashboard.
|
||||
/// </remarks>
|
||||
public static IResourceBuilder<WireMockServerResource> WithOpenTelemetry(this IResourceBuilder<WireMockServerResource> wiremock)
|
||||
{
|
||||
Guard.NotNull(wiremock);
|
||||
|
||||
// Enable OpenTelemetry in WireMock server arguments
|
||||
wiremock.Resource.Arguments.OpenTelemetryEnabled = true;
|
||||
|
||||
// Use Aspire's standard WithOtlpExporter to configure OTEL environment variables for the container
|
||||
// This sets OTEL_EXPORTER_OTLP_ENDPOINT which the OTLP exporter reads automatically
|
||||
var containerBuilder = wiremock as IResourceBuilder<ContainerResource>;
|
||||
if (containerBuilder != null)
|
||||
{
|
||||
containerBuilder.WithOtlpExporter();
|
||||
}
|
||||
|
||||
return wiremock;
|
||||
}
|
||||
|
||||
private static Task<ExecuteCommandResult> OnRunOpenInspectorCommandAsync(IResourceBuilder<WireMockServerResource> builder)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System.Diagnostics;
|
||||
using Aspire.Hosting.ApplicationModel;
|
||||
using Aspire.Hosting.Lifecycle;
|
||||
using Microsoft.Extensions.Logging;
|
||||
@@ -10,32 +11,49 @@ internal class WireMockServerLifecycleHook(ILoggerFactory loggerFactory) : IDist
|
||||
{
|
||||
private readonly CancellationTokenSource _shutdownCts = new();
|
||||
|
||||
public async Task AfterResourcesCreatedAsync(DistributedApplicationModel appModel, CancellationToken cancellationToken = default)
|
||||
private CancellationTokenSource? _linkedCts;
|
||||
private Task? _mappingTask;
|
||||
|
||||
public Task AfterEndpointsAllocatedAsync(DistributedApplicationModel appModel, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var cts = CancellationTokenSource.CreateLinkedTokenSource(_shutdownCts.Token, cancellationToken);
|
||||
_linkedCts = CancellationTokenSource.CreateLinkedTokenSource(_shutdownCts.Token, cancellationToken);
|
||||
|
||||
var wireMockServerResources = appModel.Resources
|
||||
.OfType<WireMockServerResource>()
|
||||
.ToArray();
|
||||
|
||||
foreach (var wireMockServerResource in wireMockServerResources)
|
||||
_mappingTask = Task.Run(async () =>
|
||||
{
|
||||
wireMockServerResource.SetLogger(loggerFactory.CreateLogger<WireMockServerResource>());
|
||||
var wireMockServerResources = appModel.Resources
|
||||
.OfType<WireMockServerResource>()
|
||||
.ToArray();
|
||||
|
||||
var endpoint = wireMockServerResource.GetEndpoint();
|
||||
if (endpoint.IsAllocated)
|
||||
foreach (var wireMockServerResource in wireMockServerResources)
|
||||
{
|
||||
await wireMockServerResource.WaitForHealthAsync(cts.Token);
|
||||
wireMockServerResource.SetLogger(loggerFactory.CreateLogger<WireMockServerResource>());
|
||||
|
||||
await wireMockServerResource.CallApiMappingBuilderActionAsync(cts.Token);
|
||||
var endpoint = wireMockServerResource.GetEndpoint();
|
||||
Debug.Assert(endpoint.IsAllocated);
|
||||
|
||||
wireMockServerResource.StartWatchingStaticMappings(cts.Token);
|
||||
await wireMockServerResource.WaitForHealthAsync(_linkedCts.Token);
|
||||
|
||||
await wireMockServerResource.CallAddProtoDefinitionsAsync(_linkedCts.Token);
|
||||
|
||||
await wireMockServerResource.CallApiMappingBuilderActionAsync(_linkedCts.Token);
|
||||
|
||||
wireMockServerResource.StartWatchingStaticMappings(_linkedCts.Token);
|
||||
}
|
||||
}
|
||||
}, _linkedCts.Token);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await _shutdownCts.CancelAsync();
|
||||
|
||||
_linkedCts?.Dispose();
|
||||
_shutdownCts.Dispose();
|
||||
|
||||
if (_mappingTask is not null)
|
||||
{
|
||||
await _mappingTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using RestEase;
|
||||
using Stef.Validation;
|
||||
using WireMock.Client;
|
||||
using WireMock.Client.Extensions;
|
||||
using WireMock.Net.Aspire;
|
||||
using WireMock.Util;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
@@ -19,6 +20,7 @@ public class WireMockServerResource : ContainerResource, IResourceWithServiceDis
|
||||
|
||||
internal WireMockServerArguments Arguments { get; }
|
||||
internal Lazy<IWireMockAdminApi> AdminApi => new(CreateWireMockAdminApi);
|
||||
internal WireMockMappingState ApiMappingState { get; set; } = WireMockMappingState.NoMappings;
|
||||
|
||||
private ILogger? _logger;
|
||||
private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher;
|
||||
@@ -64,6 +66,36 @@ public class WireMockServerResource : ContainerResource, IResourceWithServiceDis
|
||||
|
||||
var mappingBuilder = AdminApi.Value.GetMappingBuilder();
|
||||
await Arguments.ApiMappingBuilder.Invoke(mappingBuilder, cancellationToken);
|
||||
|
||||
ApiMappingState = WireMockMappingState.Submitted;
|
||||
}
|
||||
|
||||
internal async Task CallAddProtoDefinitionsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger?.LogInformation("Calling AdminApi to add GRPC ProtoDefinition at server level to WireMock.Net");
|
||||
|
||||
foreach (var (id, protoDefinitions) in Arguments.ProtoDefinitions)
|
||||
{
|
||||
_logger?.LogInformation("Adding ProtoDefinition {Id}", id);
|
||||
foreach (var protoDefinition in protoDefinitions)
|
||||
{
|
||||
try
|
||||
{
|
||||
var status = await AdminApi.Value.AddProtoDefinitionAsync(id, protoDefinition, cancellationToken);
|
||||
_logger?.LogInformation("ProtoDefinition '{Id}' added with status: {Status}.", id, status.Status);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger?.LogWarning(ex, "Error adding ProtoDefinition '{Id}'.", id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Force a reload of static mappings when ProtoDefinitions are added at server-level to fix #1382
|
||||
if (Arguments.ProtoDefinitions.Count > 0)
|
||||
{
|
||||
await ReloadStaticMappingsAsync(default);
|
||||
}
|
||||
}
|
||||
|
||||
internal void StartWatchingStaticMappings(CancellationToken cancellationToken)
|
||||
@@ -109,10 +141,17 @@ public class WireMockServerResource : ContainerResource, IResourceWithServiceDis
|
||||
|
||||
private async void FileCreatedChangedOrDeleted(object sender, FileSystemEventArgs args)
|
||||
{
|
||||
_logger?.LogInformation("MappingFile created, changed or deleted: '{0}'. Triggering ReloadStaticMappings.", args.FullPath);
|
||||
_logger?.LogInformation("MappingFile created, changed or deleted: '{FullPath}'. Triggering ReloadStaticMappings.", args.FullPath);
|
||||
|
||||
await ReloadStaticMappingsAsync(default);
|
||||
}
|
||||
|
||||
private async Task ReloadStaticMappingsAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
await AdminApi.Value.ReloadStaticMappingsAsync();
|
||||
var status = await AdminApi.Value.ReloadStaticMappingsAsync(cancellationToken);
|
||||
_logger?.LogInformation("ReloadStaticMappings called with status: {Status}.", status);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -140,7 +140,7 @@ public class GraphQLMatcher : IGraphQLMatcher
|
||||
}
|
||||
}
|
||||
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -97,7 +97,7 @@ public class CSharpCodeMatcher : ICSharpCodeMatcher
|
||||
}
|
||||
}
|
||||
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
}
|
||||
|
||||
private bool IsMatch(dynamic input, string pattern)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using WireMock.Matchers.Helpers;
|
||||
using WireMock.Models.Mime;
|
||||
using WireMock.Util;
|
||||
@@ -12,7 +13,7 @@ namespace WireMock.Matchers;
|
||||
/// </summary>
|
||||
public class MimePartMatcher : IMimePartMatcher
|
||||
{
|
||||
private readonly Func<IMimePartData, MatchResult>[] _funcs;
|
||||
private readonly IList<(string Name, Func<IMimePartData, MatchResult> func)> _matcherFunctions;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => nameof(MimePartMatcher);
|
||||
@@ -49,34 +50,47 @@ public class MimePartMatcher : IMimePartMatcher
|
||||
ContentTransferEncodingMatcher = contentTransferEncodingMatcher;
|
||||
ContentMatcher = contentMatcher;
|
||||
|
||||
_funcs =
|
||||
[
|
||||
mp => ContentTypeMatcher?.IsMatch(GetContentTypeAsString(mp.ContentType)) ?? MatchScores.Perfect,
|
||||
mp => ContentDispositionMatcher?.IsMatch(mp.ContentDisposition?.ToString()?.Replace("Content-Disposition: ", string.Empty)) ?? MatchScores.Perfect,
|
||||
mp => ContentTransferEncodingMatcher?.IsMatch(mp.ContentTransferEncoding.ToLowerInvariant()) ?? MatchScores.Perfect,
|
||||
MatchOnContent
|
||||
];
|
||||
_matcherFunctions = [];
|
||||
if (ContentTypeMatcher != null)
|
||||
{
|
||||
_matcherFunctions.Add((nameof(ContentTypeMatcher), mp => ContentTypeMatcher.IsMatch(GetContentTypeAsString(mp.ContentType))));
|
||||
}
|
||||
|
||||
if (ContentDispositionMatcher != null)
|
||||
{
|
||||
_matcherFunctions.Add((nameof(ContentDispositionMatcher), mp => ContentDispositionMatcher.IsMatch(mp.ContentDisposition?.ToString()?.Replace("Content-Disposition: ", string.Empty))));
|
||||
}
|
||||
|
||||
if (ContentTransferEncodingMatcher != null)
|
||||
{
|
||||
_matcherFunctions.Add((nameof(ContentTransferEncodingMatcher), mp => ContentTransferEncodingMatcher.IsMatch(mp.ContentTransferEncoding.ToLowerInvariant())));
|
||||
}
|
||||
|
||||
if (ContentMatcher != null)
|
||||
{
|
||||
_matcherFunctions.Add((ContentMatcher.Name, MatchOnContent));
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public MatchResult IsMatch(IMimePartData value)
|
||||
{
|
||||
var score = MatchScores.Mismatch;
|
||||
Exception? exception = null;
|
||||
var results = new List<MatchResult>();
|
||||
|
||||
try
|
||||
foreach (var matcherFunction in _matcherFunctions)
|
||||
{
|
||||
if (Array.TrueForAll(_funcs, func => func(value).IsPerfect()))
|
||||
try
|
||||
{
|
||||
score = MatchScores.Perfect;
|
||||
var matchResult = matcherFunction.func(value);
|
||||
results.Add(MatchResult.From(matcherFunction.Name, matchResult.Score));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
results.Add(MatchResult.From(matcherFunction.Name, MatchScores.Mismatch, ex));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
}
|
||||
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
return MatchResult.From(nameof(MimePartMatcher), results, MatchOperator.And);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -87,11 +101,6 @@ public class MimePartMatcher : IMimePartMatcher
|
||||
|
||||
private MatchResult MatchOnContent(IMimePartData mimePart)
|
||||
{
|
||||
if (ContentMatcher == null)
|
||||
{
|
||||
return MatchScores.Perfect;
|
||||
}
|
||||
|
||||
var bodyParserSettings = new BodyParserSettings
|
||||
{
|
||||
Stream = mimePart.Open(),
|
||||
@@ -102,7 +111,7 @@ public class MimePartMatcher : IMimePartMatcher
|
||||
};
|
||||
|
||||
var bodyData = BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
return BodyDataMatchScoreCalculator.CalculateMatchScore(bodyData, ContentMatcher);
|
||||
return BodyDataMatchScoreCalculator.CalculateMatchScore(bodyData, ContentMatcher!);
|
||||
}
|
||||
|
||||
private static string? GetContentTypeAsString(IContentTypeData? contentType)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -33,18 +32,27 @@ internal class MimeKitUtils : IMimeKitUtils
|
||||
StartsWithMultiPart(contentTypeHeader)
|
||||
)
|
||||
{
|
||||
var bytes = requestMessage.BodyData?.DetectedBodyType switch
|
||||
byte[] bytes;
|
||||
|
||||
switch (requestMessage.BodyData?.DetectedBodyType)
|
||||
{
|
||||
// If the body is bytes, use the BodyAsBytes to match on.
|
||||
BodyType.Bytes => requestMessage.BodyData.BodyAsBytes!,
|
||||
case BodyType.Bytes:
|
||||
bytes = requestMessage.BodyData.BodyAsBytes!;
|
||||
break;
|
||||
|
||||
// If the body is a String or MultiPart, use the BodyAsString to match on.
|
||||
BodyType.String or BodyType.MultiPart => Encoding.UTF8.GetBytes(requestMessage.BodyData.BodyAsString!),
|
||||
case BodyType.String or BodyType.MultiPart:
|
||||
bytes = Encoding.UTF8.GetBytes(requestMessage.BodyData.BodyAsString!);
|
||||
break;
|
||||
|
||||
_ => throw new NotSupportedException()
|
||||
};
|
||||
// Else return false.
|
||||
default:
|
||||
mimeMessageData = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
var fixedBytes = FixBytes(bytes, contentTypeHeader[0]);
|
||||
var fixedBytes = PrependContentTypeHeader(bytes, contentTypeHeader[0]);
|
||||
|
||||
mimeMessageData = LoadFromStream(new MemoryStream(fixedBytes));
|
||||
return true;
|
||||
@@ -60,7 +68,10 @@ internal class MimeKitUtils : IMimeKitUtils
|
||||
return contentTypeHeader.Any(ct => ct.TrimStart().StartsWith("multipart/", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private static byte[] FixBytes(byte[] bytes, WireMockList<string> contentType)
|
||||
/// <summary>
|
||||
/// Prepends the Content-Type header to the byte array to make it a valid MIME message for MimeKit.
|
||||
/// </summary>
|
||||
private static byte[] PrependContentTypeHeader(byte[] bytes, WireMockList<string> contentType)
|
||||
{
|
||||
var contentTypeBytes = Encoding.UTF8.GetBytes($"{HttpKnownHeaderNames.ContentType}: {contentType}\r\n\r\n");
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ internal class AzureADAuthenticationMatcher : IStringMatcher
|
||||
{
|
||||
if (string.IsNullOrEmpty(input))
|
||||
{
|
||||
return MatchScores.Mismatch;
|
||||
return MatchResult.From(Name);
|
||||
}
|
||||
|
||||
var token = Regex.Replace(input, BearerPrefix, string.Empty, RegexOptions.IgnoreCase, RegexConstants.DefaultTimeout);
|
||||
@@ -83,11 +83,11 @@ internal class AzureADAuthenticationMatcher : IStringMatcher
|
||||
// Throws an Exception as the token is invalid (expired, invalid-formatted, tenant mismatch, etc.)
|
||||
_jwtSecurityTokenHandler.ValidateToken(token, validationParameters, out _);
|
||||
|
||||
return MatchScores.Perfect;
|
||||
return MatchResult.From(Name, MatchScores.Perfect);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new MatchResult(MatchScores.Mismatch, ex);
|
||||
return MatchResult.From(Name, ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,13 @@ internal static class HttpClientBuilder
|
||||
var handler = new HttpClientHandler
|
||||
{
|
||||
CheckCertificateRevocationList = false,
|
||||
#if NET5_0_OR_GREATER
|
||||
SslProtocols = System.Security.Authentication.SslProtocols.Tls13 | System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls,
|
||||
#else
|
||||
SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls,
|
||||
#endif
|
||||
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true,
|
||||
|
||||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
|
||||
};
|
||||
#elif NET46
|
||||
@@ -62,7 +67,10 @@ internal static class HttpClientBuilder
|
||||
}
|
||||
}
|
||||
|
||||
#if !NETSTANDARD1_3
|
||||
#if NET5_0_OR_GREATER
|
||||
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
|
||||
ServicePointManager.ServerCertificateValidationCallback = (message, cert, chain, errors) => true;
|
||||
#elif !NETSTANDARD1_3
|
||||
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
|
||||
ServicePointManager.ServerCertificateValidationCallback = (message, cert, chain, errors) => true;
|
||||
#endif
|
||||
|
||||
@@ -11,24 +11,17 @@ using Stef.Validation;
|
||||
using WireMock.Models;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Transformers;
|
||||
using WireMock.Transformers.Handlebars;
|
||||
using WireMock.Transformers.Scriban;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Http;
|
||||
|
||||
internal class WebhookSender
|
||||
internal class WebhookSender(WireMockServerSettings settings)
|
||||
{
|
||||
private const string ClientIp = "::1";
|
||||
private static readonly ThreadLocal<Random> Random = new(() => new Random(DateTime.UtcNow.Millisecond));
|
||||
|
||||
private readonly WireMockServerSettings _settings;
|
||||
|
||||
public WebhookSender(WireMockServerSettings settings)
|
||||
{
|
||||
_settings = Guard.NotNull(settings);
|
||||
}
|
||||
private readonly WireMockServerSettings _settings = Guard.NotNull(settings);
|
||||
|
||||
public async Task<HttpResponseMessage> SendAsync(
|
||||
HttpClient client,
|
||||
@@ -49,24 +42,7 @@ internal class WebhookSender
|
||||
string requestUrl;
|
||||
if (webhookRequest.UseTransformer == true)
|
||||
{
|
||||
ITransformer transformer;
|
||||
switch (webhookRequest.TransformerType)
|
||||
{
|
||||
case TransformerType.Handlebars:
|
||||
var factoryHandlebars = new HandlebarsContextFactory(_settings);
|
||||
transformer = new Transformer(_settings, factoryHandlebars);
|
||||
break;
|
||||
|
||||
case TransformerType.Scriban:
|
||||
case TransformerType.ScribanDotLiquid:
|
||||
var factoryDotLiquid = new ScribanContextFactory(_settings.FileSystemHandler, webhookRequest.TransformerType);
|
||||
transformer = new Transformer(_settings, factoryDotLiquid);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"TransformerType '{webhookRequest.TransformerType}' is not supported.");
|
||||
}
|
||||
|
||||
var transformer = TransformerFactory.Create(webhookRequest.TransformerType, _settings);
|
||||
bodyData = transformer.TransformBody(mapping, originalRequestMessage, originalResponseMessage, webhookRequest.BodyData, webhookRequest.TransformerReplaceNodeOptions);
|
||||
headers = transformer.TransformHeaders(mapping, originalRequestMessage, originalResponseMessage, webhookRequest.Headers);
|
||||
requestUrl = transformer.TransformString(mapping, originalRequestMessage, originalResponseMessage, webhookRequest.Url);
|
||||
|
||||
@@ -69,7 +69,7 @@ public class WireMockConsoleLogger : IWireMockLogger
|
||||
/// <see cref="IWireMockLogger.DebugRequestResponse"/>
|
||||
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest)
|
||||
{
|
||||
string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented);
|
||||
string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
|
||||
Console.WriteLine(Format("DebugRequestResponse", "Admin[{0}] {1}", isAdminRequest, message));
|
||||
}
|
||||
|
||||
|
||||
46
src/WireMock.Net.Minimal/Matchers/CompositeMatcher.cs
Normal file
46
src/WireMock.Net.Minimal/Matchers/CompositeMatcher.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a matcher that combines multiple matching strategies into a single composite operation.
|
||||
/// </summary>
|
||||
public class CompositeMatcher : IMatcher
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public string Name => nameof(CompositeMatcher);
|
||||
|
||||
/// <summary>
|
||||
/// The logical operator used to combine the results of the matchers.
|
||||
/// </summary>
|
||||
public MatchOperator MatchOperator { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public MatchBehaviour MatchBehaviour { get; }
|
||||
|
||||
/// <summary>
|
||||
/// All matchers.
|
||||
/// </summary>
|
||||
public IMatcher[] Matchers { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the CompositeMatcher class with the specified matchers, operator, and match behaviour.
|
||||
/// </summary>
|
||||
/// <param name="matchers">An array of matchers to be combined. Cannot be null or contain null elements.</param>
|
||||
/// <param name="matchOperator">The logical operator used to combine the results of the matchers.</param>
|
||||
/// <param name="matchBehaviour">The behaviour that determines how the composite matcher interprets the combined results.</param>
|
||||
public CompositeMatcher(IMatcher[] matchers, MatchOperator matchOperator, MatchBehaviour matchBehaviour)
|
||||
{
|
||||
Matchers = matchers;
|
||||
MatchOperator = matchOperator;
|
||||
MatchBehaviour = matchBehaviour;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetCSharpCodeArguments()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@ public class ContentTypeMatcher : WildcardMatcher
|
||||
{
|
||||
if (string.IsNullOrEmpty(input) || !MediaTypeHeaderValue.TryParse(input, out var contentType))
|
||||
{
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch);
|
||||
return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch));
|
||||
}
|
||||
|
||||
return base.IsMatch(contentType.MediaType);
|
||||
|
||||
@@ -75,7 +75,7 @@ public class ExactMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||
: pattern => pattern == input;
|
||||
|
||||
var score = MatchScores.ToScore(_values.Select(v => equals(v)).ToArray(), MatchOperator);
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score));
|
||||
return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -106,18 +106,18 @@ public class FormUrlEncodedMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||
// Input is null or empty and if no patterns defined, return Perfect match.
|
||||
if (string.IsNullOrEmpty(input) && _patterns.Length == 0)
|
||||
{
|
||||
return new MatchResult(MatchScores.Perfect);
|
||||
return MatchResult.From(Name, MatchScores.Perfect);
|
||||
}
|
||||
|
||||
if (!QueryStringParser.TryParse(input, IgnoreCase, out var inputNameValueCollection))
|
||||
{
|
||||
return new MatchResult(MatchScores.Mismatch);
|
||||
return MatchResult.From(Name, MatchScores.Mismatch);
|
||||
}
|
||||
|
||||
var matches = GetMatches(inputNameValueCollection);
|
||||
|
||||
var score = MatchScores.ToScore(matches, MatchOperator);
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score));
|
||||
return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score));
|
||||
}
|
||||
|
||||
private bool[] GetMatches(IDictionary<string, string> inputNameValueCollection)
|
||||
|
||||
@@ -80,7 +80,7 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher
|
||||
}
|
||||
}
|
||||
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -104,7 +104,7 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher
|
||||
}
|
||||
}
|
||||
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -87,7 +87,7 @@ public class JmesPathMatcher : IStringMatcher, IObjectMatcher
|
||||
}
|
||||
}
|
||||
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -102,7 +102,7 @@ public class JmesPathMatcher : IStringMatcher, IObjectMatcher
|
||||
return IsMatch(inputAsString);
|
||||
}
|
||||
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, score);
|
||||
return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -96,7 +96,7 @@ public class JsonMatcher : IJsonMatcher
|
||||
}
|
||||
}
|
||||
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), error);
|
||||
return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score), error);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -24,14 +24,26 @@ public class RequestMatchResult : IRequestMatchResult
|
||||
public double AverageTotalScore => TotalNumber == 0 ? MatchScores.Mismatch : TotalScore / TotalNumber;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IList<MatchDetail> MatchDetails { get; } = new List<MatchDetail>();
|
||||
public IList<MatchDetail> MatchDetails { get; } = [];
|
||||
|
||||
/// <inheritdoc />
|
||||
public double AddScore(Type matcherType, double score, Exception? exception)
|
||||
{
|
||||
MatchDetails.Add(new MatchDetail { MatcherType = matcherType, Score = score, Exception = exception });
|
||||
return AddMatchDetail(new MatchDetail
|
||||
{
|
||||
Name = matcherType.Name.Replace("RequestMessage", string.Empty),
|
||||
MatcherType = matcherType,
|
||||
Score = score,
|
||||
Exception = exception
|
||||
});
|
||||
}
|
||||
|
||||
return score;
|
||||
/// <inheritdoc />
|
||||
public double AddMatchDetail(MatchDetail matchDetail)
|
||||
{
|
||||
MatchDetails.Add(matchDetail);
|
||||
|
||||
return matchDetail.Score;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -17,27 +17,27 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
||||
/// <summary>
|
||||
/// The body function
|
||||
/// </summary>
|
||||
public Func<string?, bool>? Func { get; }
|
||||
public Func<string?, bool>? MatchOnBodyAsStringFunc { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The body data function for byte[]
|
||||
/// </summary>
|
||||
public Func<byte[]?, bool>? DataFunc { get; }
|
||||
public Func<byte[]?, bool>? MatchOnBodyAsBytesFunc { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The body data function for json
|
||||
/// </summary>
|
||||
public Func<object?, bool>? JsonFunc { get; }
|
||||
public Func<object?, bool>? MatchOnBodyAsJsonFunc { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The body data function for BodyData
|
||||
/// </summary>
|
||||
public Func<IBodyData?, bool>? BodyDataFunc { get; }
|
||||
public Func<IBodyData?, bool>? MatchOnBodyAsBodyDataFunc { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The body data function for FormUrlEncoded
|
||||
/// </summary>
|
||||
public Func<IDictionary<string, string>?, bool>? FormUrlEncodedFunc { get; }
|
||||
public Func<IDictionary<string, string>?, bool>? MatchOnBodyAsFormUrlEncodedFunc { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The matchers.
|
||||
@@ -85,7 +85,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
||||
/// <param name="func">The function.</param>
|
||||
public RequestMessageBodyMatcher(Func<string?, bool> func)
|
||||
{
|
||||
Func = Guard.NotNull(func);
|
||||
MatchOnBodyAsStringFunc = Guard.NotNull(func);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -94,7 +94,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
||||
/// <param name="func">The function.</param>
|
||||
public RequestMessageBodyMatcher(Func<byte[]?, bool> func)
|
||||
{
|
||||
DataFunc = Guard.NotNull(func);
|
||||
MatchOnBodyAsBytesFunc = Guard.NotNull(func);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -103,7 +103,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
||||
/// <param name="func">The function.</param>
|
||||
public RequestMessageBodyMatcher(Func<object?, bool> func)
|
||||
{
|
||||
JsonFunc = Guard.NotNull(func);
|
||||
MatchOnBodyAsJsonFunc = Guard.NotNull(func);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -112,7 +112,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
||||
/// <param name="func">The function.</param>
|
||||
public RequestMessageBodyMatcher(Func<IBodyData?, bool> func)
|
||||
{
|
||||
BodyDataFunc = Guard.NotNull(func);
|
||||
MatchOnBodyAsBodyDataFunc = Guard.NotNull(func);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -121,7 +121,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
||||
/// <param name="func">The function.</param>
|
||||
public RequestMessageBodyMatcher(Func<IDictionary<string, string>?, bool> func)
|
||||
{
|
||||
FormUrlEncodedFunc = Guard.NotNull(func);
|
||||
MatchOnBodyAsFormUrlEncodedFunc = Guard.NotNull(func);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -147,43 +147,43 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
||||
/// <inheritdoc />
|
||||
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
|
||||
{
|
||||
var (score, exception) = CalculateMatchScore(requestMessage).Expand();
|
||||
var (score, exception) = CalculateMatchResult(requestMessage).Expand();
|
||||
return requestMatchResult.AddScore(GetType(), score, exception);
|
||||
}
|
||||
|
||||
private MatchResult CalculateMatchScore(IRequestMessage requestMessage)
|
||||
private MatchResult CalculateMatchResult(IRequestMessage requestMessage)
|
||||
{
|
||||
if (Matchers != null && Matchers.Any())
|
||||
{
|
||||
var results = Matchers.Select(matcher => BodyDataMatchScoreCalculator.CalculateMatchScore(requestMessage.BodyData, matcher)).ToArray();
|
||||
return MatchResult.From(results, MatchOperator);
|
||||
return MatchResult.From(nameof(RequestMessageBodyMatcher), results, MatchOperator);
|
||||
}
|
||||
|
||||
if (Func != null)
|
||||
if (MatchOnBodyAsStringFunc != null)
|
||||
{
|
||||
return MatchScores.ToScore(Func(requestMessage.BodyData?.BodyAsString));
|
||||
return MatchResult.From($"{nameof(RequestMessageBodyMatcher)}:{nameof(MatchOnBodyAsStringFunc)}", MatchScores.ToScore(MatchOnBodyAsStringFunc(requestMessage.BodyData?.BodyAsString)));
|
||||
}
|
||||
|
||||
if (FormUrlEncodedFunc != null)
|
||||
if (MatchOnBodyAsFormUrlEncodedFunc != null)
|
||||
{
|
||||
return MatchScores.ToScore(FormUrlEncodedFunc(requestMessage.BodyData?.BodyAsFormUrlEncoded));
|
||||
return MatchResult.From($"{nameof(RequestMessageBodyMatcher)}:{nameof(MatchOnBodyAsFormUrlEncodedFunc)}", MatchScores.ToScore(MatchOnBodyAsFormUrlEncodedFunc(requestMessage.BodyData?.BodyAsFormUrlEncoded)));
|
||||
}
|
||||
|
||||
if (JsonFunc != null)
|
||||
if (MatchOnBodyAsJsonFunc != null)
|
||||
{
|
||||
return MatchScores.ToScore(JsonFunc(requestMessage.BodyData?.BodyAsJson));
|
||||
return MatchResult.From($"{nameof(RequestMessageBodyMatcher)}:{nameof(MatchOnBodyAsJsonFunc)}", MatchScores.ToScore(MatchOnBodyAsJsonFunc(requestMessage.BodyData?.BodyAsJson)));
|
||||
}
|
||||
|
||||
if (DataFunc != null)
|
||||
if (MatchOnBodyAsBytesFunc != null)
|
||||
{
|
||||
return MatchScores.ToScore(DataFunc(requestMessage.BodyData?.BodyAsBytes));
|
||||
return MatchResult.From($"{nameof(RequestMessageBodyMatcher)}:{nameof(MatchOnBodyAsBytesFunc)}", MatchScores.ToScore(MatchOnBodyAsBytesFunc(requestMessage.BodyData?.BodyAsBytes)));
|
||||
}
|
||||
|
||||
if (BodyDataFunc != null)
|
||||
if (MatchOnBodyAsBodyDataFunc != null)
|
||||
{
|
||||
return MatchScores.ToScore(BodyDataFunc(requestMessage.BodyData));
|
||||
return MatchResult.From($"{nameof(RequestMessageBodyMatcher)}:{nameof(MatchOnBodyAsBodyDataFunc)}", MatchScores.ToScore(MatchOnBodyAsBodyDataFunc(requestMessage.BodyData)));
|
||||
}
|
||||
|
||||
return default;
|
||||
return MatchResult.From(nameof(RequestMessageBodyMatcher));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.Matchers.Request;
|
||||
|
||||
/// <summary>
|
||||
/// The request body matcher.
|
||||
/// </summary>
|
||||
public class RequestMessageBodyMatcher<T> : IRequestMatcher
|
||||
{
|
||||
private const string _name = nameof(RequestMessageBodyMatcher<T>);
|
||||
|
||||
/// <summary>
|
||||
/// The body data function for type T
|
||||
/// </summary>
|
||||
public Func<T?, bool>? Func { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="MatchOperator"/>
|
||||
/// </summary>
|
||||
public MatchOperator MatchOperator { get; } = MatchOperator.Or;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="func">The function.</param>
|
||||
public RequestMessageBodyMatcher(Func<T?, bool> func)
|
||||
{
|
||||
Func = Guard.NotNull(func);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
|
||||
{
|
||||
var (score, exception) = CalculateMatchScore(requestMessage).Expand();
|
||||
return requestMatchResult.AddScore(GetType(), score, exception);
|
||||
}
|
||||
|
||||
private MatchResult CalculateMatchScore(IRequestMessage requestMessage)
|
||||
{
|
||||
if (Func != null)
|
||||
{
|
||||
if (requestMessage.BodyData?.BodyAsJson is JObject jsonObject)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bodyAsT = jsonObject.ToObject<T>();
|
||||
return MatchResult.From(_name, MatchScores.ToScore(Func(bodyAsT)));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return MatchResult.From(_name, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MatchResult.From(_name);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,8 @@ namespace WireMock.Matchers.Request;
|
||||
/// </summary>
|
||||
public class RequestMessageClientIPMatcher : IRequestMatcher
|
||||
{
|
||||
private const string _name = nameof(RequestMessageClientIPMatcher);
|
||||
|
||||
/// <summary>
|
||||
/// The matchers
|
||||
/// </summary>
|
||||
@@ -77,8 +79,8 @@ public class RequestMessageClientIPMatcher : IRequestMatcher
|
||||
/// <inheritdoc />
|
||||
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
|
||||
{
|
||||
var (score, exception) = GetMatchResult(requestMessage).Expand();
|
||||
return requestMatchResult.AddScore(GetType(), score, exception);
|
||||
var matchDetail = GetMatchResult(requestMessage).ToMatchDetail();
|
||||
return requestMatchResult.AddMatchDetail(matchDetail);
|
||||
}
|
||||
|
||||
private MatchResult GetMatchResult(IRequestMessage requestMessage)
|
||||
@@ -86,15 +88,15 @@ public class RequestMessageClientIPMatcher : IRequestMatcher
|
||||
if (Matchers != null)
|
||||
{
|
||||
var results = Matchers.Select(m => m.IsMatch(requestMessage.ClientIP)).ToArray();
|
||||
return MatchResult.From(results, MatchOperator);
|
||||
return MatchResult.From(_name, results, MatchOperator);
|
||||
}
|
||||
|
||||
if (Funcs != null)
|
||||
{
|
||||
var results = Funcs.Select(func => func(requestMessage.ClientIP)).ToArray();
|
||||
return MatchScores.ToScore(results, MatchOperator);
|
||||
return MatchResult.From(_name, MatchScores.ToScore(results, MatchOperator));
|
||||
}
|
||||
|
||||
return default;
|
||||
return MatchResult.From(_name);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,8 @@ namespace WireMock.Matchers.Request;
|
||||
/// <inheritdoc cref="IRequestMatcher"/>
|
||||
public class RequestMessageCookieMatcher : IRequestMatcher
|
||||
{
|
||||
private const string _name = nameof(RequestMessageCookieMatcher);
|
||||
|
||||
/// <summary>
|
||||
/// MatchBehaviour
|
||||
/// </summary>
|
||||
@@ -104,7 +106,7 @@ public class RequestMessageCookieMatcher : IRequestMatcher
|
||||
{
|
||||
if (requestMessage.Cookies == null)
|
||||
{
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch);
|
||||
return MatchResult.From(_name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch));
|
||||
}
|
||||
|
||||
// Check if we want to use IgnoreCase to compare the Cookie-Name and Cookie-Value
|
||||
@@ -112,19 +114,19 @@ public class RequestMessageCookieMatcher : IRequestMatcher
|
||||
|
||||
if (Funcs != null)
|
||||
{
|
||||
return MatchScores.ToScore(Funcs.Any(f => f(cookies)));
|
||||
return MatchResult.From(_name, MatchScores.ToScore(Funcs.Any(f => f(cookies))));
|
||||
}
|
||||
|
||||
if (Matchers == null)
|
||||
{
|
||||
return default;
|
||||
return MatchResult.From(_name);
|
||||
}
|
||||
|
||||
if (!cookies.ContainsKey(Name))
|
||||
{
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch);
|
||||
return MatchResult.From(_name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch));
|
||||
}
|
||||
|
||||
return Matchers.Max(m => m.IsMatch(cookies[Name]));
|
||||
return MatchResult.From(_name, Matchers.Max(m => m.IsMatch(cookies[Name]))?.Score ?? MatchScores.Mismatch);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,8 @@ namespace WireMock.Matchers.Request;
|
||||
/// <inheritdoc cref="IRequestMatcher"/>
|
||||
public class RequestMessageHeaderMatcher : IRequestMatcher
|
||||
{
|
||||
private const string _name = nameof(RequestMessageCookieMatcher);
|
||||
|
||||
/// <summary>
|
||||
/// MatchBehaviour
|
||||
/// </summary>
|
||||
@@ -117,7 +119,7 @@ public class RequestMessageHeaderMatcher : IRequestMatcher
|
||||
{
|
||||
if (requestMessage.Headers == null)
|
||||
{
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch);
|
||||
return MatchResult.From(_name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch));
|
||||
}
|
||||
|
||||
// Check if we want to use IgnoreCase to compare the Header-Name and Header-Value(s)
|
||||
@@ -126,14 +128,14 @@ public class RequestMessageHeaderMatcher : IRequestMatcher
|
||||
if (Funcs != null)
|
||||
{
|
||||
var funcResults = Funcs.Select(f => f(headers.ToDictionary(entry => entry.Key, entry => entry.Value.ToArray()))).ToArray();
|
||||
return MatchScores.ToScore(funcResults, MatchOperator);
|
||||
return MatchResult.From(_name, MatchScores.ToScore(funcResults, MatchOperator));
|
||||
}
|
||||
|
||||
if (Matchers != null)
|
||||
{
|
||||
if (!headers.ContainsKey(Name))
|
||||
{
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch);
|
||||
return MatchResult.From(_name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch));
|
||||
}
|
||||
|
||||
var results = new List<MatchResult>();
|
||||
@@ -141,12 +143,12 @@ public class RequestMessageHeaderMatcher : IRequestMatcher
|
||||
{
|
||||
var resultsPerMatcher = headers[Name].Select(matcher.IsMatch).ToArray();
|
||||
|
||||
results.Add(MatchResult.From(resultsPerMatcher, MatchOperator.And));
|
||||
results.Add(MatchResult.From(_name, resultsPerMatcher, MatchOperator.And));
|
||||
}
|
||||
|
||||
return MatchResult.From(results, MatchOperator);
|
||||
return MatchResult.From(_name, results, MatchOperator);
|
||||
}
|
||||
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch);
|
||||
return MatchResult.From(_name, MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch));
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ namespace WireMock.Matchers.Request;
|
||||
/// </summary>
|
||||
public class RequestMessageHttpVersionMatcher : IRequestMatcher
|
||||
{
|
||||
private const string _name = nameof(RequestMessageHttpVersionMatcher);
|
||||
|
||||
/// <summary>
|
||||
/// The matcher.
|
||||
/// </summary>
|
||||
@@ -19,7 +21,7 @@ public class RequestMessageHttpVersionMatcher : IRequestMatcher
|
||||
/// <summary>
|
||||
/// The func.
|
||||
/// </summary>
|
||||
public Func<string, bool>? Func { get; }
|
||||
public Func<string, bool>? MatcherOnStringFunc { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="MatchBehaviour"/>
|
||||
@@ -61,7 +63,7 @@ public class RequestMessageHttpVersionMatcher : IRequestMatcher
|
||||
/// <param name="func">The function.</param>
|
||||
public RequestMessageHttpVersionMatcher(Func<string, bool> func)
|
||||
{
|
||||
Func = Guard.NotNull(func);
|
||||
MatcherOnStringFunc = Guard.NotNull(func);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -78,11 +80,11 @@ public class RequestMessageHttpVersionMatcher : IRequestMatcher
|
||||
return Matcher.IsMatch(requestMessage.HttpVersion);
|
||||
}
|
||||
|
||||
if (Func != null)
|
||||
if (MatcherOnStringFunc != null)
|
||||
{
|
||||
return MatchScores.ToScore(Func(requestMessage.HttpVersion));
|
||||
return MatchResult.From($"{_name}:{nameof(MatcherOnStringFunc)}", MatchScores.ToScore(MatcherOnStringFunc(requestMessage.HttpVersion)));
|
||||
}
|
||||
|
||||
return default;
|
||||
return MatchResult.From(_name);
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,12 @@ namespace WireMock.Matchers.Request;
|
||||
/// </summary>
|
||||
public class RequestMessageMultiPartMatcher : IRequestMatcher
|
||||
{
|
||||
private static readonly IMimeKitUtils MimeKitUtils = TypeLoader.LoadStaticInstance<IMimeKitUtils>();
|
||||
/// <summary>
|
||||
/// The name of this matcher.
|
||||
/// </summary>
|
||||
public const string Name = "MultiPartMatcher";
|
||||
|
||||
private readonly IMimeKitUtils _mimeKitUtils = LoadMimeKitUtils();
|
||||
|
||||
/// <summary>
|
||||
/// The matchers.
|
||||
@@ -22,7 +27,7 @@ public class RequestMessageMultiPartMatcher : IRequestMatcher
|
||||
/// <summary>
|
||||
/// The <see cref="MatchOperator"/>
|
||||
/// </summary>
|
||||
public MatchOperator MatchOperator { get; } = MatchOperator.Or;
|
||||
public MatchOperator MatchOperator { get; } = MatchOperator.And;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="MatchBehaviour"/>
|
||||
@@ -54,19 +59,20 @@ public class RequestMessageMultiPartMatcher : IRequestMatcher
|
||||
/// <inheritdoc />
|
||||
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
|
||||
{
|
||||
var score = MatchScores.Mismatch;
|
||||
var matchDetail = MatchResult.From(Name).ToMatchDetail();
|
||||
Exception? exception = null;
|
||||
|
||||
if (Matchers?.Any() != true)
|
||||
if (Matchers == null)
|
||||
{
|
||||
return requestMatchResult.AddScore(GetType(), score, null);
|
||||
return requestMatchResult.AddMatchDetail(matchDetail);
|
||||
}
|
||||
|
||||
if (!MimeKitUtils.TryGetMimeMessage(requestMessage, out var message))
|
||||
if (!_mimeKitUtils.TryGetMimeMessage(requestMessage, out var message))
|
||||
{
|
||||
return requestMatchResult.AddScore(GetType(), score, null);
|
||||
return requestMatchResult.AddMatchDetail(matchDetail);
|
||||
}
|
||||
|
||||
double score = MatchScores.Mismatch;
|
||||
try
|
||||
{
|
||||
foreach (var mimePartMatcher in Matchers.OfType<IMimePartMatcher>().ToArray())
|
||||
@@ -94,6 +100,16 @@ public class RequestMessageMultiPartMatcher : IRequestMatcher
|
||||
exception = ex;
|
||||
}
|
||||
|
||||
return requestMatchResult.AddScore(GetType(), score, exception);
|
||||
return requestMatchResult.AddMatchDetail(MatchResult.From(Name, score, exception).ToMatchDetail());
|
||||
}
|
||||
|
||||
private static IMimeKitUtils LoadMimeKitUtils()
|
||||
{
|
||||
if (TypeLoader.TryLoadStaticInstance<IMimeKitUtils>(out var mimeKitUtils))
|
||||
{
|
||||
return mimeKitUtils;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("MimeKit is required for RequestMessageMultiPartMatcher. Please install the WireMock.Net.MimePart package.");
|
||||
}
|
||||
}
|
||||
@@ -77,8 +77,8 @@ public class RequestMessagePathMatcher : IRequestMatcher
|
||||
/// <inheritdoc />
|
||||
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
|
||||
{
|
||||
var (score, exception) = GetMatchResult(requestMessage).Expand();
|
||||
return requestMatchResult.AddScore(GetType(), score, exception);
|
||||
var matchDetail = GetMatchResult(requestMessage).ToMatchDetail();
|
||||
return requestMatchResult.AddMatchDetail(matchDetail);
|
||||
}
|
||||
|
||||
private MatchResult GetMatchResult(IRequestMessage requestMessage)
|
||||
@@ -86,15 +86,16 @@ public class RequestMessagePathMatcher : IRequestMatcher
|
||||
if (Matchers != null)
|
||||
{
|
||||
var results = Matchers.Select(m => m.IsMatch(requestMessage.Path)).ToArray();
|
||||
return MatchResult.From(results, MatchOperator);
|
||||
return MatchResult.From(nameof(RequestMessagePathMatcher), results, MatchOperator);
|
||||
}
|
||||
|
||||
if (Funcs != null)
|
||||
{
|
||||
var results = Funcs.Select(func => func(requestMessage.Path)).ToArray();
|
||||
return MatchScores.ToScore(results, MatchOperator);
|
||||
var score = MatchScores.ToScore(results, MatchOperator);
|
||||
return MatchResult.From(nameof(RequestMessagePathMatcher), score);
|
||||
}
|
||||
|
||||
return default;
|
||||
return MatchResult.From(nameof(RequestMessagePathMatcher));
|
||||
}
|
||||
}
|
||||
@@ -86,15 +86,16 @@ public class RequestMessageUrlMatcher : IRequestMatcher
|
||||
if (Matchers != null)
|
||||
{
|
||||
var results = Matchers.Select(m => m.IsMatch(requestMessage.Url)).ToArray();
|
||||
return MatchResult.From(results, MatchOperator);
|
||||
return MatchResult.From(nameof(RequestMessageUrlMatcher), results, MatchOperator);
|
||||
}
|
||||
|
||||
if (Funcs != null)
|
||||
{
|
||||
var results = Funcs.Select(func => func(requestMessage.Url)).ToArray();
|
||||
return MatchScores.ToScore(results, MatchOperator);
|
||||
var score = MatchScores.ToScore(results, MatchOperator);
|
||||
return MatchResult.From(nameof(RequestMessageUrlMatcher), score);
|
||||
}
|
||||
|
||||
return default;
|
||||
return MatchResult.From(nameof(RequestMessageUrlMatcher));
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,7 @@ public class SimMetricsMatcher : IStringMatcher
|
||||
IStringMetric stringMetricType = GetStringMetricType();
|
||||
|
||||
var score = MatchScores.ToScore(_patterns.Select(p => stringMetricType.GetSimilarity(p.GetPattern(), input)).ToArray(), MatchOperator);
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, score);
|
||||
return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -116,7 +116,7 @@ public class XPathMatcher : IStringMatcher
|
||||
|
||||
private MatchResult CreateMatchResult(double score, Exception? exception = null)
|
||||
{
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
return MatchResult.From(Name, MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
}
|
||||
|
||||
private sealed class XPathEvaluator
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
#if ACTIVITY_TRACING_SUPPORTED
|
||||
|
||||
namespace WireMock.Owin.ActivityTracing;
|
||||
|
||||
/// <summary>
|
||||
/// Options for controlling activity tracing in WireMock.Net middleware.
|
||||
/// These options control the creation of System.Diagnostics.Activity objects
|
||||
/// but do not require any OpenTelemetry exporter dependencies.
|
||||
/// </summary>
|
||||
public class ActivityTracingOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to exclude admin interface requests from tracing.
|
||||
/// Default is <c>true</c>.
|
||||
/// </summary>
|
||||
public bool ExcludeAdminRequests { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to record request body in trace attributes.
|
||||
/// Default is <c>false</c> due to potential PII concerns.
|
||||
/// </summary>
|
||||
public bool RecordRequestBody { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to record response body in trace attributes.
|
||||
/// Default is <c>false</c> due to potential PII concerns.
|
||||
/// </summary>
|
||||
public bool RecordResponseBody { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to record mapping match details in trace attributes.
|
||||
/// Default is <c>true</c>.
|
||||
/// </summary>
|
||||
public bool RecordMatchDetails { get; set; } = true;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
#if !ACTIVITY_TRACING_SUPPORTED
|
||||
using System;
|
||||
#endif
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.Owin.ActivityTracing;
|
||||
|
||||
/// <summary>
|
||||
/// Validator for Activity Tracing configuration.
|
||||
/// </summary>
|
||||
internal static class ActivityTracingValidator
|
||||
{
|
||||
/// <summary>
|
||||
/// Validates that Activity Tracing is supported on the current framework.
|
||||
/// Throws an exception if ActivityTracingOptions is configured on an unsupported framework.
|
||||
/// </summary>
|
||||
/// <param name="settings">The WireMock server settings to validate.</param>
|
||||
/// <exception cref="System.InvalidOperationException">
|
||||
/// Thrown when ActivityTracingOptions is configured but the current framework does not support System.Diagnostics.Activity.
|
||||
/// </exception>
|
||||
public static void ValidateActivityApiPresence(WireMockServerSettings settings)
|
||||
{
|
||||
#if !ACTIVITY_TRACING_SUPPORTED
|
||||
if (settings.ActivityTracingOptions is not null)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Activity Tracing is not supported on this target framework. " +
|
||||
"It requires .NET 5.0 or higher which includes System.Diagnostics.Activity support.");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
#if ACTIVITY_TRACING_SUPPORTED
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using WireMock.Logging;
|
||||
|
||||
namespace WireMock.Owin.ActivityTracing;
|
||||
|
||||
/// <summary>
|
||||
/// Provides an ActivitySource for WireMock.Net distributed tracing.
|
||||
/// </summary>
|
||||
public static class WireMockActivitySource
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the ActivitySource used by WireMock.Net.
|
||||
/// </summary>
|
||||
internal const string SourceName = "WireMock.Net";
|
||||
|
||||
/// <summary>
|
||||
/// The ActivitySource instance used for creating tracing activities.
|
||||
/// </summary>
|
||||
public static readonly ActivitySource Source = new(SourceName, GetVersion());
|
||||
|
||||
private static string GetVersion()
|
||||
{
|
||||
return typeof(WireMockActivitySource).Assembly.GetName().Version?.ToString() ?? "1.0.0";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts a new activity for a WireMock request.
|
||||
/// </summary>
|
||||
/// <param name="requestMethod">The HTTP method of the request.</param>
|
||||
/// <param name="requestPath">The path of the request.</param>
|
||||
/// <returns>The started activity, or null if tracing is not enabled.</returns>
|
||||
internal static Activity? StartRequestActivity(string requestMethod, string requestPath)
|
||||
{
|
||||
if (!Source.HasListeners())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var activity = Source.StartActivity(
|
||||
$"WireMock {requestMethod} {requestPath}",
|
||||
ActivityKind.Server
|
||||
);
|
||||
|
||||
return activity;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enriches an activity with request information.
|
||||
/// </summary>
|
||||
internal static void EnrichWithRequest(Activity? activity, IRequestMessage request, ActivityTracingOptions? options = null)
|
||||
{
|
||||
if (activity == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
activity.SetTag(WireMockSemanticConventions.HttpMethod, request.Method);
|
||||
activity.SetTag(WireMockSemanticConventions.HttpUrl, request.Url);
|
||||
activity.SetTag(WireMockSemanticConventions.HttpPath, request.Path);
|
||||
activity.SetTag(WireMockSemanticConventions.HttpHost, request.Host);
|
||||
|
||||
if (request.ClientIP != null)
|
||||
{
|
||||
activity.SetTag(WireMockSemanticConventions.ClientAddress, request.ClientIP);
|
||||
}
|
||||
|
||||
// Record request body if enabled
|
||||
if (options?.RecordRequestBody == true && request.Body != null)
|
||||
{
|
||||
activity.SetTag(WireMockSemanticConventions.RequestBody, request.Body);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enriches an activity with response information.
|
||||
/// </summary>
|
||||
internal static void EnrichWithResponse(Activity? activity, IResponseMessage? response, ActivityTracingOptions? options = null)
|
||||
{
|
||||
if (activity == null || response == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// StatusCode can be int, HttpStatusCode, or string
|
||||
var statusCode = response.StatusCode;
|
||||
int? statusCodeInt = statusCode switch
|
||||
{
|
||||
int i => i,
|
||||
System.Net.HttpStatusCode hsc => (int)hsc,
|
||||
string s when int.TryParse(s, out var parsed) => parsed,
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (statusCodeInt.HasValue)
|
||||
{
|
||||
activity.SetTag(WireMockSemanticConventions.HttpStatusCode, statusCodeInt.Value);
|
||||
activity.SetTag("otel.status_description", $"HTTP {statusCodeInt.Value}");
|
||||
|
||||
// Set status based on HTTP status code (using standard otel.status_code tag)
|
||||
if (statusCodeInt.Value >= 400)
|
||||
{
|
||||
activity.SetTag("otel.status_code", "ERROR");
|
||||
}
|
||||
else
|
||||
{
|
||||
activity.SetTag("otel.status_code", "OK");
|
||||
}
|
||||
}
|
||||
|
||||
// Record response body if enabled
|
||||
if (options?.RecordResponseBody == true && response.BodyData?.BodyAsString != null)
|
||||
{
|
||||
activity.SetTag(WireMockSemanticConventions.ResponseBody, response.BodyData.BodyAsString);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enriches an activity with mapping match information.
|
||||
/// </summary>
|
||||
internal static void EnrichWithMappingMatch(
|
||||
Activity? activity,
|
||||
Guid? mappingGuid,
|
||||
string? mappingTitle,
|
||||
bool isPerfectMatch,
|
||||
double? matchScore)
|
||||
{
|
||||
if (activity == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
activity.SetTag(WireMockSemanticConventions.MappingMatched, isPerfectMatch);
|
||||
|
||||
if (mappingGuid.HasValue)
|
||||
{
|
||||
activity.SetTag(WireMockSemanticConventions.MappingGuid, mappingGuid.Value.ToString());
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(mappingTitle))
|
||||
{
|
||||
activity.SetTag(WireMockSemanticConventions.MappingTitle, mappingTitle);
|
||||
}
|
||||
|
||||
if (matchScore.HasValue)
|
||||
{
|
||||
activity.SetTag(WireMockSemanticConventions.MatchScore, matchScore.Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enriches an activity with log entry information (includes response and mapping match info).
|
||||
/// </summary>
|
||||
internal static void EnrichWithLogEntry(Activity? activity, ILogEntry logEntry, ActivityTracingOptions? options = null)
|
||||
{
|
||||
if (activity == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Enrich with response
|
||||
EnrichWithResponse(activity, logEntry.ResponseMessage, options);
|
||||
|
||||
// Enrich with mapping match (if enabled)
|
||||
if (options?.RecordMatchDetails != false)
|
||||
{
|
||||
EnrichWithMappingMatch(
|
||||
activity,
|
||||
logEntry.MappingGuid,
|
||||
logEntry.MappingTitle,
|
||||
logEntry.RequestMatchResult?.IsPerfectMatch ?? false,
|
||||
logEntry.RequestMatchResult?.TotalScore);
|
||||
}
|
||||
|
||||
// Set request GUID
|
||||
activity.SetTag(WireMockSemanticConventions.RequestGuid, logEntry.Guid.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Records an exception on the activity.
|
||||
/// </summary>
|
||||
internal static void RecordException(Activity? activity, Exception exception)
|
||||
{
|
||||
if (activity == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Use standard OpenTelemetry exception semantic conventions
|
||||
activity.SetTag("otel.status_code", "ERROR");
|
||||
activity.SetTag("otel.status_description", exception.Message);
|
||||
activity.SetTag("exception.type", exception.GetType().FullName);
|
||||
activity.SetTag("exception.message", exception.Message);
|
||||
activity.SetTag("exception.stacktrace", exception.ToString());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
namespace WireMock.Owin.ActivityTracing;
|
||||
|
||||
/// <summary>
|
||||
/// Semantic convention constants for WireMock.Net tracing attributes.
|
||||
/// </summary>
|
||||
internal static class WireMockSemanticConventions
|
||||
{
|
||||
// Standard HTTP semantic conventions (OpenTelemetry)
|
||||
public const string HttpMethod = "http.request.method";
|
||||
public const string HttpUrl = "url.full";
|
||||
public const string HttpPath = "url.path";
|
||||
public const string HttpHost = "server.address";
|
||||
public const string HttpStatusCode = "http.response.status_code";
|
||||
public const string ClientAddress = "client.address";
|
||||
|
||||
// WireMock-specific attributes
|
||||
public const string MappingMatched = "wiremock.mapping.matched";
|
||||
public const string MappingGuid = "wiremock.mapping.guid";
|
||||
public const string MappingTitle = "wiremock.mapping.title";
|
||||
public const string MatchScore = "wiremock.match.score";
|
||||
public const string PartialMappingGuid = "wiremock.partial_mapping.guid";
|
||||
public const string PartialMappingTitle = "wiremock.partial_mapping.title";
|
||||
public const string RequestGuid = "wiremock.request.guid";
|
||||
public const string RequestBody = "wiremock.request.body";
|
||||
public const string ResponseBody = "wiremock.response.body";
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Concurrent;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Owin.ActivityTracing;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
@@ -90,4 +91,12 @@ internal interface IWireMockMiddlewareOptions
|
||||
QueryParameterMultipleValueSupport? QueryParameterMultipleValueSupport { get; set; }
|
||||
|
||||
public bool ProxyAll { get; set; }
|
||||
|
||||
#if ACTIVITY_TRACING_SUPPORTED
|
||||
/// <summary>
|
||||
/// Gets or sets the activity tracing options.
|
||||
/// When set, System.Diagnostics.Activity objects are created for request tracing.
|
||||
/// </summary>
|
||||
ActivityTracingOptions? ActivityTracingOptions { get; set; }
|
||||
#endif
|
||||
}
|
||||
@@ -178,9 +178,12 @@ namespace WireMock.Owin.Mappers
|
||||
return (bodyData.Encoding ?? _utf8NoBom).GetBytes(jsonBody);
|
||||
|
||||
case BodyType.ProtoBuf:
|
||||
var protoDefinitions = bodyData.ProtoDefinition?.Invoke().Texts;
|
||||
var protoBufUtils = TypeLoader.LoadStaticInstance<IProtoBufUtils>();
|
||||
return await protoBufUtils.GetProtoBufMessageWithHeaderAsync(protoDefinitions, bodyData.ProtoBufMessageType, bodyData.BodyAsJson).ConfigureAwait(false);
|
||||
if (TypeLoader.TryLoadStaticInstance<IProtoBufUtils>(out var protoBufUtils))
|
||||
{
|
||||
var protoDefinitions = bodyData.ProtoDefinition?.Invoke().Texts;
|
||||
return await protoBufUtils.GetProtoBufMessageWithHeaderAsync(protoDefinitions, bodyData.ProtoBufMessageType, bodyData.BodyAsJson).ConfigureAwait(false);
|
||||
}
|
||||
break;
|
||||
|
||||
case BodyType.Bytes:
|
||||
return bodyData.BodyAsBytes;
|
||||
|
||||
@@ -9,16 +9,10 @@ using WireMock.Services;
|
||||
|
||||
namespace WireMock.Owin;
|
||||
|
||||
internal class MappingMatcher : IMappingMatcher
|
||||
internal class MappingMatcher(IWireMockMiddlewareOptions options, IRandomizerDoubleBetween0And1 randomizerDoubleBetween0And1) : IMappingMatcher
|
||||
{
|
||||
private readonly IWireMockMiddlewareOptions _options;
|
||||
private readonly IRandomizerDoubleBetween0And1 _randomizerDoubleBetween0And1;
|
||||
|
||||
public MappingMatcher(IWireMockMiddlewareOptions options, IRandomizerDoubleBetween0And1 randomizerDoubleBetween0And1)
|
||||
{
|
||||
_options = Guard.NotNull(options);
|
||||
_randomizerDoubleBetween0And1 = Guard.NotNull(randomizerDoubleBetween0And1);
|
||||
}
|
||||
private readonly IWireMockMiddlewareOptions _options = Guard.NotNull(options);
|
||||
private readonly IRandomizerDoubleBetween0And1 _randomizerDoubleBetween0And1 = Guard.NotNull(randomizerDoubleBetween0And1);
|
||||
|
||||
public (MappingMatcherResult? Match, MappingMatcherResult? Partial) FindBestMatch(RequestMessage request)
|
||||
{
|
||||
@@ -28,7 +22,7 @@ internal class MappingMatcher : IMappingMatcher
|
||||
|
||||
var mappings = _options.Mappings.Values
|
||||
.Where(m => m.TimeSettings.IsValid())
|
||||
.Where(m => m.Probability is null || m.Probability <= _randomizerDoubleBetween0And1.Generate())
|
||||
.Where(m => m.Probability is null || _randomizerDoubleBetween0And1.Generate() <= m.Probability)
|
||||
.ToArray();
|
||||
|
||||
foreach (var mapping in mappings)
|
||||
@@ -41,10 +35,10 @@ internal class MappingMatcher : IMappingMatcher
|
||||
|
||||
var exceptions = mappingMatcherResult.RequestMatchResult.MatchDetails
|
||||
.Where(md => md.Exception != null)
|
||||
.Select(md => md.Exception)
|
||||
.Select(md => md.Exception!)
|
||||
.ToArray();
|
||||
|
||||
if (!exceptions.Any())
|
||||
if (exceptions.Length == 0)
|
||||
{
|
||||
possibleMappings.Add(mappingMatcherResult);
|
||||
}
|
||||
@@ -52,7 +46,7 @@ internal class MappingMatcher : IMappingMatcher
|
||||
{
|
||||
foreach (var ex in exceptions)
|
||||
{
|
||||
LogException(mapping, ex!);
|
||||
LogException(mapping, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,14 +56,16 @@ internal class MappingMatcher : IMappingMatcher
|
||||
}
|
||||
}
|
||||
|
||||
var partialMappings = possibleMappings
|
||||
var partialMatches = possibleMappings
|
||||
.Where(pm => (pm.Mapping.IsAdminInterface && pm.RequestMatchResult.IsPerfectMatch) || !pm.Mapping.IsAdminInterface)
|
||||
.OrderBy(m => m.RequestMatchResult)
|
||||
.ThenBy(m => m.RequestMatchResult.TotalNumber)
|
||||
.ThenBy(m => m.Mapping.Priority)
|
||||
.ThenByDescending(m => m.Mapping.Probability)
|
||||
.ThenByDescending(m => m.Mapping.UpdatedAt)
|
||||
.ToList();
|
||||
var partialMatch = partialMappings.FirstOrDefault(pm => pm.RequestMatchResult.AverageTotalScore > 0.0);
|
||||
.Where(pm => pm.RequestMatchResult.AverageTotalScore > 0.0)
|
||||
.ToArray();
|
||||
var partialMatch = partialMatches.FirstOrDefault();
|
||||
|
||||
if (_options.AllowPartialMapping == true)
|
||||
{
|
||||
@@ -78,7 +74,11 @@ internal class MappingMatcher : IMappingMatcher
|
||||
|
||||
var match = possibleMappings
|
||||
.Where(m => m.RequestMatchResult.IsPerfectMatch)
|
||||
.OrderBy(m => m.Mapping.Priority).ThenBy(m => m.RequestMatchResult).ThenByDescending(m => m.Mapping.UpdatedAt)
|
||||
.OrderBy(m => m.Mapping.Priority)
|
||||
.ThenBy(m => m.RequestMatchResult)
|
||||
.ThenBy(m => m.RequestMatchResult.TotalNumber)
|
||||
.ThenByDescending(m => m.Mapping.Probability)
|
||||
.ThenByDescending(m => m.Mapping.UpdatedAt)
|
||||
.FirstOrDefault();
|
||||
|
||||
return (match, partialMatch);
|
||||
|
||||
@@ -16,6 +16,10 @@ using System.Collections.Generic;
|
||||
using WireMock.Constants;
|
||||
using WireMock.Exceptions;
|
||||
using WireMock.Util;
|
||||
#if ACTIVITY_TRACING_SUPPORTED
|
||||
using System.Diagnostics;
|
||||
using WireMock.Owin.ActivityTracing;
|
||||
#endif
|
||||
#if !USE_ASPNETCORE
|
||||
using IContext = Microsoft.Owin.IOwinContext;
|
||||
using OwinMiddleware = Microsoft.Owin.OwinMiddleware;
|
||||
@@ -97,6 +101,40 @@ namespace WireMock.Owin
|
||||
{
|
||||
var request = await _requestMapper.MapAsync(ctx.Request, _options).ConfigureAwait(false);
|
||||
|
||||
#if ACTIVITY_TRACING_SUPPORTED
|
||||
// Start activity if ActivityTracingOptions is configured
|
||||
var tracingEnabled = _options.ActivityTracingOptions is not null;
|
||||
var excludeAdmin = _options.ActivityTracingOptions?.ExcludeAdminRequests ?? true;
|
||||
Activity? activity = null;
|
||||
|
||||
// Check if we should trace this request (optionally exclude admin requests)
|
||||
var shouldTrace = tracingEnabled && !(excludeAdmin && request.Path.StartsWith("/__admin/"));
|
||||
|
||||
if (shouldTrace)
|
||||
{
|
||||
activity = WireMockActivitySource.StartRequestActivity(request.Method, request.Path);
|
||||
WireMockActivitySource.EnrichWithRequest(activity, request, _options.ActivityTracingOptions);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await InvokeInternalCoreAsync(ctx, request, activity).ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
activity?.Dispose();
|
||||
}
|
||||
#else
|
||||
await InvokeInternalCoreAsync(ctx, request).ConfigureAwait(false);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ACTIVITY_TRACING_SUPPORTED
|
||||
private async Task InvokeInternalCoreAsync(IContext ctx, RequestMessage request, Activity? activity)
|
||||
#else
|
||||
private async Task InvokeInternalCoreAsync(IContext ctx, RequestMessage request)
|
||||
#endif
|
||||
{
|
||||
var logRequest = false;
|
||||
IResponseMessage? response = null;
|
||||
(MappingMatcherResult? Match, MappingMatcherResult? Partial) result = (null, null);
|
||||
@@ -193,6 +231,10 @@ namespace WireMock.Owin
|
||||
{
|
||||
_options.Logger.Error($"Providing a Response for Mapping '{result.Match?.Mapping.Guid}' failed. HttpStatusCode set to 500. Exception: {ex}");
|
||||
response = ResponseMessageBuilder.Create(500, ex.Message);
|
||||
|
||||
#if ACTIVITY_TRACING_SUPPORTED
|
||||
WireMockActivitySource.RecordException(activity, ex);
|
||||
#endif
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -211,6 +253,11 @@ namespace WireMock.Owin
|
||||
PartialMatchResult = result.Partial?.RequestMatchResult
|
||||
};
|
||||
|
||||
#if ACTIVITY_TRACING_SUPPORTED
|
||||
// Enrich activity with response and mapping info
|
||||
WireMockActivitySource.EnrichWithLogEntry(activity, log, _options.ActivityTracingOptions);
|
||||
#endif
|
||||
|
||||
LogRequest(log, logRequest);
|
||||
|
||||
try
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Concurrent;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Owin.ActivityTracing;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
@@ -106,4 +107,9 @@ internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool ProxyAll { get; set; }
|
||||
|
||||
#if ACTIVITY_TRACING_SUPPORTED
|
||||
/// <inheritdoc />
|
||||
public ActivityTracingOptions? ActivityTracingOptions { get; set; }
|
||||
#endif
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using Stef.Validation;
|
||||
using WireMock.Owin.ActivityTracing;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.Owin;
|
||||
@@ -34,6 +35,27 @@ internal static class WireMockMiddlewareOptionsHelper
|
||||
options.RequestLogExpirationDuration = settings.RequestLogExpirationDuration;
|
||||
options.SaveUnmatchedRequests = settings.SaveUnmatchedRequests;
|
||||
|
||||
// Validate and configure activity tracing
|
||||
ActivityTracingValidator.ValidateActivityApiPresence(settings);
|
||||
#if ACTIVITY_TRACING_SUPPORTED
|
||||
if (settings.ActivityTracingOptions is not null)
|
||||
{
|
||||
options.ActivityTracingOptions = new Owin.ActivityTracing.ActivityTracingOptions
|
||||
{
|
||||
ExcludeAdminRequests = settings.ActivityTracingOptions.ExcludeAdminRequests,
|
||||
RecordRequestBody = settings.ActivityTracingOptions.RecordRequestBody,
|
||||
RecordResponseBody = settings.ActivityTracingOptions.RecordResponseBody,
|
||||
RecordMatchDetails = settings.ActivityTracingOptions.RecordMatchDetails
|
||||
};
|
||||
}
|
||||
#endif
|
||||
#if USE_ASPNETCORE
|
||||
options.AdditionalServiceRegistration = settings.AdditionalServiceRegistration;
|
||||
options.CorsPolicyOptions = settings.CorsPolicyOptions;
|
||||
options.ClientCertificateMode = settings.ClientCertificateMode;
|
||||
options.AcceptAnyClientCertificate = settings.AcceptAnyClientCertificate;
|
||||
#endif
|
||||
|
||||
if (settings.CustomCertificateDefined)
|
||||
{
|
||||
options.X509StoreName = settings.CertificateSettings!.X509StoreName;
|
||||
|
||||
@@ -13,16 +13,10 @@ using WireMock.Util;
|
||||
|
||||
namespace WireMock.Proxy;
|
||||
|
||||
internal class ProxyHelper
|
||||
internal class ProxyHelper(WireMockServerSettings settings)
|
||||
{
|
||||
private readonly WireMockServerSettings _settings;
|
||||
private readonly ProxyMappingConverter _proxyMappingConverter;
|
||||
|
||||
public ProxyHelper(WireMockServerSettings settings)
|
||||
{
|
||||
_settings = Guard.NotNull(settings);
|
||||
_proxyMappingConverter = new ProxyMappingConverter(settings, new GuidUtils(), new DateTimeUtils());
|
||||
}
|
||||
private readonly WireMockServerSettings _settings = Guard.NotNull(settings);
|
||||
private readonly ProxyMappingConverter _proxyMappingConverter = new(settings, new GuidUtils(), new DateTimeUtils());
|
||||
|
||||
public async Task<(IResponseMessage Message, IMapping? Mapping)> SendAsync(
|
||||
IMapping? mapping,
|
||||
@@ -39,18 +33,7 @@ internal class ProxyHelper
|
||||
var requiredUri = new Uri(url);
|
||||
|
||||
// Create HttpRequestMessage
|
||||
var replaceSettings = proxyAndRecordSettings.ReplaceSettings;
|
||||
string proxyUrl;
|
||||
if (replaceSettings is not null)
|
||||
{
|
||||
var stringComparison = replaceSettings.IgnoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
|
||||
proxyUrl = url.Replace(replaceSettings.OldValue, replaceSettings.NewValue, stringComparison);
|
||||
}
|
||||
else
|
||||
{
|
||||
proxyUrl = url;
|
||||
}
|
||||
|
||||
var proxyUrl = proxyAndRecordSettings.ReplaceSettings != null ? ProxyUrlTransformer.Transform(_settings, proxyAndRecordSettings.ReplaceSettings, url) : url;
|
||||
var httpRequestMessage = HttpRequestMessageHelper.Create(requestMessage, proxyUrl);
|
||||
|
||||
// Call the URL
|
||||
|
||||
21
src/WireMock.Net.Minimal/Proxy/ProxyUrlTransformer.cs
Normal file
21
src/WireMock.Net.Minimal/Proxy/ProxyUrlTransformer.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Transformers;
|
||||
|
||||
namespace WireMock.Proxy;
|
||||
|
||||
internal static class ProxyUrlTransformer
|
||||
{
|
||||
internal static string Transform(WireMockServerSettings settings, ProxyUrlReplaceSettings replaceSettings, string url)
|
||||
{
|
||||
if (!replaceSettings.UseTransformer)
|
||||
{
|
||||
return url.Replace(replaceSettings.OldValue, replaceSettings.NewValue, replaceSettings.IgnoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
var transformer = TransformerFactory.Create(replaceSettings.TransformerType, settings);
|
||||
return transformer.Transform(replaceSettings.TransformTemplate, url);
|
||||
}
|
||||
}
|
||||
@@ -34,13 +34,6 @@ public partial class Request
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithBodyAsJson(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
var matcher = body as IMatcher ?? new JsonMatcher(matchBehaviour, body);
|
||||
return WithBody([matcher]);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithBody(IMatcher matcher)
|
||||
{
|
||||
@@ -98,4 +91,20 @@ public partial class Request
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(Guard.NotNull(func)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithBodyAsJson(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
var matcher = body as IMatcher ?? new JsonMatcher(matchBehaviour, body);
|
||||
return WithBody([matcher]);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithBodyAsType<T>(Func<T?, bool> func)
|
||||
{
|
||||
Guard.NotNull(func);
|
||||
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher<T>(func));
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ public partial class Request
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithMultiPart(IMatcher[] matchers, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, MatchOperator matchOperator = MatchOperator.Or)
|
||||
public IRequestBuilder WithMultiPart(IMatcher[] matchers, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch, MatchOperator matchOperator = MatchOperator.And)
|
||||
{
|
||||
_requestMatchers.Add(new RequestMessageMultiPartMatcher(matchBehaviour, matchOperator, matchers));
|
||||
return this;
|
||||
|
||||
@@ -4,6 +4,7 @@ using System;
|
||||
using Stef.Validation;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Validators;
|
||||
|
||||
namespace WireMock.RequestBuilders;
|
||||
|
||||
@@ -20,7 +21,7 @@ public partial class Request
|
||||
{
|
||||
Guard.NotNullOrEmpty(matchers);
|
||||
|
||||
_requestMatchers.Add(new RequestMessagePathMatcher(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, matchers));
|
||||
_requestMatchers.Add(new RequestMessagePathMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, matchers));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -34,6 +35,10 @@ public partial class Request
|
||||
public IRequestBuilder WithPath(MatchOperator matchOperator, params string[] paths)
|
||||
{
|
||||
Guard.NotNullOrEmpty(paths);
|
||||
foreach (var path in paths)
|
||||
{
|
||||
PathValidator.ValidateAndThrow(path, nameof(paths));
|
||||
}
|
||||
|
||||
_requestMatchers.Add(new RequestMessagePathMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, paths));
|
||||
return this;
|
||||
|
||||
@@ -29,7 +29,7 @@ public partial class Request : RequestMessageCompositeMatcher, IRequestBuilder
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
public static IRequestBuilder Create()
|
||||
{
|
||||
return new Request(new List<IRequestMatcher>());
|
||||
return new Request([]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -183,16 +183,9 @@ public class RequestMessage : IRequestMessage
|
||||
#endif
|
||||
|
||||
#if MIMEKIT
|
||||
try
|
||||
if (TypeLoader.TryLoadStaticInstance<IMimeKitUtils>(out var mimeKitUtils) && mimeKitUtils.TryGetMimeMessage(this, out var mimeMessage))
|
||||
{
|
||||
if (TypeLoader.LoadStaticInstance<IMimeKitUtils>().TryGetMimeMessage(this, out var mimeMessage))
|
||||
{
|
||||
BodyAsMimeMessage = mimeMessage;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore exception from MimeMessage.Load
|
||||
BodyAsMimeMessage = mimeMessage;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -272,25 +272,8 @@ public partial class Response : IResponseBuilder
|
||||
}
|
||||
}
|
||||
|
||||
ITransformer responseMessageTransformer;
|
||||
switch (TransformerType)
|
||||
{
|
||||
case TransformerType.Handlebars:
|
||||
var factoryHandlebars = new HandlebarsContextFactory(settings);
|
||||
responseMessageTransformer = new Transformer(settings, factoryHandlebars);
|
||||
break;
|
||||
|
||||
case TransformerType.Scriban:
|
||||
case TransformerType.ScribanDotLiquid:
|
||||
var factoryDotLiquid = new ScribanContextFactory(settings.FileSystemHandler, TransformerType);
|
||||
responseMessageTransformer = new Transformer(settings, factoryDotLiquid);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotSupportedException($"TransformerType '{TransformerType}' is not supported.");
|
||||
}
|
||||
|
||||
return (responseMessageTransformer.Transform(mapping, requestMessage, responseMessage, UseTransformerForBodyAsFile, TransformerReplaceNodeOptions), null);
|
||||
var transformer = TransformerFactory.Create(TransformerType, settings);
|
||||
return (transformer.Transform(mapping, requestMessage, responseMessage, UseTransformerForBodyAsFile, TransformerReplaceNodeOptions), null);
|
||||
}
|
||||
|
||||
if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true && responseMessage.BodyData?.BodyAsFile is not null)
|
||||
|
||||
@@ -166,11 +166,12 @@ internal class LogEntryMapper
|
||||
TotalScore = matchResult.TotalScore,
|
||||
TotalNumber = matchResult.TotalNumber,
|
||||
AverageTotalScore = matchResult.AverageTotalScore,
|
||||
MatchDetails = matchResult.MatchDetails.Select(md => new
|
||||
{
|
||||
Name = md.MatcherType.Name.Replace("RequestMessage", string.Empty),
|
||||
md.Score
|
||||
} as object).ToList()
|
||||
MatchDetails = matchResult.MatchDetails
|
||||
//MatchDetails = matchResult.MatchDetails.Select(md => new
|
||||
//{
|
||||
// Name = md.MatcherType.Name.Replace("RequestMessage", string.Empty),
|
||||
// md.Score
|
||||
//} as object).ToList()
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -226,14 +226,14 @@ internal class MappingConverter(MatcherMapper mapper)
|
||||
}
|
||||
}
|
||||
|
||||
if (response.Delay is { })
|
||||
{
|
||||
sb.AppendLine($" .WithDelay({response.Delay.Value.TotalMilliseconds})");
|
||||
}
|
||||
else if (response is { MinimumDelayMilliseconds: > 0, MaximumDelayMilliseconds: > 0 })
|
||||
if (response is { MinimumDelayMilliseconds: > 0, MaximumDelayMilliseconds: > 0 })
|
||||
{
|
||||
sb.AppendLine($" .WithRandomDelay({response.MinimumDelayMilliseconds}, {response.MaximumDelayMilliseconds})");
|
||||
}
|
||||
else if (response.Delay is { })
|
||||
{
|
||||
sb.AppendLine($" .WithDelay({response.Delay.Value.TotalMilliseconds})");
|
||||
}
|
||||
|
||||
if (response.UseTransformer)
|
||||
{
|
||||
|
||||
@@ -25,9 +25,9 @@ internal class MatcherMapper
|
||||
_settings = Guard.NotNull(settings);
|
||||
}
|
||||
|
||||
public IMatcher[]? Map(IEnumerable<MatcherModel>? matchers)
|
||||
public IMatcher[] Map(IEnumerable<MatcherModel>? matchers)
|
||||
{
|
||||
return matchers?.Select(Map).OfType<IMatcher>().ToArray();
|
||||
return matchers?.Select(Map).OfType<IMatcher>().ToArray() ?? [];
|
||||
}
|
||||
|
||||
public IMatcher? Map(MatcherModel? matcherModel)
|
||||
@@ -55,7 +55,12 @@ internal class MatcherMapper
|
||||
case "CSharpCodeMatcher":
|
||||
if (_settings.AllowCSharpCodeMatcher == true)
|
||||
{
|
||||
return TypeLoader.LoadNewInstance<ICSharpCodeMatcher>(matchBehaviour, matchOperator, stringPatterns);
|
||||
if (TypeLoader.TryLoadNewInstance<ICSharpCodeMatcher>(out var csharpCodeMatcher, matchBehaviour, matchOperator, stringPatterns))
|
||||
{
|
||||
return csharpCodeMatcher;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("The 'CSharpCodeMatcher' cannot be loaded. Please install the WireMock.Net.Matchers.CSharpCode package.");
|
||||
}
|
||||
|
||||
throw new NotSupportedException("It's not allowed to use the 'CSharpCodeMatcher' because WireMockServerSettings.AllowCSharpCodeMatcher is not set to 'true'.");
|
||||
@@ -75,7 +80,12 @@ internal class MatcherMapper
|
||||
case "GraphQLMatcher":
|
||||
var patternAsString = stringPatterns[0].GetPattern();
|
||||
var schema = new AnyOf<string, StringPattern, ISchemaData>(patternAsString);
|
||||
return TypeLoader.LoadNewInstance<IGraphQLMatcher>(schema, matcherModel.CustomScalars, matchBehaviour, matchOperator);
|
||||
if (TypeLoader.TryLoadNewInstance<IGraphQLMatcher>(out var graphQLMatcher, schema, matcherModel.CustomScalars, matchBehaviour, matchOperator))
|
||||
{
|
||||
return graphQLMatcher;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("The 'GraphQLMatcher' cannot be loaded. Please install the WireMock.Net.GraphQL package.");
|
||||
|
||||
case "MimePartMatcher":
|
||||
return CreateMimePartMatcher(matchBehaviour, matcherModel);
|
||||
@@ -282,18 +292,34 @@ internal class MatcherMapper
|
||||
var contentTransferEncodingMatcher = Map(matcher.ContentTransferEncodingMatcher) as IStringMatcher;
|
||||
var contentMatcher = Map(matcher.ContentMatcher);
|
||||
|
||||
return TypeLoader.LoadNewInstance<IMimePartMatcher>(matchBehaviour, contentTypeMatcher, contentDispositionMatcher, contentTransferEncodingMatcher, contentMatcher);
|
||||
if (TypeLoader.TryLoadNewInstance<IMimePartMatcher>(
|
||||
out var mimePartMatcher,
|
||||
matchBehaviour,
|
||||
contentTypeMatcher,
|
||||
contentDispositionMatcher,
|
||||
contentTransferEncodingMatcher,
|
||||
contentMatcher))
|
||||
{
|
||||
return mimePartMatcher;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("The 'MimePartMatcher' cannot be loaded. Please install the WireMock.Net.MimePart package.");
|
||||
}
|
||||
|
||||
private IProtoBufMatcher CreateProtoBufMatcher(MatchBehaviour? matchBehaviour, IReadOnlyList<string> protoDefinitions, MatcherModel matcher)
|
||||
{
|
||||
var objectMatcher = Map(matcher.ContentMatcher) as IObjectMatcher;
|
||||
|
||||
return TypeLoader.LoadNewInstance<IProtoBufMatcher>(
|
||||
if (TypeLoader.TryLoadNewInstance<IProtoBufMatcher>(
|
||||
out var protobufMatcher,
|
||||
() => ProtoDefinitionUtils.GetIdOrTexts(_settings, protoDefinitions.ToArray()),
|
||||
matcher.ProtoBufMessageType!,
|
||||
matchBehaviour ?? MatchBehaviour.AcceptOnMatch,
|
||||
objectMatcher
|
||||
);
|
||||
objectMatcher))
|
||||
{
|
||||
return protobufMatcher;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("The 'ProtoBufMatcher' cannot be loaded. Please install the WireMock.Net.ProtoBuf package.");
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using System.Linq;
|
||||
using Stef.Validation;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Serialization;
|
||||
@@ -253,7 +254,15 @@ public partial class WireMockServer
|
||||
else if (requestModel.Body?.Matchers != null)
|
||||
{
|
||||
var matchOperator = StringUtils.ParseMatchOperator(requestModel.Body.MatchOperator);
|
||||
requestBuilder = requestBuilder.WithBody(_matcherMapper.Map(requestModel.Body.Matchers)!, matchOperator);
|
||||
|
||||
if (requestModel.Body.MatcherName == RequestMessageMultiPartMatcher.Name)
|
||||
{
|
||||
requestBuilder = requestBuilder.WithMultiPart(_matcherMapper.Map(requestModel.Body.Matchers), matchOperator: matchOperator);
|
||||
}
|
||||
else
|
||||
{
|
||||
requestBuilder = requestBuilder.WithBody(_matcherMapper.Map(requestModel.Body.Matchers), matchOperator);
|
||||
}
|
||||
}
|
||||
|
||||
return requestBuilder;
|
||||
@@ -366,10 +375,8 @@ public partial class WireMockServer
|
||||
}
|
||||
else if (responseModel.BodyAsJson != null)
|
||||
{
|
||||
if (responseModel.ProtoBufMessageType != null)
|
||||
if (responseModel.ProtoBufMessageType != null && TypeLoader.TryLoadStaticInstance<IProtoBufUtils>(out var protoBufUtils))
|
||||
{
|
||||
var protoBufUtils = TypeLoader.LoadStaticInstance<IProtoBufUtils>();
|
||||
|
||||
if (responseModel.ProtoDefinition != null)
|
||||
{
|
||||
responseBuilder = protoBufUtils.UpdateResponseBuilder(responseBuilder, responseModel.ProtoBufMessageType, responseModel.BodyAsJson, responseModel.ProtoDefinition);
|
||||
|
||||
@@ -412,11 +412,6 @@ public partial class WireMockServer : IWireMockServer
|
||||
);
|
||||
|
||||
#if USE_ASPNETCORE
|
||||
_options.AdditionalServiceRegistration = _settings.AdditionalServiceRegistration;
|
||||
_options.CorsPolicyOptions = _settings.CorsPolicyOptions;
|
||||
_options.ClientCertificateMode = _settings.ClientCertificateMode;
|
||||
_options.AcceptAnyClientCertificate = _settings.AcceptAnyClientCertificate;
|
||||
|
||||
_httpServer = new AspNetCoreSelfHost(_options, urlOptions);
|
||||
#else
|
||||
_httpServer = new OwinSelfHost(_options, urlOptions);
|
||||
|
||||
@@ -36,7 +36,7 @@ public static class WireMockServerSettingsParser
|
||||
|
||||
if (parser.GetBoolSwitchValue("help"))
|
||||
{
|
||||
(logger ?? new WireMockConsoleLogger()).Info("See https://github.com/wiremock/WireMock.Net/wiki/WireMock-commandline-parameters for details on all commandline options.");
|
||||
(logger ?? new WireMockConsoleLogger()).Info("See https://wiremock.org/dotnet/wiremock-commandline-parameters/ for details on all commandline options.");
|
||||
settings = null;
|
||||
return false;
|
||||
}
|
||||
@@ -85,6 +85,7 @@ public static class WireMockServerSettingsParser
|
||||
ParseProxyAndRecordSettings(settings, parser);
|
||||
ParseCertificateSettings(settings, parser);
|
||||
ParseHandlebarsSettings(settings, parser);
|
||||
ParseActivityTracingSettings(settings, parser);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -153,7 +154,7 @@ public static class WireMockServerSettingsParser
|
||||
}
|
||||
else if (settings.HostingScheme is null)
|
||||
{
|
||||
settings.Urls = parser.GetValues("Urls", ["http://*:9091/"]);
|
||||
settings.Urls = parser.GetValues(nameof(WireMockServerSettings.Urls), defaultValue: ["http://*:9091/"]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,14 +203,42 @@ public static class WireMockServerSettingsParser
|
||||
|
||||
private static void ParseProxyUrlReplaceSettings(ProxyAndRecordSettings settings, SimpleSettingsParser parser)
|
||||
{
|
||||
var proxyUrlReplaceOldValue = parser.GetStringValue("ProxyUrlReplaceOldValue");
|
||||
var proxyUrlReplaceNewValue = parser.GetStringValue("ProxyUrlReplaceNewValue");
|
||||
const string prefix = "ProxyUrlReplace";
|
||||
var proxyUrlReplaceOldValue = parser.GetStringValue($"{prefix}OldValue");
|
||||
var proxyUrlReplaceNewValue = parser.GetStringValue($"{prefix}NewValue");
|
||||
if (!string.IsNullOrEmpty(proxyUrlReplaceOldValue) && proxyUrlReplaceNewValue != null)
|
||||
{
|
||||
settings.ReplaceSettings = new ProxyUrlReplaceSettings
|
||||
{
|
||||
OldValue = proxyUrlReplaceOldValue!,
|
||||
NewValue = proxyUrlReplaceNewValue
|
||||
OldValue = proxyUrlReplaceOldValue,
|
||||
NewValue = proxyUrlReplaceNewValue,
|
||||
IgnoreCase = parser.GetBoolValue($"{prefix}IgnoreCase")
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
var transformTemplate = parser.GetStringValue($"{prefix}TransformTemplate");
|
||||
if (!string.IsNullOrEmpty(transformTemplate))
|
||||
{
|
||||
settings.ReplaceSettings = new ProxyUrlReplaceSettings
|
||||
{
|
||||
TransformTemplate = transformTemplate,
|
||||
TransformerType = parser.GetEnumValue($"{prefix}TransformerType", TransformerType.Handlebars)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static void ParseActivityTracingSettings(WireMockServerSettings settings, SimpleSettingsParser parser)
|
||||
{
|
||||
// Only create ActivityTracingOptions if tracing is enabled
|
||||
if (parser.GetBoolValue("ActivityTracingEnabled") || parser.GetBoolValue("ActivityTracingOptions__Enabled"))
|
||||
{
|
||||
settings.ActivityTracingOptions = new ActivityTracingOptions
|
||||
{
|
||||
ExcludeAdminRequests = parser.GetBoolWithDefault("ActivityTracingExcludeAdminRequests", "ActivityTracingOptions__ExcludeAdminRequests", defaultValue: true),
|
||||
RecordRequestBody = parser.GetBoolValue("ActivityTracingRecordRequestBody") || parser.GetBoolValue("ActivityTracingOptions__RecordRequestBody"),
|
||||
RecordResponseBody = parser.GetBoolValue("ActivityTracingRecordResponseBody") || parser.GetBoolValue("ActivityTracingOptions__RecordResponseBody"),
|
||||
RecordMatchDetails = parser.GetBoolWithDefault("ActivityTracingRecordMatchDetails", "ActivityTracingOptions__RecordMatchDetails", defaultValue: true)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,8 @@ internal static class WireMockHandlebarsHelpers
|
||||
#endif
|
||||
o.CustomHelperPaths = paths;
|
||||
|
||||
o.Categories = settings.HandlebarsSettings?.AllowedHandlebarsHelpers ?? HandlebarsSettings.DefaultAllowedHandlebarsHelpers;
|
||||
|
||||
o.CustomHelpers = new Dictionary<string, IHelpers>();
|
||||
if (settings.HandlebarsSettings?.AllowedCustomHandlebarsHelpers.HasFlag(CustomHandlebarsHelpers.File) == true)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@ using WireMock.Util;
|
||||
|
||||
namespace WireMock.Transformers;
|
||||
|
||||
interface ITransformer
|
||||
internal interface ITransformer
|
||||
{
|
||||
ResponseMessage Transform(IMapping mapping, IRequestMessage requestMessage, IResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options);
|
||||
|
||||
@@ -15,4 +15,6 @@ interface ITransformer
|
||||
IDictionary<string, WireMockList<string>> TransformHeaders(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IDictionary<string, WireMockList<string>>? headers);
|
||||
|
||||
string TransformString(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, string? value);
|
||||
|
||||
string Transform(string template, object? model);
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
namespace WireMock.Transformers
|
||||
namespace WireMock.Transformers;
|
||||
|
||||
internal interface ITransformerContextFactory
|
||||
{
|
||||
interface ITransformerContextFactory
|
||||
{
|
||||
ITransformerContext Create();
|
||||
}
|
||||
ITransformerContext Create();
|
||||
}
|
||||
@@ -75,6 +75,11 @@ internal class Transformer : ITransformer
|
||||
return transformerContext.ParseAndRender(value, model);
|
||||
}
|
||||
|
||||
public string Transform(string template, object? model)
|
||||
{
|
||||
return model is null ? string.Empty : _factory.Create().ParseAndRender(template, model);
|
||||
}
|
||||
|
||||
public ResponseMessage Transform(IMapping mapping, IRequestMessage requestMessage, IResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options)
|
||||
{
|
||||
var responseMessage = new ResponseMessage();
|
||||
|
||||
30
src/WireMock.Net.Minimal/Transformers/TransformerFactory.cs
Normal file
30
src/WireMock.Net.Minimal/Transformers/TransformerFactory.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Transformers.Handlebars;
|
||||
using WireMock.Transformers.Scriban;
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.Transformers;
|
||||
|
||||
internal static class TransformerFactory
|
||||
{
|
||||
internal static ITransformer Create(TransformerType transformerType, WireMockServerSettings settings)
|
||||
{
|
||||
switch (transformerType)
|
||||
{
|
||||
case TransformerType.Handlebars:
|
||||
var factoryHandlebars = new HandlebarsContextFactory(settings);
|
||||
return new Transformer(settings, factoryHandlebars);
|
||||
|
||||
case TransformerType.Scriban:
|
||||
case TransformerType.ScribanDotLiquid:
|
||||
var factoryDotLiquid = new ScribanContextFactory(settings.FileSystemHandler, transformerType);
|
||||
return new Transformer(settings, factoryDotLiquid);
|
||||
|
||||
default:
|
||||
throw new NotSupportedException($"{nameof(TransformerType)} '{transformerType}' is not supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user