Added custom (hack) for PrefixlessBodyModelValidatorAttribute.

This commit is contained in:
Bjarke Berg
2020-06-18 14:40:30 +02:00
parent ce35ccc0e9
commit 27227043ba
5 changed files with 89 additions and 66 deletions

View File

@@ -92,7 +92,7 @@ namespace Umbraco.Tests.Integration.TestServerTest.Controllers
{
var url = PrepareUrl<ContentController>(x => x.PostSave(null));
var contentService = GetRequiredService<IContentService>();
var contentTypeService = GetRequiredService<IContentTypeService>();
var contentType = new ContentTypeBuilder()
@@ -108,6 +108,7 @@ namespace Umbraco.Tests.Integration.TestServerTest.Controllers
contentTypeService.Save(contentType);
var contentService = GetRequiredService<IContentService>();
var content = new ContentBuilder()
.WithId(0)
.WithName("Invariant")
@@ -139,8 +140,12 @@ namespace Umbraco.Tests.Integration.TestServerTest.Controllers
var body = await response.Content.ReadAsStringAsync();
Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode);
Assert.AreEqual(")]}',\n{\"message\":\"No variants flagged for saving\"}", body);
Assert.Multiple(() =>
{
Assert.AreEqual(HttpStatusCode.NotFound, response.StatusCode);
Assert.AreEqual(")]}',\n{\"message\":\"No variants flagged for saving\"}", body);
});
}
/// <summary>
@@ -253,9 +258,13 @@ namespace Umbraco.Tests.Integration.TestServerTest.Controllers
body = body.TrimStart(AngularJsonMediaTypeFormatter.XsrfPrefix);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, body);
var display = JsonConvert.DeserializeObject<ContentItemDisplay>(body);
Assert.AreEqual(1, display.Variants.Count());
Assert.Multiple(() =>
{
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, body);
var display = JsonConvert.DeserializeObject<ContentItemDisplay>(body);
Assert.AreEqual(1, display.Variants.Count());
});
}
[Test]
@@ -307,11 +316,13 @@ namespace Umbraco.Tests.Integration.TestServerTest.Controllers
body = body.TrimStart(AngularJsonMediaTypeFormatter.XsrfPrefix);
Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);
var display = JsonConvert.DeserializeObject<ContentItemDisplay>(body);
Assert.AreEqual(1, display.Errors.Count());
Assert.IsTrue(display.Errors.ContainsKey("Variants[0].Name"));
//ModelState":{"Variants[0].Name":["Required"]}
Assert.Multiple(() =>
{
Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);
var display = JsonConvert.DeserializeObject<ContentItemDisplay>(body);
Assert.AreEqual(1, display.Errors.Count(), string.Join(",", display.Errors));
CollectionAssert.Contains(display.Errors.Keys, "Variants[0].Name");
});
}
[Test]
@@ -358,15 +369,18 @@ namespace Umbraco.Tests.Integration.TestServerTest.Controllers
});
// Assert
var body = await response.Content.ReadAsStringAsync();
body = body.TrimStart(AngularJsonMediaTypeFormatter.XsrfPrefix);
Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);
var display = JsonConvert.DeserializeObject<ContentItemDisplay>(body);
Assert.AreEqual(2, display.Errors.Count());
Assert.IsTrue(display.Errors.ContainsKey("Variants[0].Name"));
Assert.IsTrue(display.Errors.ContainsKey("_content_variant_en-US_null_"));
Assert.Multiple(() =>
{
Assert.AreEqual(HttpStatusCode.BadRequest, response.StatusCode);
var display = JsonConvert.DeserializeObject<ContentItemDisplay>(body);
Assert.AreEqual(2, display.Errors.Count());
CollectionAssert.Contains(display.Errors.Keys, "Variants[0].Name");
CollectionAssert.Contains(display.Errors.Keys, "_content_variant_en-US_null_");
});
}

View File

@@ -64,7 +64,8 @@ namespace Umbraco.Tests.Integration.TestServerTest
[TearDown]
public void TearDown()
{
Client.Dispose();
Factory.Dispose();
if (Current.IsInitialized)
{

View File

@@ -1,4 +1,5 @@
using Umbraco.Web.WebApi.Filters;
using Umbraco.Web.BackOffice.Filters;
using Umbraco.Web.WebApi.Filters;
namespace Umbraco.Web.BackOffice.Controllers
{
@@ -7,7 +8,7 @@ namespace Umbraco.Web.BackOffice.Controllers
/// resulting message is INotificationModel in which case it will append any Event Messages
/// currently in the request.
/// </summary>
//[PrefixlessBodyModelValidator] // TODO implement this!!
[PrefixlessBodyModelValidator]
[AppendCurrentEventMessagesAttribute]
public abstract class BackOfficeNotificationsController : UmbracoAuthorizedJsonController
{

View File

@@ -0,0 +1,52 @@
using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace Umbraco.Web.BackOffice.Filters
{
public class PrefixlessBodyModelValidatorAttribute : TypeFilterAttribute
{
public PrefixlessBodyModelValidatorAttribute() : base(typeof(PrefixlessBodyModelValidatorFilter))
{
}
private class PrefixlessBodyModelValidatorFilter : IActionFilter
{
public void OnActionExecuted(ActionExecutedContext context)
{
}
public void OnActionExecuting(ActionExecutingContext context)
{
if (context.ModelState.IsValid) return;
//Remove prefix from errors
foreach (var modelStateItem in context.ModelState)
{
foreach (var prefix in context.ActionArguments.Keys)
{
if (modelStateItem.Key.StartsWith(prefix))
{
if (modelStateItem.Value.Errors.Any())
{
var newKey = modelStateItem.Key.Substring(prefix.Length).TrimStart('.');
foreach (var valueError in modelStateItem.Value.Errors)
{
context.ModelState.TryAddModelError(newKey, valueError.ErrorMessage);
}
context.ModelState.Remove(modelStateItem.Key);
}
}
}
}
}
}
}
}

View File

@@ -1,45 +0,0 @@
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
namespace Umbraco.Web.BackOffice.Validation
{
public class PrefixlessBodyModelValidator : ObjectModelValidator
{
public PrefixlessBodyModelValidator(IModelMetadataProvider modelMetadataProvider, IList<IModelValidatorProvider> validatorProviders) :
base(modelMetadataProvider, validatorProviders)
{
}
public override ValidationVisitor GetValidationVisitor(ActionContext actionContext, IModelValidatorProvider validatorProvider,
ValidatorCache validatorCache, IModelMetadataProvider metadataProvider, ValidationStateDictionary validationState)
{
var visitor = new PrefixlessValidationVisitor(
actionContext,
validatorProvider,
validatorCache,
metadataProvider,
validationState);
return visitor;
}
private class PrefixlessValidationVisitor : ValidationVisitor
{
public PrefixlessValidationVisitor(ActionContext actionContext, IModelValidatorProvider validatorProvider, ValidatorCache validatorCache, IModelMetadataProvider metadataProvider, ValidationStateDictionary validationState)
: base(actionContext, validatorProvider, validatorCache, metadataProvider, validationState) {
}
public override bool Validate(ModelMetadata metadata, string key, object model, bool alwaysValidateAtTopLevel)
{
return base.Validate(metadata, string.Empty, model, alwaysValidateAtTopLevel);
}
}
}
}