input type = "hidden" asp-for = не работает для List - PullRequest
0 голосов
/ 30 октября 2019

Я ищу умный способ сохранить значения списка в hidden input в форме и получить значение обратно в моей модели представления при публикации формы.

В моей модели представления яесть список с SelectListItem пунктов. Список используется как asp-items в элементе select. Теперь, когда пользователь отключил записи и отправил форму с ошибками, я хочу повторно отобразить форму без необходимости повторного создания списка.

Свойство выглядит следующим образом:

public IReadOnlyCollection<SelectListItem> UserLevels { get; set; }

Inв режиме просмотра бритвы это не приведет к правильному сохранению значений UserLevels:

<input type="hidden" asp-for="UserLevels"/>

Я нашел этот вопрос о похожей проблеме , но не нашел там хорошего решения. Кто-нибудь знает умный способ набросать значения списка?

Ответы [ 2 ]

0 голосов
/ 30 октября 2019

После некоторых поисков и экспериментов я нашел хорошее решение.

Я создал два метода расширения SerializeForHidden и DeserializeForHidden (см. Ниже) и добавил дополнительное свойство в модель представления:

public string UserLevelsHidden
{
    get => UserLevels.SerializeForHidden();
    set => UserLevels = value.DeserializeForHidden(UserLevels);
}

Теперь значения UserLevels сохраняются в форме и воссоздаются в записи с:

<input type="hidden" asp-for="UserLevelsHidden"/>

Это будет работать для любого сериализуемого типа, а не только для списков.

Методы расширения:

using Newtonsoft.Json;
using System.Web;

namespace Forestbrook.Web
{
    public static class WebHelper
    {
        /// <summary>
        /// Deserialize a value from a hidden HTML Form field which was serialized
        /// with SerializeForHidden to its original type.
        /// </summary>
        /// <typeparam name="T">Type to deserialize to</typeparam>
        /// <param name="value">serialized and HtmlEncoded string from HTML form</param>
        /// <param name="_">Target property only used to simplify detection of T. May be null.</param>
        /// <returns>Deserialized object or null when value was null or empty</returns>
        public static T DeserializeForHidden<T>(this string value, T _)
        {
            if (string.IsNullOrEmpty(value))
                return default;

            return JsonConvert.DeserializeObject<T>(HttpUtility.HtmlDecode(value));
        }

        /// <summary>
        /// Serialize a complex value (like a List) to be stored in a hidden HTML Form field
        /// </summary>
        /// <param name="value">Value to serialize</param>
        /// <returns>Json serialized and HtmlEncoded string</returns>
        public static string SerializeForHidden(this object value)
        {
            if (value == null)
                return null;

            return HttpUtility.HtmlEncode(JsonConvert.SerializeObject(value,
                new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore }));
        }
    }
}

Помните, что параметр T _ в DeserializeForHidden добавлен только для упрощения использования DeserializeForHidden. Вы можете удалить его, если хотите, но тогда вам всегда нужно указывать тип.

0 голосов
/ 30 октября 2019

Вы можете попытаться сделать то, что предлагается в ответе, на который вы ссылаетесь.

Вместо того, чтобы скрывать все это, скрывайте элемент за элементом.

Это будет примерно так

@for(int i = 0; i < UserLevels.Count; i++)
{
    <input type="hidden" asp-for="UserLevels[i]"/>

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...