Reputation: 912
I'm creating an ASP.NET core razor page web app, one of the pages need to be able to modify a Dictionary<string, string>
property.
The object i am trying to modify is as follows:
public class Element
{
[Key]
public string ID {get;set;}
public Dictionary<string, string> Values = new Dictionary<string, string>();
}
I am able to dispay the values on the page using the following code:
<form method="POST">
<ul>
<li hidden="true">ID: <input asp-for="FocusedItem.ID"/></li>
@for (int i = 0; i < Model.FocusedItem.Values.Count(); i++)
{
<li>@Model.FocusedItem.Values.ElementAt(i).Key: <input asp-for="@Model.FocusedItem.Values.ElementAt(i).Value"/></li>
}
</ul>
<br />
<input type="submit" value="Submit" />
</form>
The pagemodel cointains the following method to handle post events:
public void OnPost(Element FocusedItem)
{
}
The "ID" property is populated properly, however, the "Values" property has a count of 0 (the input values on the form are not binding to the Dictionaty). How can this be resplved?
Also bonus question - how can one add a new element to the dictionary?
Edit: Code - -cshtml: https://raw.githubusercontent.com/thezaza101/RDMUI/master/Pages/Data/ElementManager.cshtml -cs: https://raw.githubusercontent.com/thezaza101/RDMUI/master/Pages/Data/ElementManager.cshtml.cs
Upvotes: 2
Views: 9059
Reputation: 239430
@MarkG was close, but the actual syntax would be: Values[N].Key
and Values[N].Value
, where N
is your index. However, since you're using tag helpers to generate the fields, the true problem is your use of ElementAt
. Model expressions cannot include arbitrary methods, as there's no way to bind to something like ElementAt
in the resultant POST handling. Instead, you must use the indexing syntax, i.e. [i]
. However, there's where using a dictionary breaks down, as it can't be indexed by item position - only key.
Honestly, I tend to avoid posting dictionaries, as it's unstructured data. 99.99% of the time you'd probably be better served by breaking that off into a class with properties instead of a dictionary of keys. If you insist on using a dictionary, you can try passing the actual key values as indexers:
@foreach (var key in Model.Values.Keys)
{
<input asp-for="Values[key]" />
}
I haven't tried that personally, but I think it should work. Short of that, the only way I know works is generating the input names manually:
<input name="Values[@i].Key" value="@Model.Values.ElementAt(i).Key" />
<input name="Values[@i].Value" value="@Model.Values.ElementAt(i).Value" />
Upvotes: 12