My controller action method passes a Dictionary<string, double?>
to the view. I have the following in my view:
<% foreach (var item in Model.Items) { %>
<%: Html.Label(item.Key, item.Key)%>
<%: Html.TextBox(item.Key, item.Value)%>
<% } %>
Below is my action method which handles the POST operation:
[HttpPost]
public virtual ActionResult MyMethod(Dictionary<string, double?> items)
{
// do stuff........
return View();
}
When I enter the some values into the textbox and hit the submit button the POST action method is not getting any items back? What am I doing wrong?
Model binding is a well-designed bridge between the HTTP request and the C# action methods. Data from HTTP requests are used by controllers and Razor pages. Route data, for example, may serve as a record key, while posted form fields may serve as values for model properties.
Model binding is a well-designed bridge between the HTTP request and the C# action methods. It makes it easy for developers to work with data on forms (views), because POST and GET is automatically transferred into a data model you specify. ASP.NET MVC uses default binders to complete this behind the scene.
Model Binding is the most powerful mechanism in Web API 2. It enables the response to receive data as per requester choice. i.e. it may be from the URL either form of Query String or Route data OR even from Request Body. It's just the requester has to decorate the action method with [FromUri] and [FromBody] as desired.
Model binding allows controller actions to work directly with model types (passed in as method arguments), rather than HTTP requests. Mapping between incoming request data and application models is handled by model binders.
I would recommend you reading this blog post about how your input fields should be named so that you can bind to a dictionary. So you will need an additional hidden field for the key:
<input type="hidden" name="items[0].Key" value="key1" />
<input type="text" name="items[0].Value" value="15.4" />
<input type="hidden" name="items[1].Key" value="key2" />
<input type="text" name="items[1].Value" value="17.8" />
which could be generated with something along the lines:
<% var index = 0; %>
<% foreach (var key in Model.Keys) { %>
<%: Html.Hidden("items[" + index + "].Key", key) %>
<%: Html.TextBox("items[" + index +"].Value", Model[key]) %>
<% index++; %>
<% } %>
This being said, personally I would recommend you NOT using dictionaries in your views. They are ugly and in order to generate proper names for the model binder you need to write ugly code. I would use view models. Here's an example:
Model:
public class MyViewModel
{
public string Key { get; set; }
public double? Value { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new[]
{
new MyViewModel { Key = "key1", Value = 15.4 },
new MyViewModel { Key = "key2", Value = 16.1 },
new MyViewModel { Key = "key3", Value = 20 },
};
return View(model);
}
[HttpPost]
public ActionResult Index(IEnumerable<MyViewModel> items)
{
return View(items);
}
}
View (~/Views/Home/Index.aspx
):
<% using (Html.BeginForm()) { %>
<%: Html.EditorForModel() %>
<input type="submit" value="OK" />
<% } %>
Editor Template (~/Views/Home/EditorTemplates/MyViewModel.ascx
):
<%@ Control
Language="C#"
Inherits="System.Web.Mvc.ViewUserControl<Models.MyViewModel>" %>
<%: Html.HiddenFor(x => x.Key) %>
<%: Html.TextBoxFor(x => x.Value) %>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With