diff --git a/src/Dapr.AspNetCore/StateEntryApplicationModelProvider.cs b/src/Dapr.AspNetCore/StateEntryApplicationModelProvider.cs index fec52458..24aa37d9 100644 --- a/src/Dapr.AspNetCore/StateEntryApplicationModelProvider.cs +++ b/src/Dapr.AspNetCore/StateEntryApplicationModelProvider.cs @@ -28,7 +28,7 @@ namespace Dapr.AspNetCore { // Not bindable. } - else if (property.BindingInfo.BindingSource.Id == "state") + else if (property.BindingInfo.BindingSource?.Id == "state") { // Already configured, don't overwrite in case the user customized it. } @@ -46,7 +46,7 @@ namespace Dapr.AspNetCore { // Not bindable. } - else if (parameter.BindingInfo.BindingSource.Id == "state") + else if (parameter.BindingInfo.BindingSource?.Id == "state") { // Already configured, don't overwrite in case the user customized it. } diff --git a/test/Dapr.AspNetCore.Test/StateEntryApplicationModelProviderTest.cs b/test/Dapr.AspNetCore.Test/StateEntryApplicationModelProviderTest.cs new file mode 100644 index 00000000..07fbf2b8 --- /dev/null +++ b/test/Dapr.AspNetCore.Test/StateEntryApplicationModelProviderTest.cs @@ -0,0 +1,94 @@ +// ------------------------------------------------------------ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. +// ------------------------------------------------------------ + +namespace Dapr.AspNetCore.Test +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Reflection; + using System.Text.Json; + using System.Threading.Tasks; + using Dapr.AspNetCore.Resources; + using Dapr.Client; + using Dapr.Client.Autogen.Grpc.v1; + using FluentAssertions; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.AspNetCore.Mvc.ApplicationModels; + using Microsoft.AspNetCore.Mvc.ModelBinding; + using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; + using Microsoft.AspNetCore.Mvc.Routing; + using Microsoft.Extensions.DependencyInjection; + using Xunit; + + public class StateEntryApplicationModelProviderTest + { + [Fact] + public void OnProvidersExecuted_NullActionsBindingSource() + { + var provider = new StateEntryApplicationModelProvider(); + var context = CreateContext(nameof(ApplicationModelProviderTestController.Get)); + + Action action = () => provider.OnProvidersExecuted(context); + + action + .Should() + .NotThrow(); + } + + [Fact] + public void OnProvidersExecuted_StateEntryParameterThrows() + { + var provider = new StateEntryApplicationModelProvider(); + var context = CreateContext(nameof(ApplicationModelProviderTestController.Post)); + + Action action = () => provider.OnProvidersExecuted(context); + + action + .Should() + .Throw(SR.ErrorStateStoreNameNotProvidedForStateEntry); + } + + private ApplicationModelProviderContext CreateContext(string methodName) + { + var controllerType = typeof(ApplicationModelProviderTestController).GetTypeInfo(); + var typeInfoList = new List { controllerType }; + + var context = new ApplicationModelProviderContext(typeInfoList); + var controllerModel = new ControllerModel(controllerType, new List(0)); + + context.Result.Controllers.Add(controllerModel); + + var methodInfo = controllerType.AsType().GetMethods().First(m => m.Name.Equals(methodName)); + var actionModel = new ActionModel(methodInfo, controllerModel.Attributes) + { + Controller = controllerModel + }; + + controllerModel.Actions.Add(actionModel); + var parameterInfo = actionModel.ActionMethod.GetParameters().First(); + var parameterModel = new ParameterModel(parameterInfo, controllerModel.Attributes) + { + BindingInfo = new BindingInfo(), + Action = actionModel, + }; + + actionModel.Parameters.Add(parameterModel); + + return context; + } + + [Controller] + private class ApplicationModelProviderTestController : Controller + { + [HttpGet] + public void Get([Bind(Prefix = "s")]int someId) { } + + [HttpPost] + public void Post(StateEntry bogusEntry) { } + } + } +}