- Added null-conditional operator to StateEntryApplicationModelProvider.OnProvidersExecuted when checking BindingSource to prevent startup null reference exceptions in certain implementations. (#765)

- Added null check and throws unit tests for StateEntryApplicationModelProvider
This commit is contained in:
Michael Robertson 2021-10-13 19:53:22 -04:00 committed by GitHub
parent 75bdb8ce2f
commit fc54f21d00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 96 additions and 2 deletions

View File

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

View File

@ -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<NullReferenceException>();
}
[Fact]
public void OnProvidersExecuted_StateEntryParameterThrows()
{
var provider = new StateEntryApplicationModelProvider();
var context = CreateContext(nameof(ApplicationModelProviderTestController.Post));
Action action = () => provider.OnProvidersExecuted(context);
action
.Should()
.Throw<InvalidOperationException>(SR.ErrorStateStoreNameNotProvidedForStateEntry);
}
private ApplicationModelProviderContext CreateContext(string methodName)
{
var controllerType = typeof(ApplicationModelProviderTestController).GetTypeInfo();
var typeInfoList = new List<TypeInfo> { controllerType };
var context = new ApplicationModelProviderContext(typeInfoList);
var controllerModel = new ControllerModel(controllerType, new List<object>(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<Subscription> bogusEntry) { }
}
}
}