Hello I have a model object defined in an MVC 3 project that has a Dictionary property as follows:
MyObj.ObjDictionary<string,string>
I have two controller methods, one which handles returning the view and another that handles the POSTed form from the view
public ActionResult Scanner(string val_1, string val_2, string val_3)
{
//Fetch sessionObj from Model
MyObj sessionObj = getSessionObj(val_1, val_2, val_3);
//At this point model.ObjDictionary<string,string> contains data
return View(sessionObj);
}
[HttpParamAction]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Scanner(MyObj model)
{
//At this point model.ObjDictionary<string,string> is null
//i.e. binding is not being properly achieved
//Validate POSTed data
}
In the View, I iterate through each key-value pair (kvp). It has to be done this way since the property is dynamic and I have no way of knowing how many dictionary values there will be.
#using (Html.BeginForm("Action", "Home"))
{
#foreach (var kvp in Model.ObjDictionary)
{
<span>#Html.Label("Scan " + #kvp.Key)</span>
<span>#Html.TextBox(kvp.Key, "", new { #style = "font-size:Medium;width:400px;" })</span>
}
<input type="submit" name="Cancel" value="Cancel" />
<input type="submit" id="Scanner" name="Scanner" value="Scanner" />
}
The goal is to provide a way for users to input data and have that data bound to the values of the specific key. My problem is that the Model.ObjDictionary is null when it gets POSTed. I'm not sure what I'm doing wrong, I read over this article, but this assumes pre-existing values in a dictionary. Is there a way the ModelBinder can bind the data, entered by a user, to a dictionary value mapped to a specific key?
The article you referenced answers your question, you simply need to provide the correct names for your controls, try:
#using (Html.BeginForm("Action", "Home")) {
var i = 0;
foreach (var kvp in Model.ObjDictionary)
{
#Html.Hidden("ObjDictionary[" + i + "].Key", kvp.Key)#kvp.Key
<span>#Html.TextBox("ObjDictionary[" + i + "].Value", kvp.Value, new { #style = "font-size:Medium;width:400px;" })</span>
i++;
<br />
}
<input type="submit" value="Submit" />
}
For dictionaries, each entry should have one field for the key and one field for the value.
#using (Html.BeginForm("Action", "Home"))
{
var index = 0;
#foreach (var kvp in Model.ObjDictionary)
{
<span>#Html.Hidden("ObjDictionary[" + index + "].Key", kvp.Key)
<span>#Html.Label("Scan " + #kvp.Key)</span>
<span>#Html.TextBox("ObjDictionary[" + index + "].Value", kvp.Value, new { #style = "font-size:Medium;width:400px;" })</span>
index++;
}
<input type="submit" name="Cancel" value="Cancel" />
<input type="submit" id="Scanner" name="Scanner" value="Scanner" />
}
By the way, I have encapsulated this functionality in an HTML helper class. You can find it and a working demonstration here: https://github.com/ErikSchierboom/aspnetmvcdictionaryserialization
Related
I need to pass a form element into an MVC4 view using ViewBag. The Viewbag is a list of 1 or more records for each user. The issue is nothing is being passed.
controller
// grab all records for user id 26000.
var qry = db.users.Where(m => m.user_id == "26000").ToList();
foreach (var myBag in qry)
{
// place all the items in the Viewbag.
ViewBag.myItems = "<input type='text' name=#ViewBag.myBag value=#ViewBag.myBag>";
}
view
#using (Html.BeginForm("Index", "Home"))
{
foreach (var item in ViewBag.myBag)
{
<label for="#item">#item</label>
<input type="checkbox" name="#item" value="#item"/>
}
<input id='btnSubmit' type="submit" value='submit' />
}
Controller (the query should really be in your Model).
ViewBag.myItems = db.users.Where(m => m.user_id == "26000").ToList();
View
#using (Html.BeginForm("Index", "Home"))
{
foreach (var item in ViewBag.myItems)
{
<input type="text" name="#item.user_id" value="#item.user_name">
}
<input id='btnSubmit' type="submit" value='submit' />
}
I have a webgrid contains a dropdown which contains different items for each user(Items are grouped). I want to get the selected values to the controller . How can I do that. Heres my ;
Model :
public SelectList AvailableDevices { get; set; }
View :
...
var grid = new WebGrid(Model. ...
..
..
grid.Column(header: "AvailableDevices", format: #item => Html.DropDownList("value", (IEnumerable<SelectListItem>)item.AvailableDevices)),
And I have a Submit Button
#using (Html.BeginForm("AssignUserDevices", "Device"))
{
<input type="submit" value="setUserDevice" onchange="CheckSelectedDevices()" />
}
I want to set users device according to his user type. I know what his choices and send dropdown items according to his type. So each item in webgrid differs from each other.
And Also I dont know how to give indices to each item in webgrid.( I think we will need it.)
Im new at MVC so hope you will understand.
Thanks;
What I got from our requirement that you want the selected item and have that item value in form field before posting if yes then you can follow as given.
#Html.DropDownList("value", (IEnumerable<selectlistitem>)item.AvailableDevices), new {#class="deviceclass"} )
#using (Html.BeginForm("AssignUserDevices", "Device"))
{
<input type="hidden" value="" name="deviceId" id="deviceId" />
<input type="hidden" value="" name="userId" />
<input type="submit" value="setUserDevice" />
}
<script>
$(".deviceclass").on('change', function () {
var dropdownvalue = $(this).val();
$('#deviceId').val(dropdownvalue);
})
</script>
and you can define an action function in controller
public ActionResult Details(string deviceId, string userId)
{
// do as you need.
return View();
}
I think I may be a little confused :-\
I have a basic scenario whereby I need to render out a list of forms. I have a basic ViewModel that contains a collection of entities. I have an EditorFor template for the entity in question that renders a basic set of inputs.
It looks as follows:
#for (var i = 0; i < Model.Count(); i++)
{
using (Html.BeginForm("Update", "VehicleLog", new { id = Model[i].id }, FormMethod.Post, new { #class = "vehicle-update-form std-form", data_ajaxpost = "true", data_refreshcontainer = "#vehicle-ajax-holder" }))
{
#Html.EditorFor(model => model[i])
<div class="buttons right">
<input type="submit" value="Save" name="action" class="btn-ok btn" />
<input type="submit" value="Delete" name="action" class="btn-warning btn" />
</div>
}
}
I have a for loop that then dumps out these editor template. So far so good.
My issue is that I wish to use UpdateModel in my POST action to update the entity. However, the data being sent to the controller takes the following format:
My incomplete action looks as follows:
[HttpPost]
public ActionResult Update(int id, FormCollection data, string action)
{
var response = new JsonResponse();
if (action == "Update")
{
var v = UnitOfWork.VehicleRepository.GetById(id);
UpdateModel(v);
}
return Json(response);
}
My issue is that the EditorFor helpers is (and rightly so) prefixing names with array indexes, eg [0].name. As such I am unable to use the UpdateModel method to update an entity.
Any advice appreciated!
can someone tell me if im on the right track? Im trying to display my query but i get an error. I have two textbox with the same parameter and that parameter is declared as an IEnumerable.
[HttpPost]
public ActionResult Orders1(IEnumerable<int> order)
{
using (CostcoEntities1 context = new CostcoEntities1())
{
var query = string.Empty;
foreach (var orderID in order)
{
query = (from a in context.CM_Checkout_Details
where a.CheckoutDetails_ID == orderID
select a).ToString();
}
return View(query);
}
}
this is what my controller looks like..
I am trying to read the two numbers(Id) in the text box and diplay data based on those id.
#using (Html.BeginForm("Orders1", "Track", FormMethod.Post))
{
#Html.TextBox("order")<br />
#Html.TextBox("order")
<input type="submit" value="Submit" />
}
First thing, change the names of the textboxes so that they are not the same:
#using (Html.BeginForm("Orders1", "Track", FormMethod.Post))
{
#Html.TextBox("order1")<br />
#Html.TextBox("order2")
<input type="submit" value="Submit" />
}
Next, change the signature of your action method:
[HttpPost]
public ActionResult Orders1(string order1, string order2)
MVC's model binding will try to match order1 and order2 to stuff in Request.Form, for example, which should pick up the textbox values.
I have two pages, one that edits user information, and one that edits information in a pictures table. I recently stopped using strongly typed viewmodels due to the varying types of data required on each page.
The page that edits the user information works fine, but the page that edits picture information does not post back any of the edits that are made in the input fields; except for the ID, which is correct, all the other values come back as null. They both seem to be structured exactly the same way -- I can't figure out what's the difference. As far as I can tell the code for both pages are the same, but I'm not getting data back on the second one.
User Controller and View which works
Controller
public ActionResult Preferences()
{
int userid = getUserID(User.Identity.Name);
// Info for user preferences
var accountInfo = db.users.Single(l => l.ID == userid);
ViewData["accountInfo"] = accountInfo;
AccountController usr = new AccountController(); // Info for user menu
ViewData["userInfo"] = usr.getUserInfo(User.Identity.Name);
return View();
}
[HttpPost]
public ActionResult Preferences(user accountInfo, string oldPW)
{
// Do stuff to save user info
return RedirectToAction(actionname, routeValues);
}
View
#using (Html.BeginForm("Preferences", null, FormMethod.Post,
new { id = "prefsform" }))
{
AutoShowApp_MVC.user item = new AutoShowApp_MVC.user();
item = ViewBag.accountInfo;
<input id="lastname" name="lastname" type="text" value="#item.lastname"/>
<input id="address1" name="address1" type="text" value="#item.address1"/>
<input id="city" name="city" type="text" value="#item.city"/>
<input id="state" name="state" type="text" value="#item.state"/>
<input type="submit" value="Submit Changes" />
}
Picture Controller and View which DON'T work
Controller:
public ActionResult Edit(long id)
{
var picInfo = db.lmit_pics.Single(l => l.ID == id);
ViewData["picInfo"] = picInfo; // get Picture Info
// Get User Info for menu
AccountController usr = new AccountController();
ViewData["userInfo"] = usr.getUserInfo(User.Identity.Name);
return View();
}
[HttpPost]
public ActionResult Edit(lmit_pics picInfo)
{
// Do stuff to save picInfo
return RedirectToAction("Index");
}
View:
#using (Html.BeginForm("Edit", null, FormMethod.Post, new { id = "editform" }))
{
AutoShowApp_MVC.lmit_pics item = new AutoShowApp_MVC.lmit_pics();
item = ViewBag.picInfo;
<input type="text" id="model" value="#item.model" />
<input type="text" id="description" value="#item.description" />
<input type="submit" value="Save" />
}
You do not have the name attribute specified on the inputs on your picture editing form.
<input type="text" id="model" value="#item.model" />
Should Be
<input type="text" id="model" name="model" value="#item.model" />
The form collection works from the name attribute, not the Id attribute which is why you are not getting any data back (you are, it is just not properly attributed).
However, I agree with Wahid above, using strongly typed view models, editorFor helpers, etc not only help to prevent issues such as the above, but really go a long way in making a more secure, easier to maintain site.