Moving Validate method to ApiController instead of ODataController
This commit is contained in:
Родитель
a8470366b8
Коммит
b7f192b56c
|
@ -1,12 +1,7 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Web.Http.Description;
|
||||
using System.Web.Http.Metadata;
|
||||
using System.Web.Http.OData.Properties;
|
||||
using System.Web.Http.OData.Results;
|
||||
using System.Web.Http.Validation;
|
||||
|
||||
namespace System.Web.Http.OData
|
||||
{
|
||||
|
@ -18,42 +13,6 @@ namespace System.Web.Http.OData
|
|||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public abstract class ODataController : ApiController
|
||||
{
|
||||
/// <summary>
|
||||
/// Validates the given entity and adds the validation errors to the <see cref="ApiController.ModelState"/>
|
||||
/// under the empty prefix, if any.
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity">The type of the entity to be validated.</typeparam>
|
||||
/// <param name="entity">The entity being validated.</param>
|
||||
public void Validate<TEntity>(TEntity entity)
|
||||
{
|
||||
Validate(entity, keyPrefix: String.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the given entity and adds the validation errors to the <see cref="ApiController.ModelState"/>, if any.
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity">The type of the entity to be validated.</typeparam>
|
||||
/// <param name="entity">The entity being validated.</param>
|
||||
/// <param name="keyPrefix">
|
||||
/// The key prefix under which the model state errors would be added in the <see cref="ApiController.ModelState"/>.
|
||||
/// </param>
|
||||
public void Validate<TEntity>(TEntity entity, string keyPrefix)
|
||||
{
|
||||
if (Configuration == null)
|
||||
{
|
||||
throw Error.InvalidOperation(SRResources.TypePropertyMustNotBeNull, typeof(ApiController).Name, "Configuration");
|
||||
}
|
||||
|
||||
IBodyModelValidator validator = Configuration.Services.GetBodyModelValidator();
|
||||
if (validator != null)
|
||||
{
|
||||
ModelMetadataProvider metadataProvider = Configuration.Services.GetModelMetadataProvider();
|
||||
Contract.Assert(metadataProvider != null, "GetModelMetadataProvider throws on null.");
|
||||
|
||||
validator.Validate(entity, typeof(TEntity), metadataProvider, ActionContext, keyPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an action result with the specified values that is a response to a POST operation with an entity
|
||||
/// to an entity set.
|
||||
|
|
|
@ -1572,15 +1572,6 @@ namespace System.Web.Http.OData.Properties {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0}.{1} must not be null..
|
||||
/// </summary>
|
||||
internal static string TypePropertyMustNotBeNull {
|
||||
get {
|
||||
return ResourceManager.GetString("TypePropertyMustNotBeNull", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to The ODataMediaTypeFormatter was unable to determine the base URI for the request. The request must be processed by an OData route for the OData formatter to serialize the response..
|
||||
/// </summary>
|
||||
|
|
|
@ -655,9 +655,6 @@
|
|||
<data name="OrderByNodeCountExceeded" xml:space="preserve">
|
||||
<value>The number of clauses in $orderby query option exceeded the maximum number allowed. The maximum number of $orderby clauses allowed is {0}.</value>
|
||||
</data>
|
||||
<data name="TypePropertyMustNotBeNull" xml:space="preserve">
|
||||
<value>{0}.{1} must not be null.</value>
|
||||
</data>
|
||||
<data name="ReturnEntityCollectionWithoutEntitySet" xml:space="preserve">
|
||||
<value>The EDM type '{0}' is already declared as an entity type. Use the method 'ReturnsCollectionFromEntitySet' if the return type is an entity collection.</value>
|
||||
</data>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Formatting;
|
||||
|
@ -14,10 +15,12 @@ using System.Web.Http.Controllers;
|
|||
using System.Web.Http.Dispatcher;
|
||||
using System.Web.Http.ExceptionHandling;
|
||||
using System.Web.Http.Filters;
|
||||
using System.Web.Http.Metadata;
|
||||
using System.Web.Http.ModelBinding;
|
||||
using System.Web.Http.Properties;
|
||||
using System.Web.Http.Results;
|
||||
using System.Web.Http.Routing;
|
||||
using System.Web.Http.Validation;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace System.Web.Http
|
||||
|
@ -233,6 +236,42 @@ namespace System.Web.Http
|
|||
return result.ExecuteAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the given entity and adds the validation errors to the <see cref="ApiController.ModelState"/>
|
||||
/// under the empty prefix, if any.
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity">The type of the entity to be validated.</typeparam>
|
||||
/// <param name="entity">The entity being validated.</param>
|
||||
public void Validate<TEntity>(TEntity entity)
|
||||
{
|
||||
Validate(entity, keyPrefix: String.Empty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validates the given entity and adds the validation errors to the <see cref="ApiController.ModelState"/>, if any.
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity">The type of the entity to be validated.</typeparam>
|
||||
/// <param name="entity">The entity being validated.</param>
|
||||
/// <param name="keyPrefix">
|
||||
/// The key prefix under which the model state errors would be added in the <see cref="ApiController.ModelState"/>.
|
||||
/// </param>
|
||||
public void Validate<TEntity>(TEntity entity, string keyPrefix)
|
||||
{
|
||||
if (Configuration == null)
|
||||
{
|
||||
throw Error.InvalidOperation(SRResources.TypePropertyMustNotBeNull, typeof(ApiController).Name, "Configuration");
|
||||
}
|
||||
|
||||
IBodyModelValidator validator = Configuration.Services.GetBodyModelValidator();
|
||||
if (validator != null)
|
||||
{
|
||||
ModelMetadataProvider metadataProvider = Configuration.Services.GetModelMetadataProvider();
|
||||
Contract.Assert(metadataProvider != null, "GetModelMetadataProvider throws on null.");
|
||||
|
||||
validator.Validate(entity, typeof(TEntity), metadataProvider, ActionContext, keyPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Creates a <see cref="BadRequestResult"/> (400 Bad Request).</summary>
|
||||
/// <returns>A <see cref="BadRequestResult"/>.</returns>
|
||||
protected internal virtual BadRequestResult BadRequest()
|
||||
|
|
|
@ -1,122 +0,0 @@
|
|||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Web.Http.Metadata;
|
||||
using System.Web.Http.Validation;
|
||||
using Microsoft.TestCommon;
|
||||
using Moq;
|
||||
|
||||
namespace System.Web.Http.OData
|
||||
{
|
||||
public class ODataControllerTest
|
||||
{
|
||||
[Fact]
|
||||
public void Validate_ThrowsInvalidOperationException_IfConfigurationIsNull()
|
||||
{
|
||||
// Arrange
|
||||
TestODataController controller = new TestODataController();
|
||||
TestEntity entity = new TestEntity();
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
() => controller.Validate(entity),
|
||||
"ApiController.Configuration must not be null.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_DoesNothing_IfValidatorIsNull()
|
||||
{
|
||||
// Arrange
|
||||
HttpConfiguration configuration = new HttpConfiguration();
|
||||
configuration.Services.Replace(typeof(IBodyModelValidator), null);
|
||||
TestEntity entity = new TestEntity { ID = 42 };
|
||||
|
||||
TestODataController controller = new TestODataController { Configuration = configuration };
|
||||
|
||||
// Act
|
||||
controller.Validate(entity);
|
||||
|
||||
// Assert
|
||||
Assert.True(controller.ModelState.IsValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_CallsValidateOnConfiguredValidator_UsingConfiguredMetadataProvider()
|
||||
{
|
||||
// Arrange
|
||||
Mock<IBodyModelValidator> validator = new Mock<IBodyModelValidator>();
|
||||
Mock<ModelMetadataProvider> metadataProvider = new Mock<ModelMetadataProvider>();
|
||||
|
||||
HttpConfiguration configuration = new HttpConfiguration();
|
||||
configuration.Services.Replace(typeof(IBodyModelValidator), validator.Object);
|
||||
configuration.Services.Replace(typeof(ModelMetadataProvider), metadataProvider.Object);
|
||||
|
||||
TestODataController controller = new TestODataController { Configuration = configuration };
|
||||
TestEntity entity = new TestEntity { ID = 42 };
|
||||
|
||||
// Act
|
||||
controller.Validate(entity);
|
||||
|
||||
// Assert
|
||||
validator.Verify(
|
||||
v => v.Validate(entity, typeof(TestEntity), metadataProvider.Object, controller.ActionContext, String.Empty),
|
||||
Times.Once());
|
||||
Assert.True(controller.ModelState.IsValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_SetsModelStateErrors_ForInvalidModels()
|
||||
{
|
||||
// Arrange
|
||||
HttpConfiguration configuration = new HttpConfiguration();
|
||||
TestODataController controller = new TestODataController { Configuration = configuration };
|
||||
TestEntity entity = new TestEntity { ID = -1 };
|
||||
|
||||
// Act
|
||||
controller.Validate(entity);
|
||||
|
||||
// Assert
|
||||
Assert.False(controller.ModelState.IsValid);
|
||||
Assert.Equal("The field ID must be between 0 and 100.", controller.ModelState["ID"].Errors[0].ErrorMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_SetsModelStateErrorsUnderRightPrefix_ForInvalidModels()
|
||||
{
|
||||
// Arrange
|
||||
HttpConfiguration configuration = new HttpConfiguration();
|
||||
TestODataController controller = new TestODataController { Configuration = configuration };
|
||||
TestEntity entity = new TestEntity { ID = -1 };
|
||||
|
||||
// Act
|
||||
controller.Validate(entity, keyPrefix: "prefix");
|
||||
|
||||
// Assert
|
||||
Assert.False(controller.ModelState.IsValid);
|
||||
Assert.Equal("The field ID must be between 0 and 100.",
|
||||
controller.ModelState["prefix.ID"].Errors[0].ErrorMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_DoesNotThrow_ForValidModels()
|
||||
{
|
||||
// Arrange
|
||||
HttpConfiguration configuration = new HttpConfiguration();
|
||||
TestODataController controller = new TestODataController { Configuration = configuration };
|
||||
TestEntity entity = new TestEntity { ID = 42 };
|
||||
|
||||
// Act && Assert
|
||||
Assert.DoesNotThrow(() => controller.Validate(entity));
|
||||
}
|
||||
|
||||
private class TestODataController : ODataController
|
||||
{
|
||||
}
|
||||
|
||||
private class TestEntity
|
||||
{
|
||||
[Range(0, 100)]
|
||||
public int ID { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -110,7 +110,6 @@
|
|||
<Compile Include="OData\Formatter\Serialization\ODataMetadataSerializerTest.cs" />
|
||||
<Compile Include="OData\Formatter\Serialization\ODataSerializerTest.cs" />
|
||||
<Compile Include="OData\NullEdmComplexObjectTest.cs" />
|
||||
<Compile Include="OData\ODataControllerTest.cs" />
|
||||
<Compile Include="OData\ODataNullValueAttributeTests.cs" />
|
||||
<Compile Include="OData\Formatter\Serialization\SelectExpandNodeTest.cs" />
|
||||
<Compile Include="OData\PerRequestContentNegotiatorTest.cs" />
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
@ -16,9 +17,11 @@ using System.Web.Http.Dispatcher;
|
|||
using System.Web.Http.ExceptionHandling;
|
||||
using System.Web.Http.Filters;
|
||||
using System.Web.Http.Hosting;
|
||||
using System.Web.Http.Metadata;
|
||||
using System.Web.Http.ModelBinding;
|
||||
using System.Web.Http.Routing;
|
||||
using System.Web.Http.Services;
|
||||
using System.Web.Http.Validation;
|
||||
using Microsoft.TestCommon;
|
||||
using Moq;
|
||||
|
||||
|
@ -1066,6 +1069,115 @@ namespace System.Web.Http
|
|||
Assert.Same(expectedPrincipal, context.Principal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_ThrowsInvalidOperationException_IfConfigurationIsNull()
|
||||
{
|
||||
// Arrange
|
||||
TestController controller = new TestController();
|
||||
TestEntity entity = new TestEntity();
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<InvalidOperationException>(
|
||||
() => controller.Validate(entity),
|
||||
"ApiController.Configuration must not be null.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_DoesNothing_IfValidatorIsNull()
|
||||
{
|
||||
// Arrange
|
||||
HttpConfiguration configuration = new HttpConfiguration();
|
||||
configuration.Services.Replace(typeof(IBodyModelValidator), null);
|
||||
TestEntity entity = new TestEntity { ID = 9999999 };
|
||||
|
||||
TestController controller = new TestController { Configuration = configuration };
|
||||
|
||||
// Act
|
||||
controller.Validate(entity);
|
||||
|
||||
// Assert
|
||||
Assert.True(controller.ModelState.IsValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_CallsValidateOnConfiguredValidator_UsingConfiguredMetadataProvider()
|
||||
{
|
||||
// Arrange
|
||||
Mock<IBodyModelValidator> validator = new Mock<IBodyModelValidator>();
|
||||
Mock<ModelMetadataProvider> metadataProvider = new Mock<ModelMetadataProvider>();
|
||||
|
||||
HttpConfiguration configuration = new HttpConfiguration();
|
||||
configuration.Services.Replace(typeof(IBodyModelValidator), validator.Object);
|
||||
configuration.Services.Replace(typeof(ModelMetadataProvider), metadataProvider.Object);
|
||||
|
||||
TestController controller = new TestController { Configuration = configuration };
|
||||
TestEntity entity = new TestEntity { ID = 42 };
|
||||
|
||||
// Act
|
||||
controller.Validate(entity);
|
||||
|
||||
// Assert
|
||||
validator.Verify(
|
||||
v => v.Validate(entity, typeof(TestEntity), metadataProvider.Object, controller.ActionContext, String.Empty),
|
||||
Times.Once());
|
||||
Assert.True(controller.ModelState.IsValid);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_SetsModelStateErrors_ForInvalidModels()
|
||||
{
|
||||
// Arrange
|
||||
HttpConfiguration configuration = new HttpConfiguration();
|
||||
TestController controller = new TestController { Configuration = configuration };
|
||||
TestEntity entity = new TestEntity { ID = -1 };
|
||||
|
||||
// Act
|
||||
controller.Validate(entity);
|
||||
|
||||
// Assert
|
||||
Assert.False(controller.ModelState.IsValid);
|
||||
Assert.Equal("The field ID must be between 0 and 100.", controller.ModelState["ID"].Errors[0].ErrorMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_SetsModelStateErrorsUnderRightPrefix_ForInvalidModels()
|
||||
{
|
||||
// Arrange
|
||||
HttpConfiguration configuration = new HttpConfiguration();
|
||||
TestController controller = new TestController { Configuration = configuration };
|
||||
TestEntity entity = new TestEntity { ID = -1 };
|
||||
|
||||
// Act
|
||||
controller.Validate(entity, keyPrefix: "prefix");
|
||||
|
||||
// Assert
|
||||
Assert.False(controller.ModelState.IsValid);
|
||||
Assert.Equal("The field ID must be between 0 and 100.",
|
||||
controller.ModelState["prefix.ID"].Errors[0].ErrorMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Validate_DoesNotThrow_ForValidModels()
|
||||
{
|
||||
// Arrange
|
||||
HttpConfiguration configuration = new HttpConfiguration();
|
||||
TestController controller = new TestController { Configuration = configuration };
|
||||
TestEntity entity = new TestEntity { ID = 42 };
|
||||
|
||||
// Act && Assert
|
||||
Assert.DoesNotThrow(() => controller.Validate(entity));
|
||||
}
|
||||
|
||||
private class TestController : ApiController
|
||||
{
|
||||
}
|
||||
|
||||
private class TestEntity
|
||||
{
|
||||
[Range(0, 100)]
|
||||
public int ID { get; set; }
|
||||
}
|
||||
|
||||
private Mock<IAuthorizationFilter> CreateAuthorizationFilterMock(Func<HttpActionContext, CancellationToken, Func<Task<HttpResponseMessage>>, Task<HttpResponseMessage>> implementation)
|
||||
{
|
||||
Mock<IAuthorizationFilter> filterMock = new Mock<IAuthorizationFilter>();
|
||||
|
|
Загрузка…
Ссылка в новой задаче