public async Task BindAsync_CanBindStateEntry()
        {
            var binder = new StateEntryModelBinder("testStore", "id", isStateEntry: true, typeof(Widget));

            // Configure Client
            var httpClient = new TestHttpClient();
            var context    = CreateContext(CreateServices(httpClient));

            context.HttpContext.Request.RouteValues["id"] = "test";
            var task = binder.BindModelAsync(context);

            // Create Response & Respond
            var state = new Widget()
            {
                Size = "small", Color = "yellow",
            };

            httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
            SendResponseWithState(state, entry);

            // Get response and validate
            await task;

            context.Result.IsModelSet.Should().BeTrue();
            context.Result.Model.As <StateEntry <Widget> >().Key.Should().Be("test");
            context.Result.Model.As <StateEntry <Widget> >().Value.Size.Should().Be("small");
            context.Result.Model.As <StateEntry <Widget> >().Value.Color.Should().Be("yellow");

            context.ValidationState.Count.Should().Be(1);
            context.ValidationState[context.Result.Model].SuppressValidation.Should().BeTrue();
        }
        public async Task BindAsync_CanBindStateEntry()
        {
            await using var client = TestClient.CreateForDaprClient();

            var binder = new StateEntryModelBinder("testStore", "id", isStateEntry: true, typeof(Widget));

            // Configure Client
            var context = CreateContext(CreateServices(client.InnerClient));

            context.HttpContext.Request.RouteValues["id"] = "test";

            var request = await client.CaptureGrpcRequestAsync(async _ =>
            {
                await binder.BindModelAsync(context);
            });

            // Create Response & Respond
            var state = new Widget()
            {
                Size = "small", Color = "yellow",
            };

            await SendResponseWithState(state, request);

            // Get response and validate
            context.Result.IsModelSet.Should().BeTrue();
            context.Result.Model.As <StateEntry <Widget> >().Key.Should().Be("test");
            context.Result.Model.As <StateEntry <Widget> >().Value.Size.Should().Be("small");
            context.Result.Model.As <StateEntry <Widget> >().Value.Color.Should().Be("yellow");

            context.ValidationState.Count.Should().Be(1);
            context.ValidationState[context.Result.Model].SuppressValidation.Should().BeTrue();
        }
        public async Task BindAsync_CanBindValue()
        {
            var binder = new StateEntryModelBinder("testStore", "id", isStateEntry: false, typeof(Widget));

            var httpClient = new TestHttpClient();
            var context    = CreateContext(CreateServices(httpClient));

            context.HttpContext.Request.RouteValues["id"] = "test";

            var task = binder.BindModelAsync(context);

            httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
            entry.RespondWithJson(new Widget()
            {
                Size = "small", Color = "yellow",
            });

            await task;

            context.Result.IsModelSet.Should().BeTrue();
            context.Result.Model.As <Widget>().Size.Should().Be("small");
            context.Result.Model.As <Widget>().Color.Should().Be("yellow");

            context.ValidationState.Count.Should().Be(1);
            context.ValidationState[context.Result.Model].SuppressValidation.Should().BeTrue();
        }
        public async Task BindAsync_WithoutMatchingRouteValue_ReportsError()
        {
            await using var client = TestClient.CreateForDaprClient();

            var binder  = new StateEntryModelBinder("testStore", "test", isStateEntry: false, typeof(Widget));
            var context = CreateContext(CreateServices(client.InnerClient));

            await binder.BindModelAsync(context);

            context.Result.IsModelSet.Should().BeFalse();
            context.ModelState.ErrorCount.Should().Be(1);
            context.ModelState["testParameter"].Errors.Count.Should().Be(1);

            // No request to state store, validated by disposing client
        }
        public async Task BindAsync_WithoutMatchingRouteValue_ReportsError()
        {
            var binder = new StateEntryModelBinder("testStore", "test", isStateEntry: false, typeof(Widget));

            var httpClient = new TestHttpClient();
            var context    = CreateContext(CreateServices(httpClient));

            await binder.BindModelAsync(context);

            context.Result.IsModelSet.Should().BeFalse();
            context.ModelState.ErrorCount.Should().Be(1);
            context.ModelState["testParameter"].Errors.Count.Should().Be(1);

            httpClient.Requests.Count.Should().Be(0);
        }
        public async Task BindAsync_WithStateEntry_ForNonExistentStateEntry()
        {
            var binder = new StateEntryModelBinder("testStore", "id", isStateEntry: true, typeof(Widget));

            // Configure Client
            var httpClient = new TestHttpClient();
            var context    = CreateContext(CreateServices(httpClient));

            context.HttpContext.Request.RouteValues["id"] = "test";
            var task = binder.BindModelAsync(context);

            httpClient.Requests.TryDequeue(out var entry).Should().BeTrue();
            await SendResponseWithState <string>(null, entry);

            await task;

            context.ModelState.IsValid.Should().BeTrue();
            context.Result.IsModelSet.Should().BeTrue();
            ((StateEntry <Widget>)context.Result.Model).Value.Should().BeNull();
        }
        public async Task BindAsync_WithStateEntry_ForNonExistentStateEntry()
        {
            await using var client = TestClient.CreateForDaprClient();

            var binder = new StateEntryModelBinder("testStore", "id", isStateEntry: true, typeof(Widget));

            // Configure Client
            var context = CreateContext(CreateServices(client.InnerClient));

            context.HttpContext.Request.RouteValues["id"] = "test";

            var request = await client.CaptureGrpcRequestAsync(async _ =>
            {
                await binder.BindModelAsync(context);
            });

            await SendResponseWithState <string>(null, request);

            context.ModelState.IsValid.Should().BeTrue();
            context.Result.IsModelSet.Should().BeTrue();
            ((StateEntry <Widget>)context.Result.Model).Value.Should().BeNull();
        }