How to bind list to a controller - asp.net-mvc

How to bind a list to a controller?
Code in my controller, HTTPGET and HTTPPOST :
public ActionResult Client(string id)
{
List<Customer> Contacts = WebService.GetContactsOfClient(id);
return View(Contacts);
}
[HttpPost]
public ActionResult Client(List<Customer> custs)
{
// custs = null!!! Why??
return View();
}
Code in my view :
<% using (Html.BeginForm("Client", "Formulaire", FormMethod.Post, new { id = "form" })) { %>
<% foreach (var item in Model) { %>
<%:item.MiseAjour %><br />
<% } %>
<input type="submit" />
<% } %>
Thank you all...

If you want to get some values back in your POST action you need to POST them which is achieved using input fields:
<% using (Html.BeginForm() { %>
<%= Html.EditorForModel() %>
<input type="submit" value="OK" />
<% } %>

This outlines what you're trying to achieve.
Model Bind to a List<> when Posting JavaScript Data Object
If you have specific questions, post them

Your view is not rendering any html input elements which are required if you want the model binder to put your model back together on the post. See this answer here which shows binding to a collection and posting to back. Also check out this post for binding to a dynamic list.

Solution for me :
<legend>Contacts</legend>
<% for (int i = 0; i < Model.Contacts.Count; i++) { %>
<%: Html.EditorFor(model => model.Contacts[i],"Contact") %>
<% } %>
With this, I bind my list to controller!
Thank you all!!

Related

MVC Binding to checkbox

I have found so many questions about this, but none of them go over or seem to go over my scenario. I have a model:
public class CheckBoxModel
{
public int Id{ get; set; }
public bool IsSelected { get; set; }
}
In then try and bind my IsSelected bool to a checkbox like this:
<%= Html.CheckBox("IsSelectedCheck",Model.IsSelected)%>
I have lots of items on a page, they all have a checkbox next to them, all i am trying to do is pass back to the controller all the id's of the items and which ones have been selected.
At the moment, the value of IsSelected is always false. Should Html.CheckBox set the value of Model.IsSelected each time the user toggles the checkbox.
Thanks
Try like this:
<%= Html.CheckBoxFor(x => x.IsSelected) %>
Also if you want to pass along the id don't forget to do so:
<%= Html.HiddenFor(x => x.Id) %>
And if you had a collection of those:
public class MyViewModel
{
public CheckBoxModel[] CheckBoxes { get; set; }
}
you could:
<% for (var i = 0; i < Model.CheckBoxes.Length; i++) { %>
<div>
<%= Html.HiddenFor(x => x.CheckBoxes[i].Id) %>
<%= Html.CheckBoxFor(x => x.CheckBoxes[i].IsSelected) %>
</div>
<% } %>
which will successfully bind to:
[HttpPost]
public ActionResult MyAction(MyViewModel model)
{
// model.CheckBoxes will contain everything you need here
...
}
An alternative to Darin's fantastic answer
I definitely recommend following Darin's approach for returning classes which will be most of the time. This alternative is a 'quick' and dirty hack if all you need is the checked Ids:
<% foreach (var cb in Model.CheckBoxes) { %>
<div>
<input type="checkbox"
value="<%= cb.Id %>"
<%= cb.IsSelected ? "checked=\"checked\"" : "" %>
name="ids" />
</div>
<% } %>
Will bind to the int[] ids parameter in the following action:
[HttpPost]
public ActionResult MyAction(int[] ids)
{
// ids contains only those ids that were selected
...
}
The benefit is cleaner html as there is no hidden input.
The cost is writing more code in the view.
In MVC 4.0 (Razor 2.0) you can use the following syntax in your view:
<input type="checkbox" value="#cb.Id" checked="#cb.IsSelected" name="ids" />

ASP.NET MVC form post parameter

I have a form in MVC:
<% using (Html.BeginForm("Get", "Person"))
{ %>
<%= Html.TextBox("person_id")%>
<input type="submit" value="Get Person" />
<% } %>
This redirects me to Person/Get. Okay. The question:
How do I make this Form so it redirects me to Person/Get/{person_id}?
Edit:
<% using (Html.BeginForm("Get", "Person", new { id = ??? }))
{ %>
<%= Html.TextBox("person_id")%>
<input type="submit" value="Get Person" />
<% } %>
What do I write in ???
I think the most difficult way would be using a javascript clientside.
The more straightforward way is to retrieve it on the action Person/Get and from there return a RedirectResult pointing to Person/Get/{person_id}
[HttpPost]
public ActionResult Get(string person_id)
{
return RedirectToAction("Get", "Person", new { id = person_id });
}
[HttpGet]
public ActionResult Get(string id)
{
//Do your thing
}
The redirect is usually so fast that the user will never notice. He/she will arrive at /Person/Get/{person_id}
What you want to do is specify the route values as the third parameter on the BeginForm method.
<% using (Html.BeginForm("Get", "Person", **new { person_id = this.Model}**))
{ %>
<%= Html.TextBox("person_id")%>
<input type="submit" value="Get Person" />
<% } %>
Then your controller action would look something like this
public ActionResult Get(int person_id)
{
return View(person_id);
}

How to check if checkbox is checked

I have question about accessing html.checkbox() in controller method.
In my view i have
<% foreach (var item in Model.PredmetTbl){ %>
<td>
<%:Html.CheckBox(item.Predmet) %>
<%:item.Predmet %>
</td>
<%} %>
Predemts are in DB and I want create new db records. How can i test if the checbox is checked or not ?
My controller code
[HttpPost]
public ActionResult PridajSaduPredmetov(int id, FormCollection data)
{
var zoznam = from predmet in ziakDB.PredmetTables select predmet;
ZoznamPredmetovTable predmety;
foreach (var item in zoznam)
{
if (HERE TESTING IF CHECKED)//IF Checked==true will add to db
{
predmety = new ZoznamPredmetovTable();
predmety.ZiakID = id;
predmety.PredmetID = item.PredmetID;
predmety.SkolskyRokID = IndexViewModel.GetSkolskyRokTeraz();
try
{
ziakDB.ZoznamPredmetovTables.InsertOnSubmit(predmety);
ziakDB.SubmitChanges();
}
catch { }
}
}
return RedirectToAction("DetailZiaka", "Administration", new { id = id });
}
(controlid).checked will return true/false
I did not make use of the html checkbox extension but I based my solution on this post:
How to handle checkboxes in ASP.NET MVC forms?
<% For Each item As x In Model.predmetTbl%>
<div><input type="checkbox" name="SelectedPredMet"
<% If Model.SelectedPredMet.Contains(item.Id) Then%>
checked="checked"
<% End If %>
value="<%: item.Id %>" /> <%: item.Predmet %></div>
<% Next%>

Wits End with IDictionary<T,T> and ModelBinders, ASP.NET MVC 2.0

Okay, I'm not trying to do anything super complex, I have searched, and searched, and roamed every blog and forum I can find. I am about to tear my hair out because no one just outright shows it working.
I want to use an IDictionary in my Model. Nevermind the reason why, that's irrelevant. I just want to do something very simple, and understand what is going on.
Can someone please help me figure out the HTML I should be putting in the View to make this work right? Please? I have tried Html.TextBoxFor and it comes back null on the postback. I have tried manually using the index of the dictionary item, and it comes back null. I am really getting frustrated, and all I keep seeing is redirection to blogs that don't answer the question.
Controller
public ActionResult DictionaryView()
{
var model = new Dictionary<string, int>
{
{ "First", 0 },
{ "Second", 0 },
{ "Third", 0 },
{ "Fourth", 0 }
};
return View(model);
}
[HttpPost]
public ActionResult DictionaryView(Dictionary<string, int> dictionary)
{
return null;
}
HTML
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<System.Collections.Generic.IDictionary<string,int>>" %>
<asp:Content ContentPlaceHolderID="MainContent" runat="server">
<h2>Dictionary</h2>
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<% for (int i = 0; i < Model.Count; i++) { %>
**// This is there I am stuck!**
<% } %>
<p>
<input type="submit" value="Submit" />
</p>
<% } %>
</asp:Content>
http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx
Example
<%
int i = 0;
foreach (KeyValuePair<string, int> pair in Model)
{ %>
<p>Key: <%= Html.TextBox(String.Format("[{0}].key", i), pair.Key)%></p>
<p>Value: <%= Html.TextBox(String.Format("[{0}].value", i), pair.Value)%></p>
<%
i++;
}
%>
Edit: This should work
Can you use a ViewModel (POCO) instead of a Dictionary? That way your model will have something you can select.
EDIT
ok. So my chops aren't perfect without intellisense... sorry. But this is my general idea
Public Function DictionaryView() As ActionResult
Dim model = New System.Collections.Generic.List(Of MyDictionary)
model.Add(new MyDictionary("First", 0))
model.Add(new MyDictionary("Second", 0))
model.Add(new MyDictionary("Third", 0))
model.Add(new MyDictionary("Forth", 0))
Return View(model)
End Function
''# This would be your view model.
Public Class MyDictionary
Public Property TheString
Public Property TheInt
End Class
Then in your view you can use
model.TheString
model.TheInt
Stacey,
I don't believe the ModelBinder (the default one anyway), will be able to figure out what you're trying to do, hence the IDictionary param being null.
Your items will be there in the Request.Params collection. For example:
Request.Params["First"]
will return whatever you entered in the first text box. From there, you can pluck them out by hand.
If you want to make this work without using a ViewModel as #rockinthesixstring suggested, you are most likely going to have to write a custom ModelBinder that would do what you want.
If you need an example of this, let me know and I'll dig up the custom model binder stuff.
BTW, a working view can look like this:
foreach (var pair in Model)
{
Response.Write(Html.TextBox(pair.Key, pair.Value));
}
You are missing the concept of how to have a separate counter so you have an index and also iterate through the dictionary with a foreach loop:
<% using (Html.BeginForm()) {%>
<%: Html.ValidationSummary(true) %>
<% int counter = 0;
foreach (var kv in Model) { %>
<input type="text" name="dictionary[<%= counter %>].Key" value="<%= kv.Key %>" />
<input type="text" name="dictionary[<%= counter %>].Value" value="<%= kv.Value %>" />
<%
counter++;
} %>
<p>
<input type="submit" value="Submit" />
</p>
<% } %>
Just tested this now, my Controller is a CCP of yours.
And FYI I simply read that blog post to get here. You just had to match your html elements to exactly what Scott posted.

