This repository has been archived by the owner on Dec 14, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add
IValidationAttributeProvider
to make `DefaultHtmlGenerator.AddV…
…alidationAttributes()` available - #5028 - helpers similar to our HTML or tag helpers can use the new singleton to examine validation attributes - in the most common case, helpers add validation attributes to a `TagBuilder` but that is not required - separating the `ValidationAttributesProvider` from `DefaultHtmlGenerator` avoids creating two instances of that singleton - would be even uglier to require callers to cast an `IHtmlGenerator` to `IValidationAttributeProvider`
- Loading branch information
Showing
6 changed files
with
385 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/IValidationAttributeProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System.Collections.Generic; | ||
using Microsoft.AspNetCore.Mvc.Rendering; | ||
|
||
namespace Microsoft.AspNetCore.Mvc.ViewFeatures | ||
{ | ||
/// <summary> | ||
/// Contract for a service providing validation attributes for expressions. | ||
/// </summary> | ||
public interface IValidationAttributeProvider | ||
{ | ||
/// <summary> | ||
/// Adds validation attributes to the <paramref name="attributes" /> if client validation is enabled. | ||
/// </summary> | ||
/// <param name="viewContext">A <see cref="ViewContext"/> instance for the current scope.</param> | ||
/// <param name="modelExplorer">The <see cref="ModelExplorer"/> for the <paramref name="expression"/>.</param> | ||
/// <param name="expression">Expression name, relative to the current model.</param> | ||
/// <param name="attributes"> | ||
/// The <see cref="Dictionary{TKey, TValue}"/> to receive the validation attributes. Maps the validation | ||
/// attribute names to their <see cref="string"/> values. Values must be HTML encoded before they are written | ||
/// to an HTML document or response. | ||
/// </param> | ||
/// <remarks> | ||
/// Adds nothing to <paramref name="attributes"/> if client-side validation is disabled or if attributes have | ||
/// already been generated for the <paramref name="expression"/> in the current <form>. | ||
/// </remarks> | ||
void AddValidationAttributes( | ||
ViewContext viewContext, | ||
ModelExplorer modelExplorer, | ||
string expression, | ||
IDictionary<string, string> attributes); | ||
} | ||
} |
111 changes: 111 additions & 0 deletions
111
src/Microsoft.AspNetCore.Mvc.ViewFeatures/ViewFeatures/ValidationAttributeProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using Microsoft.AspNetCore.Mvc.Internal; | ||
using Microsoft.AspNetCore.Mvc.ModelBinding; | ||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; | ||
using Microsoft.AspNetCore.Mvc.Rendering; | ||
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal; | ||
using Microsoft.Extensions.Options; | ||
|
||
namespace Microsoft.AspNetCore.Mvc.ViewFeatures | ||
{ | ||
/// <summary> | ||
/// Default implementation of <see cref="IValidationAttributeProvider"/>. | ||
/// </summary> | ||
public class ValidationAttributeProvider : IValidationAttributeProvider | ||
{ | ||
private readonly IModelMetadataProvider _metadataProvider; | ||
private readonly ClientValidatorCache _clientValidatorCache; | ||
private readonly IClientModelValidatorProvider _clientModelValidatorProvider; | ||
|
||
/// <summary> | ||
/// Initializes a new <see cref="ValidationAttributeProvider"/> instance. | ||
/// </summary> | ||
/// <param name="optionsAccessor">The accessor for <see cref="MvcViewOptions"/>.</param> | ||
/// <param name="metadataProvider">The <see cref="IModelMetadataProvider"/>.</param> | ||
/// <param name="clientValidatorCache">The <see cref="ClientValidatorCache"/> that provides | ||
/// a list of <see cref="IClientModelValidator"/>s.</param> | ||
public ValidationAttributeProvider( | ||
IOptions<MvcViewOptions> optionsAccessor, | ||
IModelMetadataProvider metadataProvider, | ||
ClientValidatorCache clientValidatorCache) | ||
{ | ||
if (optionsAccessor == null) | ||
{ | ||
throw new ArgumentNullException(nameof(optionsAccessor)); | ||
} | ||
|
||
if (metadataProvider == null) | ||
{ | ||
throw new ArgumentNullException(nameof(metadataProvider)); | ||
} | ||
|
||
if (clientValidatorCache == null) | ||
{ | ||
throw new ArgumentNullException(nameof(clientValidatorCache)); | ||
} | ||
|
||
_clientValidatorCache = clientValidatorCache; | ||
_metadataProvider = metadataProvider; | ||
|
||
var clientValidatorProviders = optionsAccessor.Value.ClientModelValidatorProviders; | ||
_clientModelValidatorProvider = new CompositeClientModelValidatorProvider(clientValidatorProviders); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public virtual void AddValidationAttributes( | ||
ViewContext viewContext, | ||
ModelExplorer modelExplorer, | ||
string expression, | ||
IDictionary<string, string> attributes) | ||
{ | ||
if (viewContext == null) | ||
{ | ||
throw new ArgumentNullException(nameof(viewContext)); | ||
} | ||
|
||
if (attributes == null) | ||
{ | ||
throw new ArgumentNullException(nameof(attributes)); | ||
} | ||
|
||
// Only render attributes if client-side validation is enabled, and then only if we've | ||
// never rendered validation for a field with this name in this form. | ||
var formContext = viewContext.ClientValidationEnabled ? viewContext.FormContext : null; | ||
if (formContext == null) | ||
{ | ||
return; | ||
} | ||
|
||
var fullName = viewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(expression); | ||
if (formContext.RenderedField(fullName)) | ||
{ | ||
return; | ||
} | ||
|
||
formContext.RenderedField(fullName, true); | ||
|
||
modelExplorer = modelExplorer ?? | ||
ExpressionMetadataProvider.FromStringExpression(expression, viewContext.ViewData, _metadataProvider); | ||
|
||
var validators = _clientValidatorCache.GetValidators(modelExplorer.Metadata, _clientModelValidatorProvider); | ||
if (validators.Count > 0) | ||
{ | ||
var validationContext = new ClientModelValidationContext( | ||
viewContext, | ||
modelExplorer.Metadata, | ||
_metadataProvider, | ||
attributes); | ||
|
||
for (var i = 0; i < validators.Count; i++) | ||
{ | ||
var validator = validators[i]; | ||
validator.AddValidation(validationContext); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.