115 lines
3.8 KiB
C#
115 lines
3.8 KiB
C#
// 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 System.Net.Http.Formatting;
|
|
using System.Text;
|
|
|
|
namespace Microsoft.AspNet.Mvc.WebApiCompatShim
|
|
{
|
|
public static class FormDataCollectionExtensions
|
|
{
|
|
// This is a helper method to use Model Binding over a JQuery syntax.
|
|
// Normalize from JQuery to MVC keys. The model binding infrastructure uses MVC keys
|
|
// x[] --> x
|
|
// [] --> ""
|
|
// x[field] --> x.field, where field is not a number
|
|
public static string NormalizeJQueryToMvc(string key)
|
|
{
|
|
if (key == null)
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
StringBuilder sb = null;
|
|
var i = 0;
|
|
while (true)
|
|
{
|
|
var indexOpen = key.IndexOf('[', i);
|
|
if (indexOpen < 0)
|
|
{
|
|
// Fast path, no normalization needed.
|
|
// This skips the string conversion and allocating the string builder.
|
|
if (i == 0)
|
|
{
|
|
return key;
|
|
}
|
|
sb = sb ?? new StringBuilder();
|
|
sb.Append(key, i, key.Length - i);
|
|
break; // no more brackets
|
|
}
|
|
|
|
sb = sb ?? new StringBuilder();
|
|
sb.Append(key, i, indexOpen - i); // everything up to "["
|
|
|
|
// Find closing bracket.
|
|
var indexClose = key.IndexOf(']', indexOpen);
|
|
if (indexClose == -1)
|
|
{
|
|
throw new ArgumentException(Resources.JQuerySyntaxMissingClosingBracket, nameof(key));
|
|
}
|
|
|
|
if (indexClose == indexOpen + 1)
|
|
{
|
|
// Empty bracket. Signifies array. Just remove.
|
|
}
|
|
else
|
|
{
|
|
if (char.IsDigit(key[indexOpen + 1]))
|
|
{
|
|
// array index. Leave unchanged.
|
|
sb.Append(key, indexOpen, indexClose - indexOpen + 1);
|
|
}
|
|
else
|
|
{
|
|
// Field name. Convert to dot notation.
|
|
sb.Append('.');
|
|
sb.Append(key, indexOpen + 1, indexClose - indexOpen - 1);
|
|
}
|
|
}
|
|
|
|
i = indexClose + 1;
|
|
if (i >= key.Length)
|
|
{
|
|
break; // end of string
|
|
}
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
|
|
public static IEnumerable<KeyValuePair<string, string>> GetJQueryNameValuePairs(
|
|
this FormDataCollection formData)
|
|
{
|
|
if (formData == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(formData));
|
|
}
|
|
|
|
var count = 0;
|
|
|
|
foreach (var kv in formData)
|
|
{
|
|
ThrowIfMaxHttpCollectionKeysExceeded(count);
|
|
|
|
var key = NormalizeJQueryToMvc(kv.Key);
|
|
var value = kv.Value ?? string.Empty;
|
|
yield return new KeyValuePair<string, string>(key, value);
|
|
|
|
count++;
|
|
}
|
|
}
|
|
|
|
private static void ThrowIfMaxHttpCollectionKeysExceeded(int count)
|
|
{
|
|
if (count >= MediaTypeFormatter.MaxHttpCollectionKeys)
|
|
{
|
|
var message = Resources.FormatMaxHttpCollectionKeyLimitReached(
|
|
MediaTypeFormatter.MaxHttpCollectionKeys,
|
|
typeof(MediaTypeFormatter));
|
|
throw new InvalidOperationException(message);
|
|
}
|
|
}
|
|
}
|
|
}
|