ASP.NET MVC newbie: getting/passing data in dropdown form for multiple objects in an edit View

Using the Authors/Books catalog example, let's say I want to edit the info for the books of a specific author.
When someone navigates to domain.com/Books/Edit/2, I want to display an edit view for all the books where Author_ID = 2. Among the various book info is the book category (fiction, non-fiction, textbook, whatever) These categories are in their own table and are referenced by a Category_ID.
What's the best way to set up the edit form?
Currently in my controller I have something like this:
public ActionResult Edit(int id)
{
IQueryable<Book> books = bookRepository.FindBooksForAuthor(id);
return View(books);
}
And in my partial view:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IQueryable<Authors.Models.Book>>" %>
<%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Fields</legend>
<%var i = 0;
foreach (var book in Model)
{%>
<p>
<label for="Category_ID">Category_ID:</label>
<%= Html.TextBox("Category_ID", book.Category_ID)%>
<%= Html.ValidationMessage("Category_ID", "*")%>
</p>
<p>
<label for="Description">Description:</label>
<%= Html.TextBox("Description", book.Description)%>
<%= Html.ValidationMessage("Description", "*")%>
</p>
<%i++;
} %>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
Is my Inherits set properly at the top of the view since I'm passing an IQueryable object?
More importantly, how do I get the Category_ID field to be a DropDown with the correct category selected?
Can I just send the data for the dropdown to the view and figure out the selected item at the view level?
ViewData["categories"] = new SelectList(_db.BookCategories.ToList().OrderBy(b => b.Category_Title), "Category_ID", "Category_Title");
You could create view model class containing list of books and select list of categories:
public class BooksEditViewModel
{
public IQueryable<Authors.Models.Book> Books { get; set; }
public IQueryable<BookCategory> BookCategories { get; set; }
}
Then use BooksEditViewModel as view model
System.Web.Mvc.ViewUserControl<BooksEditViewModel>
and code dropdown with
Html.DropDownList("Category_ID", new SelectList(Model.BookCategories,"Category_ID", "Category_Title",book.Category_ID);
You should also read about list binding:
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx

Resources