mirror of https://github.com/dapr/dotnet-sdk.git
Move to new invoke proto, specify contenttype in response to the dapr… (#295)
* Move to new invoke proto, specify contenttype in response to the dapr/config message, clarify sample * Update for additional proto changes * cr Co-authored-by: LM <lemai>
This commit is contained in:
parent
c73afa9882
commit
44ca6496d8
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
namespace RoutingSample
|
||||
{
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr;
|
||||
using Dapr.Client;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
|
|
@ -83,25 +83,33 @@ namespace RoutingSample
|
|||
|
||||
async Task Balance(HttpContext context)
|
||||
{
|
||||
Console.WriteLine("Enter Balance");
|
||||
var client = context.RequestServices.GetRequiredService<DaprClient>();
|
||||
|
||||
var id = (string)context.Request.RouteValues["id"];
|
||||
Console.WriteLine("id is {0}", id);
|
||||
var account = await client.GetStateAsync<Account>(StoreName, id);
|
||||
if (account == null)
|
||||
{
|
||||
Console.WriteLine("Account not found");
|
||||
context.Response.StatusCode = 404;
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("Account balance is {0}", account.Balance);
|
||||
|
||||
context.Response.ContentType = "application/json";
|
||||
await JsonSerializer.SerializeAsync(context.Response.Body, account, serializerOptions);
|
||||
}
|
||||
|
||||
async Task Deposit(HttpContext context)
|
||||
{
|
||||
Console.WriteLine("Enter Deposit");
|
||||
|
||||
var client = context.RequestServices.GetRequiredService<DaprClient>();
|
||||
|
||||
var transaction = await JsonSerializer.DeserializeAsync<Transaction>(context.Request.Body, serializerOptions);
|
||||
Console.WriteLine("Id is {0}, Amount is {1}", transaction.Id, transaction.Amount);
|
||||
var account = await client.GetStateAsync<Account>(StoreName, transaction.Id);
|
||||
if (account == null)
|
||||
{
|
||||
|
|
@ -110,12 +118,14 @@ namespace RoutingSample
|
|||
|
||||
if (transaction.Amount < 0m)
|
||||
{
|
||||
Console.WriteLine("Invalid amount");
|
||||
context.Response.StatusCode = 400;
|
||||
return;
|
||||
}
|
||||
|
||||
account.Balance += transaction.Amount;
|
||||
await client.SaveStateAsync(StoreName, transaction.Id, account);
|
||||
Console.WriteLine("Balance is {0}", account.Balance);
|
||||
|
||||
context.Response.ContentType = "application/json";
|
||||
await JsonSerializer.SerializeAsync(context.Response.Body, account, serializerOptions);
|
||||
|
|
@ -123,24 +133,28 @@ namespace RoutingSample
|
|||
|
||||
async Task Withdraw(HttpContext context)
|
||||
{
|
||||
Console.WriteLine("Enter Withdraw");
|
||||
var client = context.RequestServices.GetRequiredService<DaprClient>();
|
||||
|
||||
var transaction = await JsonSerializer.DeserializeAsync<Transaction>(context.Request.Body, serializerOptions);
|
||||
Console.WriteLine("Id is {0}", transaction.Id);
|
||||
var account = await client.GetStateAsync<Account>(StoreName, transaction.Id);
|
||||
if (account == null)
|
||||
{
|
||||
Console.WriteLine("Account not found");
|
||||
context.Response.StatusCode = 404;
|
||||
return;
|
||||
}
|
||||
|
||||
if (transaction.Amount < 0m)
|
||||
{
|
||||
Console.WriteLine("Invalid amount");
|
||||
context.Response.StatusCode = 400;
|
||||
return;
|
||||
}
|
||||
|
||||
account.Balance -= transaction.Amount;
|
||||
await client.SaveStateAsync(StoreName, transaction.Id, account);
|
||||
Console.WriteLine("Balance is {0}", account.Balance);
|
||||
|
||||
context.Response.ContentType = "application/json";
|
||||
await JsonSerializer.SerializeAsync(context.Response.Body, account, serializerOptions);
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@
|
|||
namespace DaprClient
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr.Client;
|
||||
using Dapr.Client.Http;
|
||||
|
||||
/// <summary>
|
||||
/// Shows Dapr client calls.
|
||||
|
|
@ -26,7 +26,15 @@ namespace DaprClient
|
|||
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
var client = new DaprClientBuilder().Build();
|
||||
var jsonOptions = new JsonSerializerOptions()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
PropertyNameCaseInsensitive = true,
|
||||
};
|
||||
|
||||
var client = new DaprClientBuilder()
|
||||
.UseJsonSerializationOptions(jsonOptions)
|
||||
.Build();
|
||||
|
||||
await PublishEventAsync(client);
|
||||
|
||||
|
|
@ -42,26 +50,31 @@ namespace DaprClient
|
|||
#region Service Invoke - Required RoutingService
|
||||
// This provides an example of how to invoke a method on another REST service that is listening on http.
|
||||
// To use it run RoutingService in this solution.
|
||||
// Invoke deposit operation on RoutingSample service by publishing event.
|
||||
// Invoke deposit operation on RoutingSample service by publishing event.
|
||||
|
||||
//await PublishDepositeEventToRoutingSampleAsync(client);
|
||||
|
||||
//await Task.Delay(TimeSpan.FromSeconds(1));
|
||||
|
||||
// Invoke deposit operation on RoutingSample service by POST.
|
||||
//await DepositUsingServiceInvocation(client);
|
||||
|
||||
//Invoke deposit operation on RoutingSample service by POST.
|
||||
//await InvokeWithdrawServiceOperationAsync(client);
|
||||
|
||||
// Invoke deposit operation on RoutingSample service by GET.
|
||||
//Invoke deposit operation on RoutingSample service by GET.
|
||||
//await InvokeBalanceServiceOperationAsync(client);
|
||||
#endregion
|
||||
|
||||
Console.WriteLine("Done");
|
||||
}
|
||||
|
||||
internal static async Task PublishDepositeEventToRoutingSampleAsync(DaprClient client)
|
||||
{
|
||||
var eventData = new { id = "17", amount = (decimal)10, };
|
||||
var eventData = new { Id = "17", Amount = (decimal)10, };
|
||||
await client.PublishEventAsync("deposit", eventData);
|
||||
Console.WriteLine("Published deposit event!");
|
||||
}
|
||||
|
||||
|
||||
internal static async Task PublishEventAsync(DaprClient client)
|
||||
{
|
||||
var eventData = new Widget() { Size = "small", Color = "yellow", };
|
||||
|
|
@ -95,6 +108,24 @@ namespace DaprClient
|
|||
Console.WriteLine("Deleted State!");
|
||||
}
|
||||
|
||||
internal static async Task DepositUsingServiceInvocation(DaprClient client)
|
||||
{
|
||||
Console.WriteLine("DepositUsingServiceInvocation");
|
||||
var data = new { id = "17", amount = (decimal)99 };
|
||||
|
||||
HTTPExtension httpExtension = new HTTPExtension()
|
||||
{
|
||||
Verb = HTTPVerb.Post
|
||||
};
|
||||
|
||||
// Invokes a POST method named "depoit" that takes input of type "Transaction" as define in the RoutingSample.
|
||||
Console.WriteLine("invoking");
|
||||
|
||||
var a = await client.InvokeMethodAsync<object, Account>("routing", "deposit", data, httpExtension);
|
||||
Console.WriteLine("Returned: id:{0} | Balance:{1}", a.Id, a.Balance);
|
||||
|
||||
Console.WriteLine("Completed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This example shows how to invoke a POST method on a service listening on http.
|
||||
|
|
@ -107,14 +138,16 @@ namespace DaprClient
|
|||
/// <returns></returns>
|
||||
internal static async Task InvokeWithdrawServiceOperationAsync(DaprClient client)
|
||||
{
|
||||
Console.WriteLine("Invoking withdraw");
|
||||
var data = new { id = "17", amount = (decimal)10, };
|
||||
|
||||
// Add the verb to metadata if the method is other than a POST
|
||||
var metaData = new Dictionary<string, string>();
|
||||
metaData.Add("http.verb", "POST");
|
||||
HTTPExtension httpExtension = new HTTPExtension()
|
||||
{
|
||||
Verb = HTTPVerb.Post
|
||||
};
|
||||
|
||||
// Invokes a POST method named "Withdraw" that takes input of type "Transaction" as define in the RoutingSample.
|
||||
await client.InvokeMethodAsync<object>("routing", "Withdraw", data, metaData);
|
||||
// Invokes a POST method named "Withdraw" that takes input of type "Transaction" as define in the RoutingSample.
|
||||
await client.InvokeMethodAsync<object>("routing", "Withdraw", data, httpExtension);
|
||||
|
||||
Console.WriteLine("Completed");
|
||||
}
|
||||
|
|
@ -130,28 +163,16 @@ namespace DaprClient
|
|||
/// <returns></returns>
|
||||
internal static async Task InvokeBalanceServiceOperationAsync(DaprClient client)
|
||||
{
|
||||
// Add the verb to metadata if the method is other than a POST
|
||||
var metaData = new Dictionary<string, string>();
|
||||
metaData.Add("http.verb", "GET");
|
||||
Console.WriteLine("Invoking balance");
|
||||
|
||||
// Invokes a GET method named "hello" that takes input of type "MyData" and returns a string.
|
||||
var res = await client.InvokeMethodAsync<object>("routing", "17", metaData);
|
||||
|
||||
Console.WriteLine($"Received balance {res}");
|
||||
}
|
||||
HTTPExtension httpExtension = new HTTPExtension()
|
||||
{
|
||||
Verb = HTTPVerb.Get
|
||||
};
|
||||
var res = await client.InvokeMethodAsync<Account>("routing", "17", httpExtension);
|
||||
|
||||
/// <summary>
|
||||
/// This example shows how to invoke a method on a service listening on gRPC.
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <returns></returns>
|
||||
internal static async Task InvokeMethodOnGrpcServiceAsync(DaprClient client)
|
||||
{
|
||||
MyData data = new MyData() { Message = "mydata" };
|
||||
|
||||
// invokes a method named "hello" that takes input of type "MyData" and returns a string.
|
||||
string s = await client.InvokeMethodAsync<MyData, string>("nodeapp", "hello", data);
|
||||
Console.WriteLine("received {0}", s);
|
||||
Console.WriteLine($"Received balance {res.Balance}");
|
||||
}
|
||||
|
||||
private class Widget
|
||||
|
|
@ -167,5 +188,14 @@ namespace DaprClient
|
|||
|
||||
public String Message { get; set; }
|
||||
}
|
||||
|
||||
|
||||
internal class Account
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
public decimal Balance { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ namespace Dapr.Actors.AspNetCore
|
|||
{
|
||||
routeBuilder.MapGet("dapr/config", async context =>
|
||||
{
|
||||
await ActorRuntime.Instance.SerializeSettingsAndRegisteredTypes(context.Response.BodyWriter);
|
||||
context.Response.ContentType = "application/json";
|
||||
await ActorRuntime.Instance.SerializeSettingsAndRegisteredTypes(context.Response.BodyWriter);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,24 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Protobuf Include="Protos\dapr\proto\common\v1\common.proto" ProtoRoot="Protos" GrpcServices="Client" />
|
||||
<Protobuf Include="Protos\dapr\proto\dapr\v1\dapr.proto" ProtoRoot="Protos" GrpcServices="Client" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Additional Nuget package properties. -->
|
||||
<PropertyGroup>
|
||||
<Description>This package contains the reference assemblies for developing services using Dapr.</Description>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Google.Protobuf" Version="3.11.4" />
|
||||
<PackageReference Include="Grpc.Net.Client" Version="2.27.0" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.27.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Protos\" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Additional Nuget package properties. -->
|
||||
<PropertyGroup>
|
||||
<Description>This package contains the reference assemblies for developing services using Dapr.</Description>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Protobuf Include="Protos\dapr.proto" GrpcServices="Client" />
|
||||
<Protobuf Include="Protos\daprclient.proto" GrpcServices="Client" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Google.Protobuf" Version="3.11.4" />
|
||||
<PackageReference Include="Grpc.Net.Client" Version="2.27.0" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.27.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -5,12 +5,9 @@
|
|||
|
||||
namespace Dapr.Client
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr.Client.Autogen.Grpc;
|
||||
|
||||
/// <summary>
|
||||
/// Defines client methods for interacting with Dapr endpoints.
|
||||
|
|
@ -56,20 +53,13 @@ namespace Dapr.Client
|
|||
/// </summary>
|
||||
/// <param name="appId">The Dapr application id to invoke the method on.</param>
|
||||
/// <param name="methodName">The name of the method to invoke.</param>
|
||||
/// <param name="metadata">A key/value pair to pass to the method to invoke.</param>
|
||||
/// <param name="httpExtension">Additional fields that may be needed if the receiving app is listening on HTTP.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
|
||||
/// <returns>A <see cref="Task" /> that will complete when the operation has completed.</returns>
|
||||
/// <remarks>If the target service is listening on http, a key value pair of http.verb and the verb must be added to the metadata parameter.
|
||||
/// For example:
|
||||
///
|
||||
/// ...
|
||||
/// myMetadata.Add("http.verb", "POST");
|
||||
/// daprClient.InvokeMethodAsync(...., myMetadata);
|
||||
/// </remarks>
|
||||
/// <returns>A <see cref="Task" /> that will complete when the operation has completed.</returns>
|
||||
public abstract Task InvokeMethodAsync(
|
||||
string appId,
|
||||
string methodName,
|
||||
Dictionary<string, string> metadata = default,
|
||||
Dapr.Client.Http.HTTPExtension httpExtension = default,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -79,21 +69,14 @@ namespace Dapr.Client
|
|||
/// <param name="appId">The Dapr application id to invoke the method on.</param>
|
||||
/// <param name="methodName">The name of the method to invoke.</param>
|
||||
/// <param name="data">Data to pass to the method</param>
|
||||
/// <param name="metadata">A key/value pair to pass to the method to invoke.</param>
|
||||
/// <param name="httpExtension">Additional fields that may be needed if the receiving app is listening on HTTP.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
|
||||
/// <returns>A <see cref="ValueTask{T}" /> that will return the value when the operation has completed.</returns>
|
||||
/// <remarks>If the target service is listening on http, a key value pair of http.verb and the verb must be added to the metadata parameter.
|
||||
/// For example:
|
||||
///
|
||||
/// ...
|
||||
/// myMetadata.Add("http.verb", "POST");
|
||||
/// daprClient.InvokeMethodAsync(...., myMetadata);
|
||||
/// </remarks>
|
||||
/// <returns>A <see cref="ValueTask{T}" /> that will return the value when the operation has completed.</returns>
|
||||
public abstract Task InvokeMethodAsync<TRequest>(
|
||||
string appId,
|
||||
string methodName,
|
||||
TRequest data,
|
||||
Dictionary<string, string> metadata = default,
|
||||
Dapr.Client.Http.HTTPExtension httpExtension = default,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -102,20 +85,13 @@ namespace Dapr.Client
|
|||
/// <typeparam name="TResponse">The type of the object in the response.</typeparam>
|
||||
/// <param name="appId">The Dapr application id to invoke the method on.</param>
|
||||
/// <param name="methodName">The name of the method to invoke.</param>
|
||||
/// <param name="metadata">A key/value pair to pass to the method to invoke.</param>
|
||||
/// <param name="httpExtension">Additional fields that may be needed if the receiving app is listening on HTTP.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
|
||||
/// <returns>A <see cref="ValueTask{T}" /> that will return the value when the operation has completed.</returns>
|
||||
/// <remarks>If the target service is listening on http, a key value pair of http.verb and the verb must be added to the metadata parameter.
|
||||
/// For example:
|
||||
///
|
||||
/// ...
|
||||
/// myMetadata.Add("http.verb", "POST");
|
||||
/// daprClient.InvokeMethodAsync(...., myMetadata);
|
||||
/// </remarks>
|
||||
/// <returns>A <see cref="ValueTask{T}" /> that will return the value when the operation has completed.</returns>
|
||||
public abstract ValueTask<TResponse> InvokeMethodAsync<TResponse>(
|
||||
string appId,
|
||||
string methodName,
|
||||
Dictionary<string, string> metadata = default,
|
||||
Dapr.Client.Http.HTTPExtension httpExtension = default,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -125,22 +101,15 @@ namespace Dapr.Client
|
|||
/// <typeparam name="TResponse">The type of the object in the response.</typeparam>
|
||||
/// <param name="appId">The Dapr application id to invoke the method on.</param>
|
||||
/// <param name="methodName">The name of the method to invoke.</param>
|
||||
/// <param name="data">Data to pass to the method</param>
|
||||
/// <param name="metadata">A key/value pair to pass to the method to invoke.</param>
|
||||
/// <param name="data">Data to pass to the method</param>
|
||||
/// <param name="httpExtension">Additional fields that may be needed if the receiving app is listening on HTTP.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
|
||||
/// <returns>A <see cref="ValueTask{T}" /> that will return the value when the operation has completed.</returns>
|
||||
/// <remarks>If the target service is listening on http, a key value pair of http.verb and the verb must be added to the metadata parameter.
|
||||
/// For example:
|
||||
///
|
||||
/// ...
|
||||
/// myMetadata.Add("http.verb", "POST");
|
||||
/// daprClient.InvokeMethodAsync(...., myMetadata);
|
||||
/// </remarks>
|
||||
/// <returns>A <see cref="ValueTask{T}" /> that will return the value when the operation has completed.</returns>
|
||||
public abstract ValueTask<TResponse> InvokeMethodAsync<TRequest, TResponse>(
|
||||
string appId,
|
||||
string methodName,
|
||||
TRequest data,
|
||||
Dictionary<string, string> metadata = default,
|
||||
Dapr.Client.Http.HTTPExtension httpExtension = default,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ namespace Dapr.Client
|
|||
public DaprClientBuilder()
|
||||
{
|
||||
var daprGrpcPort = Environment.GetEnvironmentVariable("DAPR_GRPC_PORT") ?? defaultDaprGrpcPort;
|
||||
this.daprEndpoint = $"http://127.0.0.1:{daprGrpcPort}";
|
||||
this.daprEndpoint = $"http://127.0.0.1:{daprGrpcPort}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -7,17 +7,17 @@ namespace Dapr.Client
|
|||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr.Client.Autogen.Grpc;
|
||||
using Dapr.Client.Autogen.Grpc.v1;
|
||||
using Dapr.Client.Http;
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Grpc.Core;
|
||||
using Grpc.Net.Client;
|
||||
using Autogenerated = Dapr.Client.Autogen.Grpc;
|
||||
using Autogenerated = Dapr.Client.Autogen.Grpc.v1;
|
||||
|
||||
/// <summary>
|
||||
/// A client for interacting with the Dapr endpoints.
|
||||
|
|
@ -113,20 +113,20 @@ namespace Dapr.Client
|
|||
public override async Task InvokeMethodAsync(
|
||||
string appId,
|
||||
string methodName,
|
||||
Dictionary<string, string> metadata = default,
|
||||
Http.HTTPExtension httpExtension = default,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(appId, nameof(appId));
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(methodName, nameof(methodName));
|
||||
|
||||
_ = await this.MakeInvokeRequestAsync(appId, methodName, null, metadata, cancellationToken);
|
||||
_ = await this.MakeInvokeRequestAsync(appId, methodName, null, httpExtension, cancellationToken);
|
||||
}
|
||||
|
||||
public override async Task InvokeMethodAsync<TRequest>(
|
||||
string appId,
|
||||
string methodName,
|
||||
TRequest data,
|
||||
Dictionary<string, string> metadata = default,
|
||||
Http.HTTPExtension httpExtension = default,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(appId, nameof(appId));
|
||||
|
|
@ -138,33 +138,32 @@ namespace Dapr.Client
|
|||
serializedData = ConvertToAnyAsync(data, this.jsonSerializerOptions);
|
||||
}
|
||||
|
||||
_ = await this.MakeInvokeRequestAsync(appId, methodName, serializedData, metadata, cancellationToken);
|
||||
_ = await this.MakeInvokeRequestAsync(appId, methodName, serializedData, httpExtension, cancellationToken);
|
||||
}
|
||||
|
||||
public override async ValueTask<TResponse> InvokeMethodAsync<TResponse>(
|
||||
string appId,
|
||||
string methodName,
|
||||
Dictionary<string, string> metadata = default,
|
||||
Http.HTTPExtension httpExtension = default,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(appId, nameof(appId));
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(methodName, nameof(methodName));
|
||||
|
||||
var response = await this.MakeInvokeRequestAsync(appId, methodName, null, metadata, cancellationToken);
|
||||
var response = await this.MakeInvokeRequestAsync(appId, methodName, null, httpExtension, cancellationToken);
|
||||
if (response.Data.Value.IsEmpty)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var responseData = response.Data.Value.ToStringUtf8();
|
||||
return JsonSerializer.Deserialize<TResponse>(responseData, this.jsonSerializerOptions);
|
||||
return ConvertFromInvokeResponse<TResponse>(response, this.jsonSerializerOptions);
|
||||
}
|
||||
|
||||
public override async ValueTask<TResponse> InvokeMethodAsync<TRequest, TResponse>(
|
||||
string appId,
|
||||
string methodName,
|
||||
TRequest data,
|
||||
Dictionary<string, string> metadata = default,
|
||||
Http.HTTPExtension httpExtension = default,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(appId, nameof(appId));
|
||||
|
|
@ -176,45 +175,64 @@ namespace Dapr.Client
|
|||
serializedData = ConvertToAnyAsync(data, this.jsonSerializerOptions);
|
||||
}
|
||||
|
||||
var response = await this.MakeInvokeRequestAsync(appId, methodName, serializedData, metadata, cancellationToken);
|
||||
var response = await this.MakeInvokeRequestAsync(appId, methodName, serializedData, httpExtension, cancellationToken);
|
||||
if (response.Data.Value.IsEmpty)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var responseData = response.Data.Value.ToStringUtf8();
|
||||
return JsonSerializer.Deserialize<TResponse>(responseData, this.jsonSerializerOptions);
|
||||
return ConvertFromInvokeResponse<TResponse>(response, this.jsonSerializerOptions);
|
||||
}
|
||||
|
||||
private async Task<InvokeServiceResponseEnvelope> MakeInvokeRequestAsync(
|
||||
private async Task<InvokeResponse> MakeInvokeRequestAsync(
|
||||
string appId,
|
||||
string methodName,
|
||||
Any data,
|
||||
Dictionary<string, string> metadata = default,
|
||||
Http.HTTPExtension httpExtension,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var envelope = new Autogenerated.InvokeServiceEnvelope()
|
||||
Autogenerated.HTTPExtension protoHTTPExtension = null;
|
||||
string contentType = "";
|
||||
|
||||
if (httpExtension != null)
|
||||
{
|
||||
Id = appId,
|
||||
Method = methodName
|
||||
protoHTTPExtension = new Autogenerated.HTTPExtension()
|
||||
{
|
||||
Verb = ConvertHTTPVerb(httpExtension.Verb)
|
||||
};
|
||||
|
||||
if (httpExtension.QueryString != null)
|
||||
{
|
||||
foreach (var kv in httpExtension.QueryString)
|
||||
{
|
||||
protoHTTPExtension.Querystring.Add(kv.Key, kv.Value);
|
||||
}
|
||||
}
|
||||
|
||||
contentType = httpExtension.ContentType == null ? "application/json" : httpExtension.ContentType;
|
||||
}
|
||||
|
||||
var invokeRequest = new InvokeRequest()
|
||||
{
|
||||
Method = methodName,
|
||||
Data = data,
|
||||
ContentType = contentType,
|
||||
HttpExtension = protoHTTPExtension
|
||||
};
|
||||
|
||||
if (data != null)
|
||||
var request = new Autogenerated.InvokeServiceRequest()
|
||||
{
|
||||
envelope.Data = data;
|
||||
}
|
||||
|
||||
if (metadata != null)
|
||||
{
|
||||
envelope.Metadata.Add(metadata);
|
||||
}
|
||||
|
||||
Id = appId,
|
||||
Message = invokeRequest,
|
||||
};
|
||||
|
||||
return await this.MakeGrpcCallHandleError(
|
||||
(options) =>
|
||||
{
|
||||
return client.InvokeServiceAsync(envelope, options);
|
||||
},
|
||||
cancellationToken);
|
||||
(options) =>
|
||||
{
|
||||
return client.InvokeServiceAsync(request, options);
|
||||
},
|
||||
cancellationToken);
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
|
@ -502,7 +520,7 @@ namespace Dapr.Client
|
|||
{
|
||||
var callOptions = new CallOptions(cancellationToken: cancellationToken);
|
||||
|
||||
// COmmon Exception Handling logic can be added here for all calls.
|
||||
// Common Exception Handling logic can be added here for all calls.
|
||||
return await callFunc.Invoke(callOptions);
|
||||
}
|
||||
|
||||
|
|
@ -517,7 +535,7 @@ namespace Dapr.Client
|
|||
|
||||
if (stateOptions.Concurrency != null)
|
||||
{
|
||||
stateRequestOptions.Concurrency = GetStringForConcurrencyMode(stateOptions.Concurrency.Value);
|
||||
stateRequestOptions.Concurrency = GetStringForConcurrencyMode(stateOptions.Concurrency.Value);
|
||||
}
|
||||
|
||||
if (stateOptions.RetryOptions != null)
|
||||
|
|
@ -552,12 +570,43 @@ namespace Dapr.Client
|
|||
{
|
||||
var bytes = JsonSerializer.SerializeToUtf8Bytes(data, options);
|
||||
any.Value = ByteString.CopyFrom(bytes);
|
||||
|
||||
}
|
||||
|
||||
return any;
|
||||
}
|
||||
|
||||
private static T ConvertFromInvokeResponse<T>(InvokeResponse response, JsonSerializerOptions options = null)
|
||||
{
|
||||
var responseData = response.Data.Value.ToStringUtf8();
|
||||
return JsonSerializer.Deserialize<T>(responseData, options);
|
||||
}
|
||||
|
||||
private static Autogenerated.HTTPExtension.Types.Verb ConvertHTTPVerb(HTTPVerb verb)
|
||||
{
|
||||
switch (verb)
|
||||
{
|
||||
case HTTPVerb.Get:
|
||||
return Autogenerated.HTTPExtension.Types.Verb.Get;
|
||||
case HTTPVerb.Head:
|
||||
return Autogenerated.HTTPExtension.Types.Verb.Head;
|
||||
case HTTPVerb.Post:
|
||||
return Autogenerated.HTTPExtension.Types.Verb.Post;
|
||||
case HTTPVerb.Put:
|
||||
return Autogenerated.HTTPExtension.Types.Verb.Put;
|
||||
case HTTPVerb.Delete:
|
||||
return Autogenerated.HTTPExtension.Types.Verb.Delete;
|
||||
case HTTPVerb.Connect:
|
||||
return Autogenerated.HTTPExtension.Types.Verb.Connect;
|
||||
case HTTPVerb.Options:
|
||||
return Autogenerated.HTTPExtension.Types.Verb.Options;
|
||||
case HTTPVerb.Trace:
|
||||
return Autogenerated.HTTPExtension.Types.Verb.Trace;
|
||||
default:
|
||||
throw new NotImplementedException(
|
||||
string.Format("Service invocation with verb '{0}' is not supported", verb.ToString()));
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetStringForConsistencyMode(ConsistencyMode consistencyMode)
|
||||
{
|
||||
if (consistencyMode.Equals(ConsistencyMode.Eventual))
|
||||
|
|
@ -571,7 +620,7 @@ namespace Dapr.Client
|
|||
}
|
||||
|
||||
throw new ArgumentException($"{consistencyMode.ToString()} Consistency Mode is not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetStringForConcurrencyMode(ConcurrencyMode concurrencyMode)
|
||||
{
|
||||
|
|
@ -605,3 +654,4 @@ namespace Dapr.Client
|
|||
#endregion Helper Methods
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
namespace Dapr.Client.Http
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// This class is only needed if the app you are calling is listening on HTTP.
|
||||
/// It contains propertes that represent data may be populated for an HTTP receiver.
|
||||
/// </summary>
|
||||
public class HTTPExtension
|
||||
{
|
||||
/// <summary>
|
||||
/// The constructor.
|
||||
/// </summary>
|
||||
public HTTPExtension()
|
||||
{
|
||||
this.Verb = HTTPVerb.Post;
|
||||
this.QueryString = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The HTTP Content-Type
|
||||
/// </summary>
|
||||
public string ContentType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This is the HTTP verb.
|
||||
/// </summary>
|
||||
public HTTPVerb Verb { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// This represents a collection of query strings.
|
||||
/// </summary>
|
||||
public Dictionary<string, string> QueryString { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
namespace Dapr.Client.Http
|
||||
{
|
||||
/// <summary>
|
||||
/// The HTTP verb to use for this message.
|
||||
/// </summary>
|
||||
public enum HTTPVerb
|
||||
{
|
||||
/// <summary>
|
||||
/// The HTTP verb GET
|
||||
/// </summary>
|
||||
Get,
|
||||
|
||||
/// <summary>
|
||||
/// The HTTP verb HEAD
|
||||
/// </summary>
|
||||
Head,
|
||||
|
||||
/// <summary>
|
||||
/// The HTTP verb POST
|
||||
/// </summary>
|
||||
Post,
|
||||
|
||||
/// <summary>
|
||||
/// The HTTP verb PUT
|
||||
/// </summary>
|
||||
Put,
|
||||
|
||||
/// <summary>
|
||||
/// The HTTP verb DELETE
|
||||
/// </summary>
|
||||
Delete,
|
||||
|
||||
/// <summary>
|
||||
/// The HTTP verb CONNECT
|
||||
/// </summary>
|
||||
Connect,
|
||||
|
||||
/// <summary>
|
||||
/// The HTTP verb OPTIONS
|
||||
/// </summary>
|
||||
Options,
|
||||
|
||||
/// <summary>
|
||||
/// The HTTP verb TRACE
|
||||
/// </summary>
|
||||
Trace
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package dapr.proto.common.v1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
|
||||
option csharp_namespace = "Dapr.Client.Autogen.Grpc.v1";
|
||||
option java_outer_classname = "CommonProtos";
|
||||
option java_package = "io.dapr.v1";
|
||||
option go_package = "github.com/dapr/dapr/pkg/proto/common/v1";
|
||||
|
||||
// HTTPExtension includes HTTP verb and querystring
|
||||
// when Dapr runtime delivers HTTP content.
|
||||
//
|
||||
// For example, when callers calls http invoke api
|
||||
// POST http://localhost:3500/v1.0/invoke/<app_id>/method/<method>?query1=value1&query2=value2
|
||||
//
|
||||
// Dapr runtime will parse POST as a verb and extract querystring to quersytring map.
|
||||
message HTTPExtension {
|
||||
// Type of HTTP 1.1 Methods
|
||||
// RFC 7231: https://tools.ietf.org/html/rfc7231#page-24
|
||||
enum Verb {
|
||||
NONE = 0;
|
||||
GET = 1;
|
||||
HEAD = 2;
|
||||
POST = 3;
|
||||
PUT = 4;
|
||||
DELETE = 5;
|
||||
CONNECT = 6;
|
||||
OPTIONS = 7;
|
||||
TRACE = 8;
|
||||
}
|
||||
|
||||
// verb is HTTP verb.
|
||||
//
|
||||
// This is required.
|
||||
Verb verb = 1;
|
||||
|
||||
// querystring includes HTTP querystring.
|
||||
map<string, string> querystring = 2;
|
||||
}
|
||||
|
||||
message InvokeRequest {
|
||||
// method is a method name which will be invoked by caller.
|
||||
//
|
||||
// This field is required.
|
||||
string method = 1;
|
||||
|
||||
// data conveys bytes value or Protobuf message which caller sent.
|
||||
// Dapr treats Any.value as bytes type if Any.type_url is unset.
|
||||
//
|
||||
// This field is required.
|
||||
google.protobuf.Any data = 2;
|
||||
|
||||
// content_type is the type of data content.
|
||||
//
|
||||
// This field is required if data delivers http request body
|
||||
// Otherwise, this is optional.
|
||||
string content_type = 3;
|
||||
|
||||
// http_extension includes http specific fields if request conveys
|
||||
// http-compatible request.
|
||||
//
|
||||
// This field is optional.
|
||||
HTTPExtension http_extension = 4;
|
||||
}
|
||||
|
||||
message InvokeResponse {
|
||||
// data conveys the content body of InvokeService response.
|
||||
//
|
||||
// This field is required.
|
||||
google.protobuf.Any data = 1;
|
||||
|
||||
// content_type is the type of data content.
|
||||
//
|
||||
// This field is required.
|
||||
string content_type = 2;
|
||||
}
|
||||
|
|
@ -1,21 +1,26 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package dapr;
|
||||
package dapr.proto.dapr.v1;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
import "dapr/proto/common/v1/common.proto";
|
||||
|
||||
option csharp_namespace = "Dapr.Client.Autogen.Grpc.v1";
|
||||
option java_outer_classname = "DaprProtos";
|
||||
option java_package = "io.dapr";
|
||||
option java_package = "io.dapr.v1";
|
||||
option go_package = "github.com/dapr/dapr/pkg/proto/dapr/v1";
|
||||
|
||||
option csharp_namespace = "Dapr.Client.Autogen.Grpc";
|
||||
|
||||
|
||||
// Dapr definitions
|
||||
// Dapr service provides APIs to user application to access Dapr building blocks.
|
||||
service Dapr {
|
||||
rpc PublishEvent(PublishEventEnvelope) returns (google.protobuf.Empty) {}
|
||||
rpc InvokeService(InvokeServiceEnvelope) returns (InvokeServiceResponseEnvelope) {}
|
||||
rpc InvokeService(InvokeServiceRequest) returns (common.v1.InvokeResponse) {}
|
||||
rpc InvokeBinding(InvokeBindingEnvelope) returns (google.protobuf.Empty) {}
|
||||
rpc GetState(GetStateEnvelope) returns (GetStateResponseEnvelope) {}
|
||||
rpc GetSecret(GetSecretEnvelope) returns (GetSecretResponseEnvelope) {}
|
||||
|
|
@ -23,27 +28,35 @@ service Dapr {
|
|||
rpc DeleteState(DeleteStateEnvelope) returns (google.protobuf.Empty) {}
|
||||
}
|
||||
|
||||
message InvokeServiceResponseEnvelope {
|
||||
google.protobuf.Any data = 1;
|
||||
map<string,string> metadata = 2;
|
||||
// InvokeServiceRequest represents the request message for Service invocation.
|
||||
message InvokeServiceRequest {
|
||||
// id specifies callee's app id.
|
||||
//
|
||||
// This field is required.
|
||||
string id = 1;
|
||||
|
||||
// message which will be delivered to callee.
|
||||
//
|
||||
// This field is required.
|
||||
common.v1.InvokeRequest message = 3;
|
||||
}
|
||||
|
||||
message DeleteStateEnvelope {
|
||||
string storeName = 1;
|
||||
string store_name = 1;
|
||||
string key = 2;
|
||||
string etag = 3;
|
||||
StateOptions options = 4;
|
||||
}
|
||||
|
||||
message SaveStateEnvelope {
|
||||
string storeName = 1;
|
||||
string store_name = 1;
|
||||
repeated StateRequest requests = 2;
|
||||
}
|
||||
|
||||
message GetStateEnvelope {
|
||||
string storeName = 1;
|
||||
string key = 2;
|
||||
string consistency = 3;
|
||||
string store_name = 1;
|
||||
string key = 2;
|
||||
string consistency = 3;
|
||||
}
|
||||
|
||||
message GetStateResponseEnvelope {
|
||||
|
|
@ -52,7 +65,7 @@ message GetStateResponseEnvelope {
|
|||
}
|
||||
|
||||
message GetSecretEnvelope {
|
||||
string storeName = 1;
|
||||
string store_name = 1;
|
||||
string key = 2;
|
||||
map<string,string> metadata = 3;
|
||||
}
|
||||
|
|
@ -67,16 +80,9 @@ message InvokeBindingEnvelope {
|
|||
map<string,string> metadata = 3;
|
||||
}
|
||||
|
||||
message InvokeServiceEnvelope {
|
||||
string id = 1;
|
||||
string method = 2;
|
||||
google.protobuf.Any data = 3;
|
||||
map<string,string> metadata = 4;
|
||||
}
|
||||
|
||||
message PublishEventEnvelope {
|
||||
string topic = 1;
|
||||
google.protobuf.Any data = 2;
|
||||
string topic = 1;
|
||||
google.protobuf.Any data = 2;
|
||||
}
|
||||
|
||||
message State {
|
||||
|
|
@ -90,7 +96,7 @@ message State {
|
|||
message StateOptions {
|
||||
string concurrency = 1;
|
||||
string consistency = 2;
|
||||
RetryPolicy retryPolicy = 3;
|
||||
RetryPolicy retry_policy = 3;
|
||||
}
|
||||
|
||||
message RetryPolicy {
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
syntax = "proto3";
|
||||
|
||||
package daprclient;
|
||||
|
||||
import "google/protobuf/any.proto";
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/duration.proto";
|
||||
|
||||
option java_outer_classname = "DaprClientProtos";
|
||||
option java_package = "io.dapr";
|
||||
|
||||
// User Code definitions
|
||||
service DaprClient {
|
||||
rpc OnInvoke (InvokeEnvelope) returns (google.protobuf.Any) {}
|
||||
rpc GetTopicSubscriptions(google.protobuf.Empty) returns (GetTopicSubscriptionsEnvelope) {}
|
||||
rpc GetBindingsSubscriptions(google.protobuf.Empty) returns (GetBindingsSubscriptionsEnvelope) {}
|
||||
rpc OnBindingEvent(BindingEventEnvelope) returns (BindingResponseEnvelope) {}
|
||||
rpc OnTopicEvent(CloudEventEnvelope) returns (google.protobuf.Empty) {}
|
||||
}
|
||||
|
||||
message CloudEventEnvelope {
|
||||
string id = 1;
|
||||
string source = 2;
|
||||
string type = 3;
|
||||
string specVersion = 4;
|
||||
string dataContentType = 5;
|
||||
string topic = 6;
|
||||
google.protobuf.Any data = 7;
|
||||
}
|
||||
|
||||
message BindingEventEnvelope {
|
||||
string name = 1;
|
||||
google.protobuf.Any data = 2;
|
||||
map<string,string> metadata = 3;
|
||||
}
|
||||
|
||||
message BindingResponseEnvelope {
|
||||
google.protobuf.Any data = 1;
|
||||
repeated string to = 2;
|
||||
repeated State state = 3;
|
||||
string concurrency = 4;
|
||||
}
|
||||
|
||||
message InvokeEnvelope {
|
||||
string method = 1;
|
||||
google.protobuf.Any data = 2;
|
||||
map<string,string> metadata = 3;
|
||||
}
|
||||
|
||||
message GetTopicSubscriptionsEnvelope {
|
||||
repeated string topics = 1;
|
||||
}
|
||||
|
||||
message GetBindingsSubscriptionsEnvelope {
|
||||
repeated string bindings = 1;
|
||||
}
|
||||
|
||||
message State {
|
||||
string key = 1;
|
||||
google.protobuf.Any value = 2;
|
||||
string etag = 3;
|
||||
map<string,string> metadata = 4;
|
||||
StateOptions options = 5;
|
||||
}
|
||||
|
||||
message StateOptions {
|
||||
string concurrency = 1;
|
||||
string consistency = 2;
|
||||
RetryPolicy retryPolicy = 3;
|
||||
}
|
||||
|
||||
message RetryPolicy {
|
||||
int32 threshold = 1;
|
||||
string pattern = 2;
|
||||
google.protobuf.Duration interval = 3;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
|
@ -53,4 +53,4 @@ namespace Dapr.Extensions.Configuration
|
|||
public static IConfigurationBuilder AddDaprSecretStore(this IConfigurationBuilder configurationBuilder, Action<DaprSecretStoreConfigurationSource> configureSource)
|
||||
=> configurationBuilder.Add(configureSource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
|
@ -62,4 +62,4 @@ namespace Dapr.Extensions.Configuration.DaprSecretStore
|
|||
Data = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
|
@ -35,4 +35,4 @@ namespace Dapr.Extensions.Configuration.DaprSecretStore
|
|||
return new DaprSecretStoreConfigurationProvider(Store, SecretDescriptors, Client);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,19 +6,11 @@
|
|||
namespace Dapr.AspNetCore.Test
|
||||
{
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr.Client;
|
||||
using Dapr.Client.Autogen.Grpc;
|
||||
using Dapr.Client.Autogen.Grpc.v1;
|
||||
using FluentAssertions;
|
||||
using Google.Protobuf;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Grpc.Core;
|
||||
using Grpc.Net.Client;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
|
@ -69,7 +61,7 @@ namespace Dapr.AspNetCore.Test
|
|||
|
||||
context.ValidationState.Count.Should().Be(1);
|
||||
context.ValidationState[context.Result.Model].SuppressValidation.Should().BeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindAsync_CanBindStateEntry()
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ namespace Dapr.Client.Test
|
|||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr.Client.Autogen.Grpc;
|
||||
using Dapr.Client.Autogen.Grpc.v1;
|
||||
using Dapr.Client.Http;
|
||||
using FluentAssertions;
|
||||
using Grpc.Core;
|
||||
using Grpc.Net.Client;
|
||||
|
|
@ -26,21 +27,31 @@ namespace Dapr.Client.Test
|
|||
.UseGrpcChannelOptions(new GrpcChannelOptions { HttpClient = httpClient })
|
||||
.Build();
|
||||
|
||||
var metadata = new Dictionary<string, string>();
|
||||
metadata.Add("key1", "value1");
|
||||
metadata.Add("key2", "value2");
|
||||
var task = daprClient.InvokeMethodAsync<InvokedResponse>("test", "test", metadata);
|
||||
var queryString = new Dictionary<string, string>();
|
||||
queryString.Add("key1", "value1");
|
||||
queryString.Add("key2", "value2");
|
||||
|
||||
var httpExtension = new Http.HTTPExtension()
|
||||
{
|
||||
Verb = HTTPVerb.Post,
|
||||
QueryString = queryString
|
||||
};
|
||||
|
||||
var task = daprClient.InvokeMethodAsync<InvokedResponse>("app1", "mymethod", httpExtension);
|
||||
|
||||
// Get Request and validate
|
||||
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceEnvelope>(entry.Request);
|
||||
envelope.Id.Should().Be("test");
|
||||
envelope.Method.Should().Be("test");
|
||||
envelope.Metadata.Count.Should().Be(2);
|
||||
envelope.Metadata.Keys.Contains("key1").Should().BeTrue();
|
||||
envelope.Metadata.Keys.Contains("key2").Should().BeTrue();
|
||||
envelope.Metadata["key1"].Should().Be("value1");
|
||||
envelope.Metadata["key2"].Should().Be("value2");
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceRequest>(entry.Request);
|
||||
|
||||
envelope.Id.Should().Be("app1");
|
||||
envelope.Message.Method.Should().Be("mymethod");
|
||||
|
||||
envelope.Message.HttpExtension.Verb.Should().Be(Autogen.Grpc.v1.HTTPExtension.Types.Verb.Post);
|
||||
envelope.Message.HttpExtension.Querystring.Count.Should().Be(2);
|
||||
envelope.Message.HttpExtension.Querystring.ContainsKey("key1").Should().BeTrue();
|
||||
envelope.Message.HttpExtension.Querystring.ContainsKey("key2").Should().BeTrue();
|
||||
envelope.Message.HttpExtension.Querystring["key1"].Should().Be("value1");
|
||||
envelope.Message.HttpExtension.Querystring["key2"].Should().Be("value2");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -53,12 +64,12 @@ namespace Dapr.Client.Test
|
|||
.Build();
|
||||
|
||||
var task = daprClient.InvokeMethodAsync<InvokedResponse>("test", "test");
|
||||
|
||||
|
||||
// Get Request and validate
|
||||
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceEnvelope>(entry.Request);
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceRequest>(entry.Request);
|
||||
envelope.Id.Should().Be("test");
|
||||
envelope.Method.Should().Be("test");
|
||||
envelope.Message.Method.Should().Be("test");
|
||||
|
||||
// Create Response & Respond
|
||||
var data = new InvokedResponse() { Name = "Look, I was invoked!" };
|
||||
|
|
@ -82,10 +93,11 @@ namespace Dapr.Client.Test
|
|||
|
||||
// Get Request and validate
|
||||
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceEnvelope>(entry.Request);
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceRequest>(entry.Request);
|
||||
envelope.Id.Should().Be("test");
|
||||
envelope.Method.Should().Be("test");
|
||||
var json = envelope.Data.Value.ToStringUtf8();
|
||||
envelope.Message.Method.Should().Be("test");
|
||||
|
||||
var json = envelope.Message.Data.Value.ToStringUtf8();
|
||||
var typeFromRequest = JsonSerializer.Deserialize<InvokeRequest>(json);
|
||||
typeFromRequest.RequestParameter.Should().Be("Hello ");
|
||||
|
||||
|
|
@ -111,10 +123,11 @@ namespace Dapr.Client.Test
|
|||
|
||||
// Get Request and validate
|
||||
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceEnvelope>(entry.Request);
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceRequest>(entry.Request);
|
||||
envelope.Id.Should().Be("test");
|
||||
envelope.Method.Should().Be("test");
|
||||
var json = envelope.Data.Value.ToStringUtf8();
|
||||
envelope.Message.Method.Should().Be("test");
|
||||
|
||||
var json = envelope.Message.Data.Value.ToStringUtf8();
|
||||
var typeFromRequest = JsonSerializer.Deserialize<InvokeRequest>(json);
|
||||
typeFromRequest.RequestParameter.Should().Be("Hello ");
|
||||
|
||||
|
|
@ -139,9 +152,9 @@ namespace Dapr.Client.Test
|
|||
|
||||
// Get Request and validate
|
||||
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceEnvelope>(entry.Request);
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceRequest>(entry.Request);
|
||||
envelope.Id.Should().Be("test");
|
||||
envelope.Method.Should().Be("test");
|
||||
envelope.Message.Method.Should().Be("test");
|
||||
|
||||
// Create Response & Respond
|
||||
var data = new InvokedResponse() { Name = "Look, I was invoked!" };
|
||||
|
|
@ -165,9 +178,9 @@ namespace Dapr.Client.Test
|
|||
|
||||
// Get Request and validate
|
||||
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceEnvelope>(entry.Request);
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceRequest>(entry.Request);
|
||||
envelope.Id.Should().Be("test");
|
||||
envelope.Method.Should().Be("test");
|
||||
envelope.Message.Method.Should().Be("test");
|
||||
|
||||
// Create Response & Respond
|
||||
var response = GrpcUtils.CreateResponse(HttpStatusCode.NotAcceptable);
|
||||
|
|
@ -186,20 +199,22 @@ namespace Dapr.Client.Test
|
|||
.UseGrpcChannelOptions(new GrpcChannelOptions { HttpClient = httpClient })
|
||||
.Build();
|
||||
|
||||
var task = daprClient.InvokeMethodAsync<InvokeRequest>("test", "test", new InvokeRequest() { RequestParameter = "Hello " });
|
||||
InvokeRequest invokeRequest = new InvokeRequest() { RequestParameter = "Hello " };
|
||||
var task = daprClient.InvokeMethodAsync<InvokeRequest>("test", "test", invokeRequest);
|
||||
|
||||
// Get Request and validate
|
||||
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceEnvelope>(entry.Request);
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceRequest>(entry.Request);
|
||||
envelope.Id.Should().Be("test");
|
||||
envelope.Method.Should().Be("test");
|
||||
var json = envelope.Data.Value.ToStringUtf8();
|
||||
envelope.Message.Method.Should().Be("test");
|
||||
|
||||
var json = envelope.Message.Data.Value.ToStringUtf8();
|
||||
var typeFromRequest = JsonSerializer.Deserialize<InvokeRequest>(json);
|
||||
typeFromRequest.RequestParameter.Should().Be("Hello ");
|
||||
|
||||
// Create Response & Respond
|
||||
var data = new InvokedResponse() { Name = "Look, I was invoked!" };
|
||||
SendResponse(data, entry);
|
||||
var response = new InvokedResponse() { Name = "Look, I was invoked!" };
|
||||
SendResponse(response, entry);
|
||||
|
||||
FluentActions.Awaiting(async () => await task).Should().NotThrow();
|
||||
}
|
||||
|
|
@ -217,10 +232,10 @@ namespace Dapr.Client.Test
|
|||
|
||||
// Get Request and validate
|
||||
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceEnvelope>(entry.Request);
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceRequest>(entry.Request);
|
||||
envelope.Id.Should().Be("test");
|
||||
envelope.Method.Should().Be("test");
|
||||
var json = envelope.Data.Value.ToStringUtf8();
|
||||
envelope.Message.Method.Should().Be("test");
|
||||
var json = envelope.Message.Data.Value.ToStringUtf8();
|
||||
var typeFromRequest = JsonSerializer.Deserialize<InvokeRequest>(json);
|
||||
typeFromRequest.RequestParameter.Should().Be("Hello ");
|
||||
|
||||
|
|
@ -248,17 +263,17 @@ namespace Dapr.Client.Test
|
|||
|
||||
// Get Request and validate
|
||||
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceEnvelope>(entry.Request);
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceRequest>(entry.Request);
|
||||
envelope.Id.Should().Be("test");
|
||||
envelope.Method.Should().Be("test");
|
||||
var json = envelope.Data.Value.ToStringUtf8();
|
||||
envelope.Message.Method.Should().Be("test");
|
||||
|
||||
var json = envelope.Message.Data.Value.ToStringUtf8();
|
||||
json.Should().Be(JsonSerializer.Serialize(invokeRequest, jsonOptions));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeMethodAsync_WithReturnTypeAndData_UsesConfiguredJsonSerializerOptions()
|
||||
{
|
||||
{
|
||||
// Configure Client
|
||||
var httpClient = new TestHttpClient();
|
||||
var jsonOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
|
||||
|
|
@ -274,10 +289,55 @@ namespace Dapr.Client.Test
|
|||
|
||||
// Get Request and validate
|
||||
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceEnvelope>(entry.Request);
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceRequest>(entry.Request);
|
||||
envelope.Id.Should().Be("test");
|
||||
envelope.Method.Should().Be("test");
|
||||
var json = envelope.Data.Value.ToStringUtf8();
|
||||
envelope.Message.Method.Should().Be("test");
|
||||
|
||||
var json = envelope.Message.Data.Value.ToStringUtf8();
|
||||
json.Should().Be(JsonSerializer.Serialize(invokeRequest, jsonOptions));
|
||||
|
||||
SendResponse(invokedResponse, entry, jsonOptions);
|
||||
var response = await task;
|
||||
|
||||
response.Name.Should().Be(invokedResponse.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task InvokeMethodAsync_WithReturnTypeAndData_WithNonDefaultVerb_WithQueryString_UsesConfiguredJsonSerializerOptions()
|
||||
{
|
||||
// Configure Client
|
||||
var httpClient = new TestHttpClient();
|
||||
var jsonOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
|
||||
var daprClient = new DaprClientBuilder()
|
||||
.UseGrpcChannelOptions(new GrpcChannelOptions { HttpClient = httpClient })
|
||||
.UseJsonSerializationOptions(jsonOptions)
|
||||
.Build();
|
||||
|
||||
var invokeRequest = new InvokeRequest() { RequestParameter = "Hello " };
|
||||
var invokedResponse = new InvokedResponse { Name = "Look, I was invoked!" };
|
||||
|
||||
Dictionary<string, string> queryString = new Dictionary<string, string>();
|
||||
queryString.Add("key1", "value1");
|
||||
var httpExtension = new Http.HTTPExtension()
|
||||
{
|
||||
Verb = HTTPVerb.Put,
|
||||
QueryString = queryString
|
||||
};
|
||||
|
||||
var task = daprClient.InvokeMethodAsync<InvokeRequest, InvokedResponse>("test", "test", invokeRequest, httpExtension);
|
||||
|
||||
// Get Request and validate
|
||||
httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
|
||||
var envelope = await GrpcUtils.GetEnvelopeFromRequestMessageAsync<InvokeServiceRequest>(entry.Request);
|
||||
envelope.Id.Should().Be("test");
|
||||
envelope.Message.Method.Should().Be("test");
|
||||
envelope.Message.HttpExtension.Verb.Should().Be(Autogen.Grpc.v1.HTTPExtension.Types.Verb.Put);
|
||||
envelope.Message.HttpExtension.Querystring.Count.Should().Be(1);
|
||||
envelope.Message.HttpExtension.Querystring.ContainsKey("key1").Should().BeTrue();
|
||||
envelope.Message.HttpExtension.Querystring["key1"].Should().Be("value1");
|
||||
|
||||
|
||||
var json = envelope.Message.Data.Value.ToStringUtf8();
|
||||
json.Should().Be(JsonSerializer.Serialize(invokeRequest, jsonOptions));
|
||||
|
||||
SendResponse(invokedResponse, entry, jsonOptions);
|
||||
|
|
@ -289,7 +349,7 @@ namespace Dapr.Client.Test
|
|||
private async void SendResponse<T>(T data, TestHttpClient.Entry entry, JsonSerializerOptions options = null)
|
||||
{
|
||||
var dataAny = ProtobufUtils.ConvertToAnyAsync(data, options);
|
||||
var dataResponse = new InvokeServiceResponseEnvelope();
|
||||
var dataResponse = new InvokeResponse();
|
||||
dataResponse.Data = dataAny;
|
||||
|
||||
var streamContent = await GrpcUtils.CreateResponseContent(dataResponse);
|
||||
|
|
|
|||
|
|
@ -6,12 +6,10 @@
|
|||
namespace Dapr.Client.Test
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr.Client.Autogen.Grpc;
|
||||
using Dapr.Client.Autogen.Grpc.v1;
|
||||
using FluentAssertions;
|
||||
using Grpc.Core;
|
||||
using Grpc.Net.Client;
|
||||
using Xunit;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ namespace Dapr.Client.Test
|
|||
{
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr.Client.Autogen.Grpc;
|
||||
using Dapr.Client.Autogen.Grpc.v1;
|
||||
using FluentAssertions;
|
||||
using Grpc.Net.Client;
|
||||
using Xunit;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ namespace Dapr.Client.Test
|
|||
using FluentAssertions;
|
||||
using Grpc.Net.Client;
|
||||
using Xunit;
|
||||
using Autogenerated = Dapr.Client.Autogen.Grpc;
|
||||
using Autogenerated = Dapr.Client.Autogen.Grpc.v1;
|
||||
|
||||
public class SecretApiTest
|
||||
{
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace Dapr.Client.Test
|
|||
using System.Net;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Autogenerated = Dapr.Client.Autogen.Grpc;
|
||||
using Autogenerated = Dapr.Client.Autogen.Grpc.v1;
|
||||
using FluentAssertions;
|
||||
using Grpc.Core;
|
||||
using Grpc.Net.Client;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
// ------------------------------------------------------------
|
||||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Autogenerated = Dapr.Client.Autogen.Grpc;
|
||||
using Autogenerated = Dapr.Client.Autogen.Grpc.v1;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
|
@ -84,4 +84,4 @@ namespace Dapr.Extensions.Configuration.Test
|
|||
return new ConfigurationBuilder();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue