| File: ModelBinding\JQueryKeyValuePairNormalizer.cs | Web Access |
| Project: src\aspnetcore\src\Mvc\Mvc.Core\src\Microsoft.AspNetCore.Mvc.Core.csproj (Microsoft.AspNetCore.Mvc.Core) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable enable using System.Text; using Microsoft.AspNetCore.Mvc.Core; using Microsoft.Extensions.Primitives; namespace Microsoft.AspNetCore.Mvc.ModelBinding; // Normalizes keys, in a KeyValuePair collection, from jQuery format to a format that MVC understands. internal static class JQueryKeyValuePairNormalizer { public static IDictionary<string, StringValues> GetValues( IEnumerable<KeyValuePair<string, StringValues>> originalValues, int valueCount) { var builder = new StringBuilder(); var dictionary = new Dictionary<string, StringValues>( valueCount, StringComparer.OrdinalIgnoreCase); foreach (var originalValue in originalValues) { var normalizedKey = NormalizeJQueryToMvc(builder, originalValue.Key); builder.Clear(); dictionary[normalizedKey] = originalValue.Value; } return dictionary; } // This is a helper method for Model Binding over a JQuery syntax. // Normalize from JQuery to MVC keys. The model binding infrastructure uses MVC keys. // x[] --> x // [] --> "" // x[12] --> x[12] // x[field] --> x.field, where field is not a number private static string NormalizeJQueryToMvc(StringBuilder builder, string key) { if (string.IsNullOrEmpty(key)) { return string.Empty; } var indexOpen = key.IndexOf('['); if (indexOpen == -1) { // Fast path, no normalization needed. // This skips string conversion and allocating the string builder. return key; } var position = 0; while (position < key.Length) { if (indexOpen == -1) { // No more brackets. builder.Append(key, position, key.Length - position); break; } builder.Append(key, position, indexOpen - position); // everything up to "[" // Find closing bracket. var indexClose = key.IndexOf(']', indexOpen); if (indexClose == -1) { throw new ArgumentException( message: Resources.FormatJQueryFormValueProviderFactory_MissingClosingBracket(key), paramName: nameof(key)); } if (indexClose == indexOpen + 1) { // Empty brackets signify an array. Just remove. } else if (char.IsDigit(key[indexOpen + 1])) { // Array index. Leave unchanged. builder.Append(key, indexOpen, indexClose - indexOpen + 1); } else { // Field name. Convert to dot notation. if (builder.Length != 0) { // Was x[field], not [field] or [][field]. builder.Append('.'); } builder.Append(key, indexOpen + 1, indexClose - indexOpen - 1); } position = indexClose + 1; indexOpen = key.IndexOf('[', position); } return builder.ToString(); } }