输入type =“ hidden” asp-for =不适用于列表

时间:2019-10-30 14:04:50

标签: c# asp.net-core

我正在寻找一种聪明的方法来将List的值存储在表单中的hidden input中,并在表单发布后将其返回到我的视图模型中。

在我的视图模型中,我有一个包含SelectListItem个项目的列表。该列表在asp-items元素中用作select。现在,当用户关闭了脚本并张贴了带有错误的表单时,我想重新显示表单而不必重新创建列表。

属性如下:

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

在剃刀视图中,这将无法正确保存UserLevels的值:

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

我找到了this question about a similar problem,但在那里没有找到一个好的解决方案。有谁知道一种巧妙的方法来破坏列表的值?

3 个答案:

答案 0 :(得分:0)

您可以尝试执行所链接的答案中建议的操作。

与其隐藏所有内容,不如逐个隐藏元素。

会是这样

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

}

答案 1 :(得分:0)

经过一些搜索和实验,我找到了一个不错的解决方案。

我创建了两个扩展方法SerializeForHiddenDeserializeForHidden(见下文),并在视图模型中添加了一个额外的属性:

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 }));
        }
    }
}

请注意,仅在DeserializeForHidden中添加T _参数是为了使DeserializeForHidden的使用更加容易。您可以根据需要将其删除,但是始终必须指定类型。

答案 2 :(得分:0)

只需通过模型添加增值属性即可对其进行分配。 尝试以下代码:

<input type="hidden" asp-for="UserLevels" value="@Model.UserLevels" />