Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,5 @@
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

*.ps1 linguist-vendored
Binary file not shown.
13 changes: 13 additions & 0 deletions docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,19 @@
"docs/framework/ui-automation/**/**.md": "None",
"docs/framework/wcf/**/**.md": "None"
},
"social_image_url": {
"docs/**/*.*": "/dotnet/media/dotnet-logo.svg",
"docs/azure/**/*.*": "/dotnet/media/dotnet-bot_cloud-apps.svg",
"docs/iot/**/*.*": "/dotnet/media/dotnet-iot.svg",
"docs/maui/**/*.*": "/dotnet/media/dotnet-bot_mobile-apps-xamarin.svg",
"docs/machine-learning/**/*.*": "/dotnet/media/dotnet-bot_machinelearning.svg",
"docs/architecture/**/*.*": "/dotnet/media/dotnet-bot_microservices.svg",
"docs/spark/**/*.*": "/dotnet/media/dotnet-bot_apache-spark.svg",
"docs/standard/**/*.*": "/dotnet/media/dot-net-cross-platform.svg",
"docs/csharp/**/*.*": "/media/logos/logo_csharp.svg",
"docs/fsharp/**/*.*": "/media/logos/logo_fsharp.svg",
"docs/visual-basic/**/*.*": "/media/logos/logo_vb.svg"
},
"feedback_product_url": {
"docs/azure/sdk/**/*.*": "https://github.com/azure/azure-sdk-for-net",
"docs/fsharp/**/**.md": "https://github.com/dotnet/fsharp",
Expand Down
16 changes: 9 additions & 7 deletions docs/architecture/dapr-for-net-developers/actors.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: The Dapr actors building block
description: A deep dive into the Dapr actors building block and how to apply it
author: amolenk
ms.date: 06/22/2021
ms.date: 06/26/2021
---

# The Dapr actors building block
Expand Down Expand Up @@ -110,7 +110,7 @@ public int Increment()

Unfortunately, using explicit locking mechanisms is error-prone. They can easily lead to deadlocks and can have serious impact on performance.

Thanks to the turn-based access model, you don't need to worry about multiple threads with actors, making it much easier to concurrent systems. The following actor example closely mirrors the code from the previous sample, but doesn't require any locking mechanisms to be correct:
Thanks to the turn-based access model, you don't need to worry about multiple threads with actors, making it much easier to write concurrent systems. The following actor example closely mirrors the code from the previous sample, but doesn't require any locking mechanisms to be correct:

```csharp
public async Task<int> IncrementAsync()
Expand Down Expand Up @@ -168,8 +168,10 @@ Actor state is persisted using the Dapr [state management building block](state-

- Azure Cosmos DB
- MongoDB
- MySQL
- PostgreSQL
- Redis
- RethinkDB
- SQL Server

To configure a state store component for use with actors, you need to append the following metadata to the state store configuration:
Expand Down Expand Up @@ -200,13 +202,13 @@ spec:

## Use the Dapr .NET SDK

You can create an actor model implementation using only HTTP/gRPC calls. However, it's much more convenient to use the language specific Dapr SDKs. At the time of writing, both the .NET and Java SDKs provide extensive support for working with actors.
You can create an actor model implementation using only HTTP/gRPC calls. However, it's much more convenient to use the language specific Dapr SDKs. At the time of writing, the .NET, Java and Python SDKs all provide extensive support for working with actors.

To get started with the .NET Dapr actors SDK, you add a package reference to [`Dapr.Actors`](https://www.nuget.org/packages/Dapr.Actors) to your service project. The first step of creating an actual actor is to define an interface that derives from `IActor`. Clients use the interface to invoke operations on the actor. Here's a simple example of an actor interface for keeping scores:

```csharp
public interface IScoreActor : IActor
{
{
Task<int> IncrementScoreAsync();

Task<int> GetScoreAsync();
Expand Down Expand Up @@ -288,7 +290,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
The actors endpoints are necessary because the Dapr sidecar calls the application to host and interact with actor instances.

> [!IMPORTANT]
> By default, a generated `Startup` class contains an `app.UseHttpsRedirection` call to redirect client to the HTTPS endpoint. This will not work with actors and must be removed. By design, a Dapr sidecar sends requests over unencrypted HTTP by default. The HTTPS middleware will block these requests when enabled.
> Make sure your `Startup` class does not contain an `app.UseHttpsRedirection` call to redirect clients to the HTTPS endpoint. This will not work with actors. By design, a Dapr sidecar sends requests over unencrypted HTTP by default. The HTTPS middleware will block these requests when enabled.

The `Startup` class is also the place to register the specific actor types. In the example below, `ConfigureServices` registers the `ScoreActor` using `services.AddActors`:

Expand All @@ -314,7 +316,7 @@ static async Task MainAsync(string[] args)
var proxy = ActorProxy.Create<IScoreActor>(actorId, "ScoreActor");

var score = await proxy.IncrementScoreAsync();

Console.WriteLine($"Current score: {score}");
}
```
Expand Down Expand Up @@ -344,7 +346,7 @@ public void ConfigureServices(IServiceCollection services)
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true
};

options.JsonSerializerOptions = jsonSerializerOptions;
options.Actors.RegisterActor<ScoreActor>();
});
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ public Task ReceiveReminderAsync(
JsonConvert.DeserializeObject<List<int>>(Encoding.UTF8.GetString(state))),
PaymentSucceededReminder => OnPaymentSucceededSimulatedWorkDoneAsync(),
PaymentFailedReminder => OnPaymentFailedSimulatedWorkDoneAsync(),
_ => Task.CompletedTask
_ => Task.CompletedTask
};
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ The `CalculateFine` method expects a string containing a `licenseKey` as its fir
}

// ...

else if (violationInKmh == 35)
{
fine += 372;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ Information is retrieved by the ASP.NET `CollectionController` class in the Fine

// get owner info (Dapr service invocation)
var vehicleInfo = _vehicleRegistrationService.GetVehicleInfo(speedingViolation.VehicleId).Result;

// ...
}
```
Expand All @@ -282,7 +282,7 @@ The code uses a proxy of type `VehicleRegistrationService` to call the VehicleRe
```csharp
public CollectionController(
ILogger<CollectionController> logger,
IFineCalculator fineCalculator,
IFineCalculator fineCalculator,
VehicleRegistrationService vehicleRegistrationService,
DaprClient daprClient)
{
Expand All @@ -300,7 +300,7 @@ The `VehicleRegistrationService` class contains a single method: `GetVehicleInfo
{
_httpClient = httpClient;
}

public async Task<VehicleInfo> GetVehicleInfo(string licenseNumber)
{
return await _httpClient.GetFromJsonAsync<VehicleInfo>(
Expand All @@ -314,7 +314,7 @@ The code doesn't depend on any Dapr classes directly. It instead leverages the D
```csharp
// ...

services.AddSingleton<VehicleRegistrationService>(_ =>
services.AddSingleton<VehicleRegistrationService>(_ =>
new VehicleRegistrationService(DaprClient.CreateInvokeHttpClient(
"vehicleregistrationservice", $"http://localhost:{daprHttpPort}"
)));
Expand Down
49 changes: 48 additions & 1 deletion docs/architecture/grpc-for-wcf-developers/channel-credentials.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Channel credentials - gRPC for WCF Developers
description: How to implement and use gRPC channel credentials in ASP.NET Core 3.0.
ms.date: 12/15/2020
ms.date: 06/28/2021
---

# Channel credentials
Expand Down Expand Up @@ -92,6 +92,10 @@ public class Startup

With the `Grpc.Net.Client` package, you configure certificates on an <xref:System.Net.Http.HttpClient> instance that is provided to the `GrpcChannel` used for the connection.

### Load a client certificate from a .PFX file

A certificate can be loaded from a _.pfx_ file.

```csharp
class Program
{
Expand All @@ -117,6 +121,49 @@ class Program
}
```

### Load a client certificate from certificate and private key .PEM files

A certificate can be loaded from a certificate and private key _.pem_ file.

```csharp
class Program
{
static async Task Main(string[] args)
{
// Assume path to a certificate and private key .pem files are passed from command line
string certificatePem = File.ReadAllText(args[0]);
string privateKeyPem = File.ReadAllText(args[1]);
var cert = X509Certificate2.CreateFromPem(certificatePem, privateKeyPem);

var handler = new HttpClientHandler();
handler.ClientCertificates.Add(cert);
using HttpClient httpClient = new(handler);

var channel = GrpcChannel.ForAddress("https://localhost:5001/", new GrpcChannelOptions
{
HttpClient = httpClient
});

var grpc = new Greeter.GreeterClient(channel);
var response = await grpc.SayHelloAsync(new HelloRequest { Name = "Bob" });
System.Console.WriteLine(response.Message);
}
}
```

> [!NOTE]
> Due to an internal Windows bug as [documented here](https://github.com/dotnet/runtime/issues/23749#issuecomment-388231655), you'll need to apply the following a workaround if the certificate is created from certificate and private key PEM data.
>
> ```csharp
> X509Certificate2 cert = X509Certificate2.CreateFromPem(certificatePem, rsaPrivateKeyPem);
> if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
> {
> var originalCert = cert;
> cert = new X509Certificate2(cert.Export(X509ContentType.Pkcs12));
> originalCert.Dispose();
> }
> ```

## Combine ChannelCredentials and CallCredentials

You can configure your server to use both certificate and token authentication. To do this, apply the certificate changes to the Kestrel server, and use the JWT bearer middleware in ASP.NET Core.
Expand Down
Loading