Adding ApiController.Validate : Fixes #1286
This commit is contained in:
parent
22869b41c0
commit
5a83383179
|
|
@ -7,6 +7,7 @@ using Microsoft.AspNet.Http;
|
||||||
using Microsoft.AspNet.Mvc;
|
using Microsoft.AspNet.Mvc;
|
||||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||||
using Microsoft.AspNet.Mvc.WebApiCompatShim;
|
using Microsoft.AspNet.Mvc.WebApiCompatShim;
|
||||||
|
using Microsoft.Framework.DependencyInjection;
|
||||||
|
|
||||||
namespace System.Web.Http
|
namespace System.Web.Http
|
||||||
{
|
{
|
||||||
|
|
@ -83,6 +84,40 @@ namespace System.Web.Http
|
||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validates the given entity and adds the validation errors to the <see cref="ApiController.ModelState"/>
|
||||||
|
/// under an empty prefix.
|
||||||
|
/// </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"/>.
|
||||||
|
/// </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)
|
||||||
|
{
|
||||||
|
var validator = Context.RequestServices.GetService<IBodyModelValidator>();
|
||||||
|
var metadataProvider = Context.RequestServices.GetService<IModelMetadataProvider>();
|
||||||
|
var modelMetadata = metadataProvider.GetMetadataForType(() => entity, typeof(TEntity));
|
||||||
|
var validatorProvider = Context.RequestServices.GetService<ICompositeModelValidatorProvider>();
|
||||||
|
var modelValidationContext = new ModelValidationContext(metadataProvider,
|
||||||
|
validatorProvider,
|
||||||
|
ModelState,
|
||||||
|
modelMetadata,
|
||||||
|
containerMetadata: null);
|
||||||
|
validator.Validate(modelValidationContext, keyPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,53 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
|
||||||
Assert.Equal(expected, formatters);
|
Assert.Equal(expected, formatters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ApiController_CanValidateCustomObjectWithPrefix_Fails()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var server = TestServer.Create(_provider, _app);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await client.GetStringAsync(
|
||||||
|
"http://localhost/api/Blog/BasicApi/ValidateObjectWithPrefixFails?prefix=prefix");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(response);
|
||||||
|
Assert.Equal(1, json.Count);
|
||||||
|
Assert.Equal("The field ID must be between 0 and 100.", json["prefix.ID"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ApiController_CanValidateCustomObject_IsSuccessFul()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var server = TestServer.Create(_provider, _app);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await client.GetStringAsync("http://localhost/api/Blog/BasicApi/ValidateObject_Passes");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal("true", response);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ApiController_CanValidateCustomObject_Fails()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var server = TestServer.Create(_provider, _app);
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await client.GetStringAsync("http://localhost/api/Blog/BasicApi/ValidateObjectFails");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(response);
|
||||||
|
Assert.Equal(1, json.Count);
|
||||||
|
Assert.Equal("The field ID must be between 0 and 100.", json["ID"]);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ApiController_RequestProperty()
|
public async Task ApiController_RequestProperty()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Web.Http;
|
using System.Web.Http;
|
||||||
|
|
@ -45,5 +47,52 @@ namespace WebApiCompatShimWebSite
|
||||||
{
|
{
|
||||||
return OptionsAccessor.Options.Formatters.Select(f => f.GetType().FullName).ToArray();
|
return OptionsAccessor.Options.Formatters.Select(f => f.GetType().FullName).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public bool ValidateObject_Passes()
|
||||||
|
{
|
||||||
|
var entity = new TestEntity { ID = 42 };
|
||||||
|
Validate(entity);
|
||||||
|
return ModelState.IsValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public object ValidateObjectFails()
|
||||||
|
{
|
||||||
|
var entity = new TestEntity { ID = -1 };
|
||||||
|
Validate(entity);
|
||||||
|
return CreateValidationDictionary();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public object ValidateObjectWithPrefixFails(string prefix)
|
||||||
|
{
|
||||||
|
var entity = new TestEntity { ID = -1 };
|
||||||
|
Validate(entity, prefix);
|
||||||
|
return CreateValidationDictionary();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestEntity
|
||||||
|
{
|
||||||
|
[Range(0, 100)]
|
||||||
|
public int ID { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<string, string> CreateValidationDictionary()
|
||||||
|
{
|
||||||
|
var result = new Dictionary<string, string>();
|
||||||
|
foreach (var item in ModelState)
|
||||||
|
{
|
||||||
|
var error = item.Value.Errors.SingleOrDefault();
|
||||||
|
if (error != null)
|
||||||
|
{
|
||||||
|
var value = error.Exception != null ? error.Exception.Message :
|
||||||
|
error.ErrorMessage;
|
||||||
|
result.Add(item.Key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue