Allow ValidationAttributes and IValidatableObjects to resolve services from the RequestServices provider by injecting it into the ValidationContext.
This commit is contained in:
parent
a229b20c48
commit
328f4d648b
|
|
@ -82,7 +82,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
var memberName = metadata.PropertyName ?? metadata.ModelType.Name;
|
||||
var container = validationContext.Container;
|
||||
|
||||
var context = new ValidationContext(container ?? validationContext.Model)
|
||||
var context = new ValidationContext(
|
||||
instance: container ?? validationContext.Model,
|
||||
serviceProvider: validationContext.ActionContext?.HttpContext?.RequestServices,
|
||||
items: null)
|
||||
{
|
||||
DisplayName = metadata.GetDisplayName(),
|
||||
MemberName = memberName
|
||||
|
|
|
|||
|
|
@ -29,7 +29,11 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
throw new InvalidOperationException(message);
|
||||
}
|
||||
|
||||
var validationContext = new ValidationContext(validatable, serviceProvider: null, items: null);
|
||||
var validationContext = new ValidationContext(
|
||||
instance: validatable,
|
||||
serviceProvider: context.ActionContext?.HttpContext?.RequestServices,
|
||||
items: null);
|
||||
|
||||
return ConvertResults(validatable.Validate(validationContext));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,10 @@ using System.Linq;
|
|||
#if DNXCORE50
|
||||
using System.Reflection;
|
||||
#endif
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Metadata;
|
||||
using Microsoft.AspNet.Testing;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
||||
|
|
@ -431,6 +433,49 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
Assert.Equal("Error3", error.ErrorMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_ComplexType_IValidatableObject_CanUseRequestServices()
|
||||
{
|
||||
// Arrange
|
||||
var service = new Mock<IExampleService>();
|
||||
service.Setup(x => x.DoSomething()).Verifiable();
|
||||
|
||||
var provider = new ServiceCollection().AddSingleton(service.Object).BuildServiceProvider();
|
||||
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.SetupGet(x => x.RequestServices).Returns(provider);
|
||||
|
||||
var actionContext = new ActionContext { HttpContext = httpContext.Object };
|
||||
|
||||
var validatorProvider = CreateValidatorProvider();
|
||||
var modelState = actionContext.ModelState;
|
||||
var validationState = new ValidationStateDictionary();
|
||||
|
||||
var validator = CreateValidator();
|
||||
|
||||
var model = new Mock<IValidatableObject>();
|
||||
model
|
||||
.Setup(x => x.Validate(It.IsAny<ValidationContext>()))
|
||||
.Callback((ValidationContext context) =>
|
||||
{
|
||||
var receivedService = context.GetService<IExampleService>();
|
||||
Assert.Equal(service.Object, receivedService);
|
||||
receivedService.DoSomething();
|
||||
})
|
||||
.Returns(new List<ValidationResult>());
|
||||
|
||||
// Act
|
||||
validator.Validate(
|
||||
actionContext,
|
||||
validatorProvider,
|
||||
validationState,
|
||||
null,
|
||||
model.Object);
|
||||
|
||||
// Assert
|
||||
service.Verify();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[ReplaceCulture]
|
||||
public void Validate_ComplexType_FieldsAreIgnored_Valid()
|
||||
|
|
@ -1071,5 +1116,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface IExampleService
|
||||
{
|
||||
void DoSomething();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNet.Http;
|
||||
using Microsoft.AspNet.Mvc.DataAnnotations;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
|
|
@ -152,7 +154,7 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void Validatate_ValidationResultSuccess()
|
||||
public void Validate_ValidationResultSuccess()
|
||||
{
|
||||
// Arrange
|
||||
var metadata = _metadataProvider.GetMetadataForType(typeof(string));
|
||||
|
|
@ -315,6 +317,50 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
Assert.Equal("Longueur est invalide : 4", validationResult.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_CanUseRequestServices_WithinValidationAttribute()
|
||||
{
|
||||
// Arrange
|
||||
var service = new Mock<IExampleService>();
|
||||
service.Setup(x => x.DoSomething()).Verifiable();
|
||||
|
||||
var provider = new ServiceCollection().AddSingleton(service.Object).BuildServiceProvider();
|
||||
|
||||
var httpContext = new Mock<HttpContext>();
|
||||
httpContext.SetupGet(x => x.RequestServices).Returns(provider);
|
||||
|
||||
var attribute = new Mock<TestableValidationAttribute> { CallBase = true };
|
||||
attribute
|
||||
.Setup(p => p.IsValidPublic(It.IsAny<object>(), It.IsAny<ValidationContext>()))
|
||||
.Callback((object o, ValidationContext context) =>
|
||||
{
|
||||
var receivedService = context.GetService<IExampleService>();
|
||||
Assert.Equal(service.Object, receivedService);
|
||||
receivedService.DoSomething();
|
||||
});
|
||||
|
||||
var validator = new DataAnnotationsModelValidator(
|
||||
new ValidationAttributeAdapterProvider(),
|
||||
attribute.Object,
|
||||
stringLocalizer: null);
|
||||
|
||||
var validationContext = new ModelValidationContext(
|
||||
actionContext: new ActionContext
|
||||
{
|
||||
HttpContext = httpContext.Object
|
||||
},
|
||||
modelMetadata: _metadataProvider.GetMetadataForType(typeof(object)),
|
||||
metadataProvider: _metadataProvider,
|
||||
container: null,
|
||||
model: new object());
|
||||
|
||||
// Act
|
||||
var results = validator.Validate(validationContext);
|
||||
|
||||
// Assert
|
||||
service.Verify();
|
||||
}
|
||||
|
||||
private const string LocalizationKey = "LocalizeIt";
|
||||
|
||||
public static TheoryData Validate_AttributesIncludeValues
|
||||
|
|
@ -430,5 +476,10 @@ namespace Microsoft.AspNet.Mvc.ModelBinding.Validation
|
|||
{
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
public interface IExampleService
|
||||
{
|
||||
void DoSomething();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue