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:
Leon Mai 2020-04-30 11:47:29 -07:00 committed by GitHub
parent c73afa9882
commit 44ca6496d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 528 additions and 304 deletions

View File

@ -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);

View File

@ -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; }
}
}
}

View File

@ -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);
});
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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
}
}

View File

@ -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; }
}
}

View File

@ -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
}
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -1,4 +1,4 @@
// ------------------------------------------------------------
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
// ------------------------------------------------------------
@ -62,4 +62,4 @@ namespace Dapr.Extensions.Configuration.DaprSecretStore
Data = data;
}
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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()

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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
{

View File

@ -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;

View File

@ -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();
}
}
}
}