我正在寻找一种聪明的方法来将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,但在那里没有找到一个好的解决方案。有谁知道一种巧妙的方法来破坏列表的值?
答案 0 :(得分:0)
您可以尝试执行所链接的答案中建议的操作。
与其隐藏所有内容,不如逐个隐藏元素。
会是这样
@for(int i = 0; i < UserLevels.Count; i++)
{
<input type="hidden" asp-for="UserLevels[i]"/>
}
答案 1 :(得分:0)
经过一些搜索和实验,我找到了一个不错的解决方案。
我创建了两个扩展方法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 }));
}
}
}
请注意,仅在DeserializeForHidden中添加T _
参数是为了使DeserializeForHidden的使用更加容易。您可以根据需要将其删除,但是始终必须指定类型。
答案 2 :(得分:0)
只需通过模型添加增值属性即可对其进行分配。 尝试以下代码:
<input type="hidden" asp-for="UserLevels" value="@Model.UserLevels" />