Skip to content

Commit 82cc7cf

Browse files
mconnewsubhra231weshaggardscottaddie
authored
WCF Client/CoreWCF extension packages to use Azure Queue Storage as transport (#42124)
* Add Azure Queue Storage support * Added custom Credentials classes with binding support to choose credential type. Added tests * First round of PR feedback changes * Addressing Review comments and fix test pipeline break * Update CoreWCF dependent package version * Fix problem with version pinning where type was removed in later version that NetFx asp.net core 2.1 needed * Changes to resolve PR comments * Read me updated to fix validation errors * Enable split build in extensions folder for aspnetcore and wcf * Remove Snippet annotation from documentation samples * Fix old package version specified by existing SDK versions which breaks the WCF build * Fix readme url's to be relative so they don't point to main branch which doesn't exist yet * Added samples with snippets, fixed yml definitions * Adding WCF docs to .docsettings.yml as well as CoreWCF * Fix end2end dlq test which didn't have credentials configured * Apply suggestions from code review Co-authored-by: Wes Haggard <[email protected]> * Apply suggestions from code review Co-authored-by: Scott Addie <[email protected]> * Fixed readme, fixed folder separator to be / instead of \ in service.projects --------- Co-authored-by: subhra231 <[email protected]> Co-authored-by: Wes Haggard <[email protected]> Co-authored-by: Scott Addie <[email protected]>
1 parent 0de35d0 commit 82cc7cf

File tree

122 files changed

+7808
-5
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

122 files changed

+7808
-5
lines changed

eng/.docsettings.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ known_content_issues:
133133
- ['sdk/storage/Azure.Storage.Files.DataLake/README.md', 'Storage: #11492: Needs auth section']
134134
- ['sdk/storage/Azure.Storage.Files.Shares/README.md', 'Storage: #11492: Needs auth section']
135135

136+
- ['sdk/extensions/wcf/Microsoft.CoreWCF.Azure.StorageQueues/README.md', 'https://github.com/Azure/azure-sdk-tools/issues/404']
137+
- ['sdk/extensions/wcf/Microsoft.WCF.Azure.StorageQueues/README.md', 'https://github.com/Azure/azure-sdk-tools/issues/404']
138+
136139
# .net climbs upwards. placing these to prevent assigning readmes to the wrong project
137140
package_indexing_exclusion_list:
138141
- 'AutoRest-AzureDotNetSDK'

eng/Packages.Data.props

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@
245245
<PackageReference Update="ApprovalUtilities" Version="3.0.22" />
246246
<PackageReference Update="Azure.Identity" Version="1.11.1" />
247247
<PackageReference Update="Azure.Messaging.EventGrid" Version="4.17.0" />
248-
<PackageReference Update="Azure.Messaging.EventHubs.Processor" Version="5.11.2" />
248+
<PackageReference Update="Azure.Messaging.EventHubs.Processor" Version="5.11.2" />
249249
<PackageReference Update="Azure.Messaging.ServiceBus" Version="7.17.5" />
250250
<PackageReference Update="Azure.ResourceManager.Compute" Version="1.2.0" />
251251
<PackageReference Update="Azure.ResourceManager.CognitiveServices" Version="1.3.0" />
@@ -257,9 +257,9 @@
257257
<PackageReference Update="Azure.ResourceManager.RecoveryServices" Version="1.1.0" />
258258
<PackageReference Update="Azure.ResourceManager.Resources" Version="1.6.0" />
259259
<PackageReference Update="Azure.ResourceManager.Storage" Version="1.1.1" />
260-
<PackageReference Update="Azure.ResourceManager.Kubernetes" Version="1.0.0-beta.3" />
261-
<PackageReference Update="Azure.ResourceManager.KubernetesConfiguration" Version="1.2.0-beta.1" />
262-
<PackageReference Update="Azure.ResourceManager.ExtendedLocations" Version="1.1.0-beta.1" />
260+
<PackageReference Update="Azure.ResourceManager.Kubernetes" Version="1.0.0-beta.3" />
261+
<PackageReference Update="Azure.ResourceManager.KubernetesConfiguration" Version="1.2.0-beta.1" />
262+
<PackageReference Update="Azure.ResourceManager.ExtendedLocations" Version="1.1.0-beta.1" />
263263
<PackageReference Update="Azure.ResourceManager.EventHubs" Version="1.0.0" />
264264
<PackageReference Update="Azure.ResourceManager.ContainerRegistry" Version="1.1.0" />
265265
<PackageReference Update="Azure.Search.Documents" Version="11.2.0" />
@@ -357,11 +357,29 @@
357357
<PackageReference Update="xunit.runner.visualstudio" Version="2.4.2" />
358358
<PackageReference Update="xunit" Version="2.4.2" />
359359
</ItemGroup>
360-
361360
<ItemGroup Condition="'$(TargetFramework)'=='netstandard2.0'">
362361
<PackageDownload Update="NETStandard.Library.Ref" Version="[2.1.0]" />
363362
</ItemGroup>
364363

364+
<!-- IsWcfLibrary is set in "..\sdk\extensions\wcf\Directory.Build.props". This property indicates that WCF/CoreWCF extensions project is being built.-->
365+
<ItemGroup Condition="'$(IsWcfLibrary)' == 'true'">
366+
<PackageReference Update="CoreWCF.Primitives" Version="[1.5.2,2.0)" />
367+
<PackageReference Update="CoreWCF.Queue" Version="[1.5.2,2.0)" />
368+
<PackageReference Update="System.IO.Pipelines" Version="6.0.3" />
369+
<PackageReference Update="Microsoft.AspNetCore" Version="2.1.0" />
370+
<PackageReference Update="System.ServiceModel.Primitives" Version="6.2.0" />
371+
<PackageReference Update="Azure.Storage.Files.Shares" Version="12.17.1" />
372+
<PackageReference Update="Azure.Storage.Queues" Version="12.17.1" />
373+
<PackageReference Update="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
374+
<PackageReference Update="Microsoft.Extensions.Http" Version="6.0.0" />
375+
<PackageReference Update="Microsoft.Extensions.Logging.Configuration" Version="2.1.1" />
376+
</ItemGroup>
377+
<ItemGroup Condition="('$(IsWcfLibrary)' == 'true') AND ($(TargetFramework.StartsWith('net4')))">
378+
<PackageReference Update="Microsoft.Extensions.Configuration.UserSecrets" Version="2.1.1" />
379+
<PackageReference Update="Microsoft.Extensions.Http" Version="2.1.1" />
380+
<PackageReference Update="Microsoft.Extensions.Logging.Configuration" Version="2.1.1" />
381+
</ItemGroup>
382+
365383
<PropertyGroup>
366384
<TestProxyVersion>1.0.0-dev.20240410.2</TestProxyVersion>
367385
</PropertyGroup>

sdk/extensions/ci.wcf.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# NOTE: Please refer to https://aka.ms/azsdk/engsys/ci-yaml before editing this file.
2+
3+
trigger:
4+
branches:
5+
include:
6+
- main
7+
- hotfix/*
8+
- release/*
9+
paths:
10+
include:
11+
- sdk/extensions/wcf
12+
13+
pr:
14+
branches:
15+
include:
16+
- main
17+
- feature/*
18+
- hotfix/*
19+
- release/*
20+
paths:
21+
include:
22+
- sdk/extensions/wcf
23+
24+
extends:
25+
template: /eng/pipelines/templates/stages/archetype-sdk-client.yml
26+
parameters:
27+
SDKType: wcf
28+
ServiceDirectory: extensions/wcf
29+
ArtifactName: packages
30+
Artifacts:
31+
- name: Microsoft.CoreWCF.Azure.StorageQueues
32+
safeName: MicrosoftCoreWCFAzureStorageQueues
33+
- name: Microsoft.WCF.Azure.StorageQueues
34+
safeName: MicrosoftWCFAzureStorageQueues
35+
CheckAOTCompat: false
36+
TestSetupSteps:
37+
- template: /sdk/storage/tests-install-azurite.yml

sdk/extensions/ci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ trigger:
99
paths:
1010
include:
1111
- sdk/extensions/
12+
exclude:
13+
- sdk/extensions/wcf/
1214

1315
pr:
1416
branches:
@@ -20,10 +22,13 @@ pr:
2022
paths:
2123
include:
2224
- sdk/extensions/
25+
exclude:
26+
- sdk/extensions/wcf/
2327

2428
extends:
2529
template: /eng/pipelines/templates/stages/archetype-sdk-client.yml
2630
parameters:
31+
SDKType: client
2732
ServiceDirectory: extensions
2833
ArtifactName: packages
2934
Artifacts:

sdk/extensions/service.projects

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!--
2+
This file allows overrides and extensions to the build configuration defined
3+
by the central engineering system, and is considered during pipeline builds for
4+
CI, test runs, and package release.
5+
6+
Based on the SDKType variable (msbuild property or env variable) this will filter
7+
the set of projects to to match what type of SDK we are interested in building.
8+
9+
SDKType values
10+
- "all" will build all projects
11+
- "client" will build the asp.net core extension libraries contained at the top level extensions folder
12+
- "wcf" will build the WCF/CoreWCF extension libraries contained in the wcf folder
13+
-->
14+
15+
<Project>
16+
<ItemGroup Condition="'$(SDKType)' == 'client'">
17+
<ProjectsToIncludeBySDKType Include="$(MSBuildThisFileDirectory)**/*.csproj" Exclude="$(MSBuildThisFileDirectory)wcf/**/*.csproj" />
18+
</ItemGroup>
19+
20+
<ItemGroup Condition="'$(SDKType)' == 'wcf'">
21+
<ProjectsToIncludeBySDKType Include="$(MSBuildThisFileDirectory)wcf/**/*.csproj" />
22+
</ItemGroup>
23+
</Project>

sdk/extensions/tests.wcf.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
trigger: none
2+
3+
extends:
4+
template: ../../eng/pipelines/templates/stages/archetype-sdk-tests.yml
5+
parameters:
6+
SDKType: wcf
7+
ServiceDirectory: extensions
8+
SupportedClouds: 'Public,Canary,UsGov,China'

sdk/extensions/tests.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ trigger: none
33
extends:
44
template: ../../eng/pipelines/templates/stages/archetype-sdk-tests.yml
55
parameters:
6+
SDKType: client
67
ServiceDirectory: extensions
78
SupportedClouds: 'Public,Canary,UsGov,China'
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<Project>
2+
<ItemGroup Condition="'$(IsTestProject)' != 'true'">
3+
<!--When parsing the None Item, output path doesn't include the TFM as part of the path
4+
The tfm gets added when building the target, so CopyIconFile has to specify the parent
5+
folder to have it be the same location-->
6+
<None Include="$(OutputPath)\Icon.png" Pack="true" PackagePath="\" />
7+
</ItemGroup>
8+
9+
<Target Condition="('$(IsTestProject)' != 'true') and ('$(IsSamplesProject)' != 'true')" Name="CopyIconFile" AfterTargets="AfterCompile">
10+
<ItemGroup>
11+
<SystemServiceModelIconFile Include="$(PkgSystem_ServiceModel_Primitives)\Icon.png"/>
12+
</ItemGroup>
13+
<Copy SourceFiles="@(SystemServiceModelIconFile)"
14+
DestinationFolder="$(OutputPath)\.." />
15+
</Target>
16+
<!-- Need to set IsClientLibrary for CentralPackageManagement versions file in $(root)\eng\Packages.Data.props -->
17+
<PropertyGroup>
18+
<IsClientLibrary Condition="'$(IsClientLibrary)' == '' and $(MSBuildProjectName.StartsWith('Microsoft.'))">true</IsClientLibrary>
19+
<IsTestProject Condition="'$(IsTestProject)' == '' and $(MSBuildProjectName.EndsWith('.Tests'))">true</IsTestProject>
20+
<IsWcfLibrary>true</IsWcfLibrary>
21+
</PropertyGroup>
22+
23+
<Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.props, $(MSBuildThisFileDirectory)..))" Condition="'$([MSBuild]::GetPathOfFileAbove(Directory.Build.props, $(MSBuildThisFileDirectory)..))' != ''"/>
24+
</Project>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Release History
2+
3+
## 1.0.0-beta.1 (Unreleased)
4+
5+
### Features Added
6+
7+
### Breaking Changes
8+
9+
### Bugs Fixed
10+
11+
### Other Changes
12+
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# CoreWCF Azure Queue Storage library for .NET
2+
3+
CoreWCF Azure Queue Storage is the service side library that will help existing WCF services to be able to use Azure Queue Storage to communicate with clients as a modern replacement to using MSMQ.
4+
5+
## Getting started
6+
7+
### Install the package
8+
9+
Install the Microsoft.CoreWCF.Azure.StorageQueues library for .NET with [NuGet][nuget]:
10+
11+
```dotnetcli
12+
dotnet add package Microsoft.CoreWCF.Azure.StorageQueues
13+
```
14+
15+
### Prerequisites
16+
17+
You need an [Azure subscription][azure_sub] and a
18+
[Storage Account][storage_account_docs] to use this package.
19+
20+
To create a new Storage Account, you can use the [Azure portal][storage_account_create_portal],
21+
[Azure PowerShell][storage_account_create_ps], or the [Azure CLI][storage_account_create_cli].
22+
Here's an example using the Azure CLI:
23+
24+
```azurecli
25+
az storage account create --name MyStorageAccount --resource-group MyResourceGroup --location westus --sku Standard_LRS
26+
```
27+
28+
### Configure ASP.NET Core to use CoreWCF with Queue transports
29+
30+
In order to receive requests from the Azure Queue Storage service, you'll need to configure CoreWCF to use queue transports.
31+
32+
```C# Snippet:Configure_CoreWCF_QueueTransport
33+
public void ConfigureServices(IServiceCollection services)
34+
{
35+
services.AddServiceModelServices()
36+
.AddQueueTransport();
37+
}
38+
```
39+
40+
### Authenticate the service to Azure Queue Storage
41+
42+
To receive requests from the Azure Queue Storage service, you'll need to configure CoreWCF with the appropriate endpoint, and configure credentials. The [Azure Identity library][identity] makes it easy to add Microsoft Entra ID support for authenticating with Azure services.
43+
44+
There are multiple authentication mechanisms for Azure Queue Storage. Which mechanism to use is configured via the property `AzureQueueStorageBinding.Security.Transport.ClientCredentialType`. The default authentication mechanism is `Default`, which uses `DefaultAzureCredential`.
45+
46+
```C# Snippet:CoreWCF_Azure_Storage_Queues_Sample_DefaultAzureCredential
47+
public void Configure(IApplicationBuilder app)
48+
{
49+
app.UseServiceModel(serviceBuilder =>
50+
{
51+
// Configure CoreWCF to dispatch to service type Service
52+
serviceBuilder.AddService<Service>();
53+
54+
// Create a binding instance to use Azure Queue Storage, passing an optional queue name for the dead letter queue
55+
// The default client credential type is Default, which uses DefaultAzureCredential
56+
var aqsBinding = new AzureQueueStorageBinding("DEADLETTERQUEUENAME");
57+
58+
// Add a service endpoint using the AzureQueueStorageBinding
59+
string queueEndpointString = "https://MYSTORAGEACCOUNT.queue.core.windows.net/QUEUENAME";
60+
serviceBuilder.AddServiceEndpoint<Service, IService>(aqsBinding, queueEndpointString);
61+
});
62+
}
63+
```
64+
65+
Learn more about enabling Microsoft Entra ID for authentication with Azure Storage in [our documentation][storage_ad].
66+
67+
### Other authentication credential mechanisms
68+
69+
If you are using a different credential mechanism such as `StorageSharedKeyCredential`, you configure the appropriate `ClientCredentialType` on the binding and set the credential on an `AzureServiceCredentials` instance via an extension method.
70+
71+
```C# Snippet:CoreWCF_Azure_Storage_Queus_Sample_StorageSharedKey
72+
public void Configure(IApplicationBuilder app)
73+
{
74+
app.UseServiceModel(serviceBuilder =>
75+
{
76+
// Configure CoreWCF to dispatch to service type Service
77+
serviceBuilder.AddService<Service>();
78+
79+
// Create a binding instance to use Azure Queue Storage, passing an optional queue name for the dead letter queue
80+
var aqsBinding = new AzureQueueStorageBinding("DEADLETTERQUEUENAME");
81+
82+
// Configure the client credential type to use StorageSharedKeyCredential
83+
aqsBinding.Security.Transport.ClientCredentialType = AzureClientCredentialType.StorageSharedKey;
84+
85+
// Add a service endpoint using the AzureQueueStorageBinding
86+
string queueEndpointString = "https://MYSTORAGEACCOUNT.queue.core.windows.net/QUEUENAME";
87+
serviceBuilder.AddServiceEndpoint<Service, IService>(aqsBinding, queueEndpointString);
88+
89+
// Use extension method to configure CoreWCF to use AzureServiceCredentials and set the
90+
// StorageSharedKeyCredential instance.
91+
serviceBuilder.UseAzureCredentials<Service>(credentials =>
92+
{
93+
credentials.StorageSharedKey = GetStorageSharedKey();
94+
});
95+
});
96+
}
97+
98+
public StorageSharedKeyCredential GetStorageSharedKey()
99+
{
100+
// Fetch shared key using a secure mechanism such as Azure Key Vault
101+
// and construct an instance of StorageSharedKeyCredential to return;
102+
return default;
103+
}
104+
```
105+
106+
Other values for ClientCredentialType are `Sas`, `Token`, and `ConnectionString`. The credentials class `AzureServiceCredentials` has corresponding properties to set each of these credential types.
107+
108+
## Troubleshooting
109+
110+
If there are any errors receiving a message from Azure Queue Storage, the CoreWCF transport will log the details at the `Debug` log level. You can configure logging for the category `Microsoft.CoreWCF` at the `Debug` level to see any errors.
111+
112+
```C# Snippet:CoreWCF_Azure_Storage_Queus_Sample_Logging
113+
.ConfigureLogging((logging) =>
114+
{
115+
logging.AddFilter("Microsoft.CoreWCF", LogLevel.Debug);
116+
});
117+
```
118+
119+
If a message was recevied from the queue, but wasn't able to be processed, it will be placed in the dead letter queue. You can sepcify the dead letter queue name by passing it to the constructor of `AzureQueueStorageBinding`. If not specified, the default value of `default-dead-letter-queue` will be used.
120+
121+
## Key concepts
122+
123+
CoreWCF is an implementation of the service side features of Windows Communication Foundation (WCF) for .NET. The goal of this project is to enable migrating existing WCF services to .NET that are currently using MSMQ and wish to deploy their service to Azure, replacing MSMQ with Azure Queue Storage.
124+
125+
More general samples of using CoreWCF can be found in the [CoreWCF samples repository][corewcf_repo]. To create a client to send messages to an Azure Storage Queue, see the[Microsoft.WCF.Azure.StorageQueues documentation][wcf_docs].
126+
127+
## Contributing
128+
129+
See the [Storage CONTRIBUTING.md][storage_contrib] for details on building,testing, and contributing to this library.
130+
131+
This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit [cla.microsoft.com][cla].
132+
133+
This project has adopted the [Microsoft Open Source Code of Conduct][coc].
134+
For more information see the [Code of Conduct FAQ][coc_faq] or contact [[email protected]][coc_contact] with any additional questions or comments.
135+
136+
<!-- LINKS -->
137+
[nuget]: https://www.nuget.org/
138+
[storage_account_docs]: https://learn.microsoft.com/azure/storage/common/storage-account-overview
139+
[storage_account_create_ps]: https://learn.microsoft.com/azure/storage/common/storage-account-create?tabs=azure-powershell
140+
[storage_account_create_cli]: https://learn.microsoft.com/azure/storage/common/storage-account-create?tabs=azure-cli
141+
[storage_account_create_portal]: https://learn.microsoft.com/azure/storage/common/storage-account-create?tabs=azure-portal
142+
[azure_cli]: https://learn.microsoft.com/cli/azure/
143+
[azure_sub]: https://azure.microsoft.com/free/dotnet/
144+
[identity]: https://github.com/Azure/azure-sdk-for-net/tree/main/sdk/identity/Azure.Identity/README.md
145+
[storage_ad]: https://learn.microsoft.com/azure/storage/blobs/authorize-access-azure-active-directory
146+
[storage_contrib]: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/storage/CONTRIBUTING.md
147+
[cla]: https://opensource.microsoft.com/cla/
148+
[coc]: https://opensource.microsoft.com/codeofconduct/
149+
[coc_faq]: https://opensource.microsoft.com/codeofconduct/faq/
150+
[coc_contact]: mailto:[email protected]
151+
[corewcf_repo]: https://github.com/CoreWCF/samples/
152+
[wcf_docs]: https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/extensions/wcf/Microsoft.WCF.Azure.StorageQueues

0 commit comments

Comments
 (0)