mirror of https://github.com/dapr/dotnet-sdk.git
Fix the ArgumentNull exception (#537)
* Fix the ArgumentNull exception Co-authored-by: Sander Molenkamp <a.molenkamp@gmail.com> Co-authored-by: Ryan Nowak <nowakra@gmail.com>
This commit is contained in:
parent
4a193ec1ac
commit
ac7e20e070
|
|
@ -69,15 +69,26 @@ namespace Dapr.AspNetCore
|
|||
bindingContext.ModelState.TryAddModelError(bindingContext.ModelName, message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
var obj = await this.thunk(daprClient, this.storeName, key);
|
||||
bindingContext.Result = ModelBindingResult.Success(obj);
|
||||
|
||||
bindingContext.ValidationState.Add(bindingContext.Result.Model, new ValidationStateEntry()
|
||||
// When the state isn't found in the state store:
|
||||
// - If the StateEntryModelBinder is associated with a value of type StateEntry<T>, then the above call returns an object of type
|
||||
// StateEntry<T> which is non-null, but StateEntry<T>.Value is null
|
||||
// - If the StateEntryModelBinder is associated with a value of type T, then the above call returns a null value.
|
||||
if (obj == null)
|
||||
{
|
||||
// Don't do validation since the data came from a trusted source.
|
||||
SuppressValidation = true,
|
||||
});
|
||||
bindingContext.Result = ModelBindingResult.Failed();
|
||||
}
|
||||
else
|
||||
{
|
||||
bindingContext.Result = ModelBindingResult.Success(obj);
|
||||
bindingContext.ValidationState.Add(bindingContext.Result.Model, new ValidationStateEntry()
|
||||
{
|
||||
// Don't do validation since the data came from a trusted source.
|
||||
SuppressValidation = true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task<object> GetStateEntryAsync<T>(DaprClient daprClient, string storeName, string key)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
namespace Dapr.AspNetCore.IntegrationTest.App
|
||||
{
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr;
|
||||
using Dapr.Client;
|
||||
|
|
@ -53,5 +54,18 @@ namespace Dapr.AspNetCore.IntegrationTest.App
|
|||
// To simulate an action where there's no Dapr attribute, yet MVC still checks the list of available model binder providers.
|
||||
return user;
|
||||
}
|
||||
|
||||
[HttpGet("controllerwithoutstateentry/{widget}")]
|
||||
public ActionResult<Widget> Get([FromState("testStore")] Widget widget)
|
||||
{
|
||||
return widget;
|
||||
}
|
||||
|
||||
[HttpGet("controllerwithstateentry/{widgetStateEntry}")]
|
||||
public ActionResult<Widget> Get([FromState("testStore")] StateEntry<Widget> widgetStateEntry)
|
||||
{
|
||||
return widgetStateEntry.Value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,12 @@
|
|||
|
||||
namespace Dapr.AspNetCore.IntegrationTest
|
||||
{
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr.AspNetCore.IntegrationTest.App;
|
||||
using FluentAssertions;
|
||||
using Newtonsoft.Json;
|
||||
using Xunit;
|
||||
|
||||
public class ControllerIntegrationTest
|
||||
|
|
@ -32,6 +34,43 @@ namespace Dapr.AspNetCore.IntegrationTest
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelBinder_GetFromStateEntryWithKeyPresentInStateStore_ReturnsStateValue()
|
||||
{
|
||||
using (var factory = new AppWebApplicationFactory())
|
||||
{
|
||||
var httpClient = factory.CreateClient();
|
||||
var daprClient = factory.DaprClient;
|
||||
|
||||
var widget = new Widget() { Size = "small", Count = 17, };
|
||||
await daprClient.SaveStateAsync("testStore", "test", widget);
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/controllerwithoutstateentry/test");
|
||||
var response = await httpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
var responseWidget = JsonConvert.DeserializeObject<Widget>(responseContent);
|
||||
responseWidget.Size.Should().Be(widget.Size);
|
||||
responseWidget.Count.Should().Be(widget.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelBinder_GetFromStateEntryWithKeyNotInStateStore_ReturnsNull()
|
||||
{
|
||||
using (var factory = new AppWebApplicationFactory())
|
||||
{
|
||||
var httpClient = factory.CreateClient();
|
||||
var daprClient = factory.DaprClient;
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/controllerwithoutstateentry/test");
|
||||
var response = await httpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
var responseWidget = JsonConvert.DeserializeObject<Widget>(responseContent);
|
||||
Assert.Null(responseWidget);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelBinder_CanBindFromState_WithStateEntry()
|
||||
{
|
||||
|
|
@ -70,6 +109,43 @@ namespace Dapr.AspNetCore.IntegrationTest
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelBinder_GetFromStateEntryWithStateEntry_WithKeyPresentInStateStore()
|
||||
{
|
||||
using (var factory = new AppWebApplicationFactory())
|
||||
{
|
||||
var httpClient = factory.CreateClient();
|
||||
var daprClient = factory.DaprClient;
|
||||
|
||||
var widget = new Widget() { Size = "small", Count = 17, };
|
||||
await daprClient.SaveStateAsync("testStore", "test", widget);
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/controllerwithstateentry/test");
|
||||
var response = await httpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
var responseWidget = JsonConvert.DeserializeObject<Widget>(responseContent);
|
||||
responseWidget.Size.Should().Be(widget.Size);
|
||||
responseWidget.Count.Should().Be(widget.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelBinder_GetFromStateEntryWithStateEntry_WithKeyNotInStateStore()
|
||||
{
|
||||
using (var factory = new AppWebApplicationFactory())
|
||||
{
|
||||
var httpClient = factory.CreateClient();
|
||||
var daprClient = factory.DaprClient;
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/controllerwithstateentry/test");
|
||||
var response = await httpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
var responseWidget = JsonConvert.DeserializeObject<Widget>(responseContent);
|
||||
Assert.Null(responseWidget);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ModelBinder_CanGetOutOfTheWayWhenTheresNoBinding()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -90,6 +90,46 @@ namespace Dapr.AspNetCore.Test
|
|||
context.ValidationState[context.Result.Model].SuppressValidation.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BindAsync_ReturnsNullForNonExistentStateEntry()
|
||||
{
|
||||
var binder = new StateEntryModelBinder("testStore", "id", isStateEntry: false, 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().BeFalse();
|
||||
context.Result.Should().Be(ModelBindingResult.Failed());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
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();
|
||||
}
|
||||
|
||||
private static ModelBindingContext CreateContext(IServiceProvider services)
|
||||
{
|
||||
return new DefaultModelBindingContext()
|
||||
|
|
|
|||
Loading…
Reference in New Issue