Moving Validate method to ApiController instead of ODataController

This commit is contained in:
raghuramn 2013-11-05 14:18:05 -08:00
Родитель a8470366b8
Коммит b7f192b56c
7 изменённых файлов: 151 добавлений и 176 удалений

Просмотреть файл

@ -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>();