Why is it removed: ASP.NET MVC CheckBoxList (without MVCContrib) - asp.net-mvc

Why is the CheckBoxList removed from ASP.NET MVC preview release 5?
Currently I don't see any way in which I can create a list of checkboxes (with similar names but different id's) so people can select 0-1-more options from the list.
There is an CheckBoxList list present in the MVCContrib library, but it is deprecated. I can understand this for the other HtmlHelpers, but there does not seem to be a replacement for the CheckBoxList in preview 5.
I would like to create a very simple list like you see below, but what is the best way to do this using ASP.NET MVC preview release 5?
<INPUT TYPE="checkbox" NAME="Inhoud" VALUE="goed"> goed
<INPUT TYPE="checkbox" NAME="Inhoud" VALUE="redelijk"> redelijk
<INPUT TYPE="checkbox" NAME="Inhoud" VALUE="matig"> matig
<INPUT TYPE="checkbox" NAME="Inhoud" VALUE="slecht"> slecht

A for loop in the view to generate the checkboxes
<% foreach(Inhoud i in ViewData["InhoudList"] as List<Inhoud>) { %>
<input type="checkbox" name="Inhoud" value="<%= i.name %>" checked="checked" /> <%= i.name %>
<% } %>
Don't use Html.Checkbox, as that will generate two values for each item in the list (as it uses a hidden input for false values)

I recently blogged about implementing the CheckBoxList helper in the MVC Beta. Here is the link.

I have my own implementation of CheckListBox which has support for ModelState.
If you are interested it's in Un CheckBoxList que funciona en ASP.NET MVC. The post is in Spanish, but you shouldn't have any problems reading the code.
What is interesting in Jeremiah solution is the fact that you can set the initial state of the checkboxes, something you can't do with my CheckListBox.

I recommend using JeremiahClark extension posted above. (CheckBoxList)
My controller resulted into very simple instructions. For clarify I add a fragment of my code that's absent in the sample.
var rolesList = new List<CheckBoxListInfo>();
foreach (var role in Roles.GetAllRoles())
{
rolesList.Add(new CheckBoxListInfo(role, role, Roles.IsUserInRole(user.UserName, role)));
}
ViewData["roles"] = listaRoles;
And in the view:
<div><%= Html.CheckBoxList("roles", ViewData["roles"]) %></div>
That's all.

Related

How do i create dynamic properties in Model and use in Controller and View. - MVC

I am looking for a solution which creates dynamic properties to be create in Model.
I want to use them in my View and Controller.
Can any one have idea, how to create it?
I am having scenario in my project where one page will be having options to be lets say Profile2, Profile5 etc.
Profile 2 can have two URLs to be submit from user.
Profile 5 can have five URLs to be submit from user.
and
So on........
Is there any solution or alternative to do this????
He Amit , For your situation "I am having scenario in my project where one page will be having options to be lets say Profile2, Profile5 etc.
Profile 2 can have two URLs to be submit from user.
Profile 5 can have five URLs to be submit from use"
You want to put this url in your properties ok.
SO do one thing create a property like this.
public List<string> urlList {get;set;}
use this in your property andd add url in the list.
you can add n no of urls.
That is exactly what ViewBag is for. Its a dynamic property on Controller and View.
public ActionResult SomeAction()
{
ViewBag.Message = "Hello, world";
}
<p>#ViewBag.Message</p>
This will allow you to send anonymous property values from your Controller to your View. However, if you're looking to post different numbers of values (urls in your example), you should use an IList as your model.
#model IList<string>
#for (int i = 0; i < Model.Count; i++)
{
#Html.EditorFor(model => model[i])
}
Your model should probably store the values in a list. Here is an example explaining how to display and save data for a list property.
How to interact with List<t> in MVC
see this is what i have done as an alternative.
Make all divs and other fields in MODEL and use jQuery to work around.
I guess this is an alternative, but not exactly what i want. Still looking for answer. I post this as this can be helpful to some one in future.
Please check below.
<div>
#for (var i = 0; i < ProfileCount; i++)
{
<label>
URL:</label>
<input type="text" id=#string.Format("URL{0}", i) />
<label>
CheckName:</label>
<input type="text" id=#string.Format("URL{0}CheckName", i) />
<label>
Run Check From:</label>
#Html.DropDownList(string.Format("URL{0}Region", i), (IEnumerable<SelectListItem>)ViewBag.Regions)
<br />
<span id=#string.Format("URL{0}Result", i)></span>
<input type="button" value="Create check" id=#string.Format("URL{0}CheckSetup", i) onclick="getResponseFromUrl('#string.Format("URL{0}')", i);" />
<input type="button" value="Delete check" id=#string.Format("URL{0}Delete", i) onclick="DeleteCheck('#string.Format("URL{0}')", i);"
style="display: none" />
<input type="hidden" id=#string.Format("URL{0}Hidden", i) />
<br />
<br />
<br />
}
</div>

ASP.NET MVC 2: Better way to handle multiple buttons in each HTML table row?

I have an HTML table where each row has buttons which toggle status bits in the database for each row. Assuming Javascript is not an option, what would be the "best practice" way of handling this?
I'm currently handling it by wrapping each row in a form like this:
<table>
<tr>
<td>
<form action="/FooArea/BarController/BazAction" id="frm0" name="frm0" method="post">
<span>Item 1</span>
<input type="submit" value="Toggle1" name="submitButton" />
<input type="submit" value="Toggle2" name="submitButton" />
<input type="hidden" name="itemID" value="1" />
</form>
</td>
</tr>
<tr>
<td>
<form action="/FooArea/BarController/BazAction" id="frm1" name="frm1" method="post">
<span>Item 2</span>
<input type="submit" value="Toggle1" name="submitButton" />
<input type="submit" value="Toggle2" name="submitButton" />
<input type="hidden" name="itemID" value="2" />
</form>
</td>
</tr>
</table>
And the post method looks something like this:
string buttonName = Request.Form["submitButton"];
if (!String.IsNullOrEmpty(buttonName ))
{
int itemID = Convert.ToInt32(Request.Form["itemID"]);
switch (buttonName )
{
case "Toggle1":
DoSomething(itemID);
break;
case "Toggle2":
DoSomethingElse(itemID);
break;
}
}
Any better suggestions? Is having 50 forms on a page cool? I dunno.. let me know what you are doing in this case.
The best way to handle POST scenarios without JavaScript is, as several others have stated, a tiny form with only the necessary values, and only one submit button. Basically, what you should do is to create a helper method that creates a form with the necessary POST values in hidden fields and a submit button. For example, you could have a method you use like this:
<%= Html.PostLink("FooArea/BarController/BazAction", "Toggle1", new List<KeyValuePair<string, string>>{ new KeyValuePair<string, string>("itemId", 1), new KeyValuePair("action", "option1") }); %>
It looks pretty verbose, but I've tried to make it as generic as possible. You can probably create the List<KeyValuePair<string, string>> in the controller when you render the view, so you only have to call something
<%= Html.PostLink("FooArea/BarController/BazAction", "Toggle1", Model.Values) %>
In the action method that handles the post, you bind to the posted FormCollection, and retrieve the values of itemId and action to determine what to do, instead of checking for Request.Form values.
An implementation of the helper method might look like this:
public static string PostLink(this HtmlHelper helper, string postAction, string submitText, IEnumerable<KeyValuePair<string, string>> postValues)
{
var form = new TagBuilder("form");
// Setup basic properties like method, action
form.Attributes.Add("method", "post");
form.Attributes.Add("action", postAction);
// Instantiate a stringbuilder for the inner html of the form
var innerHtml = new StringBuilder();
// Create and append hidden fields for the post values
foreach(var value in postValues)
{
var hidden = new TagBuilder("input");
hidden.Attributes.Add("type", "hidden");
hidden.Attributes.Add("name", value.Key);
hidden.Attributes.Add("value", value.Value);
innerHtml.Append(hidden.ToString(TagRenderMode.SelfClosing));
}
// Create the submit button
var submit = new TagBuilder("input");
submit.Attributes.Add("type", "submit");
submit.Attributes.Add("value", submitText);
// Append it to the stringbuilder
innerHtml.Append(submit.ToString(TagRenderMode.SelfClosing));
// Set the InnerHtml property of the form, and return it
form.InnerHtml = innerHtml.ToString();
return form.ToString(TagRenderMode.Normal);
}
This seems like a prime case for some JQuery and Ajax functionality. But if javascript isn't an option then i think wrapping each one in a form is probably the most simple solution.
When I need to do something like this I do it pretty much the same way as you do here. It is no problem to have multiple forms in one view. Its like having multiple links in one view (but they use POST instead of GET). I guess many .net developers think its wrong because of webforms only having one form tag. In your case I would even create more forms for each submit button as they seem to do different things. I consider having to check the name of the button in the controller to be a code smell. If they do something like activate/deactivate you should probably post that as a bool or something and have both forms post to the same action.
I think technically this is the best way to go. From a usability point of view you can question if this is the best way to do it. More than 20 items in a list can get quite confusing. But ofcourse, I don't really know what you are programming :)
I agree with Mattias about creating different actions for the activate and deactivate-button. This way you avoid having to use a switch-statement.

ASP .Net MVC, problem with checkboxes!

Basically I have a set of checkboxes that are dynamically created from view data like so:
<input type="checkbox" name="Calendars" value="<%= c.ID %>" /><%= c.Name %>
The value being the Calendar Id.
I can get what checkbox has been brought back using the FormsCollection its messy but it works!
(There also seems to be a bug with the checkbox helper that renders a hidden field next to the checkbox which means true is actually returned as "true,false"! I can work around this so its not an issue just thought Id mention it)
The problem comes when trying to hook the checkboxes up on an edit page!
I have a schedule class which can have multiple calendars and I want to show which calendars a schedule has by checking them on the edit!
My view is strongly typed but MVC magic can't map this!
Any ideas on whats the best way to do this??
I had tried passing the calendar ids in ViewData and do some inline code to check the appropriate checkbox but this is getting messy!
Thanks!!
UPDATE:
Done this
s.ID == c.ID).Select(s => s).Count() > 0) ? "checked=checked" : "" %>
You need to add "checked" tag manually to every check box:
<input type="checkbox" name="Calendars" value="<%= c.ID %>" checked="checked" /><%= c.Name %>
You dont need <input type="checkbox" - use Html.Checkbox(). It renders a hidden field next to the checkbox - but it is not a bug. From ASP.NET MVC source, InputExtensions.cs, line 201:
// Render an additional <input type="hidden".../> for checkboxes. This
// addresses scenarios where unchecked checkboxes are not sent in the request.
// Sending a hidden input makes it possible to know that the checkbox was present
// on the page when the request was submitted.
Use this:
<%= Html.CheckBox("Calendars", c.ID) %>

ASP.NET MVC Updating a list of objects on one form? (model binding to a list)

Quick question regarding updating a list of items in asp.net mvc.
Basically I have an edit action method that returns a collection of objects (incidentally, the table structure of which looks as follows 'testID, assetID, Result' - a link table).
I basically want this items to be displayed one after another in a form and to be able to edit them. The form should post back and the modelbinder do its magic. But, its not that easy.
I have scoured the net and it seems the majority of the information about this stuff seems to be a little out of date. I've come across this post, which has not been updated in a long time, and this one which seems to suggest that you shouldn't bind to a already existing list for updating, and that there are problems when working with EF or Linq to Sql (which I am).
Is there an easy way to achieve what I want? Has the state of list model binding changed in the release version?
UPDATE - A little closer...
Here's my Edit method:
public ActionResult EditSurveyResults(Guid id)
{
var results = surveyRepository.GetSurveyResults(id);
return PartialView("EditSurveyResults", results);
}
And my form:
<div id="editSurveyResults">
<h2>
EditSurveryResults</h2>
<%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>
<% using (Html.BeginForm())
{%>
<fieldset>
<legend>Results</legend>
<% int i = 0; foreach (var result in Model)
{ %>
<input type="hidden" name='results[<%= i %>].TestID' value='<%= result.TestID %>' />
<input type="hidden" name='results[<%= i %>].AssetID' value='<%= result.AssetID %>' />
<p>
<%= result.Task.TaskName%>
</p>
<p>
<label for="Result">
Result:</label>
<input type="text" name='results[<%= i %>].Result' value='<%= result.Result %>' />
<%= Html.ValidationMessage("Result", "*")%>
</p>
<% i++; } %>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
And my Edit POST method:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditSurveyResults(Guid id, IList<SurveyTestResult> results)
{
var oldValues = surveyRepository.GetSurveyResults(id);
if (ModelState.IsValid)
{
UpdateModel(oldValues);
surveyRepository.Save();
return Content("Done");
}
else
return PartialView("EditSurveyResults");
}
It's not complete of course, but it doesn't update anything in its current state. Am I missing a trick here? results is populated with the the updated entities so I'm not sure why its not updating...
UPDATE 2:
So, Im starting to think that the model binder cant do stuff like this. So, I've resorted to doing things in a more hacky way. If anyone can spot a problem with this then please let me know. FYI - this form will be grabbed with AJAX so I dont return a view, rather a simple message.
Here's the new code:
IList<SurveyTestResult> oldValues = surveyRepository.GetSurveyResults(id).ToList();
foreach (var result in SurveyTestResult)
{
//SurveyTestResult is the IList that comes down from the form.
SurveyTestResult thisone = oldValues.Single(p => p.AssetID == result.AssetID &&
p.TestID == result.TestID);
//update the old entity with the result from the new one
thisone.Result = result.Result;
}
And then I call Save on my repository.
Thanks in advance
One thing i noticed is that your not rendering <input type="hidden" name='results.Index' value='<%= i %>' /> as phil Haacks article mentions is mandatory.
Switching to a different Modelbinder might do the trick too. I use the DataAnnotations model binder and with that i dont have to generate .Index fields when binding to List's.

HTML.CheckBox(string) evaluates to two HTML elements instead of one

The code
<%=Html.CheckBox("SendEmail") %>
evaluates to two HTML elements when it's rendered
<input id="SendEmail" name="SendEmail" type="checkbox" value="true" />
<input name="SendEmail" type="hidden" value="false" />
Is this by a bug? Or by design? If it's by design, why?
I was having some trouble this morning with retrieving selected values from a checkbox group in my MVC app. I sent this out to my team and thought I'd share it with everyone else.
When posting back values for checkboxes, the standard behaviour of all browsers is to completely leave out un-checked checkboxes from the post back. So if you have a checkbox that isn’t checked then nothing shows up for this in Request.Form. This is a fairly well-known phenomenon that most developers account for.
In ASP.Net MVC when you use Html.Checkbox, it attempts to get around this and ensure that you have a value posted back (in this case ‘false’) for un-checked checkboxes. This is done by adding a hidden field containing the value ‘false’.
Eg.
<%= Html.CheckBox("Sites", s.Selected, new { value = s.Value })%>
Produces the HTML
<input id="Sites" name="Sites" type="checkbox" value="1" /><input name="Sites" type="hidden" value="false" />
This is all good and well, until you attempt to use checkbox groups. That is more than one checkbox with the same name where the values are sent back in a single comma separated string.
MVC can split this string up for you automatically if you define the value as an array (string[] Sites).
Here’s the view code:
<% foreach(var s in Model) { %>
<li><%= Html.CheckBox("Sites", s.Selected, new { value = s.Value })%>
<label><%= s.Name %></label>
</li>
<% } %>
The appropriate controller action:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int Id, string Name, string SubmissionUrl, string[] Sites)
Unfortunately, because the Html.Checkbox produces this hidden field value as well, the resulting array contains not only values for the selected checkboxes but also ‘false’ for every un-checked checkbox. You get an array that looks something like this:
[0] 'false'
[1] 'false'
[2] '110'
[3] '50'
[4] 'false'
Where 'false' is for checkboxes that are not selected, and integers are the values for the checkboxes that are selected.
This can throw your code out quite a bit if you have only integers for the values of your checkboxes and want to define the result as an array of integers, like so:
public ActionResult Edit(int Id, string Name, string SubmissionUrl, int[] Sites)
Which results in an exception being thrown because it can’t convert the string value ‘false’ to an integer.
The solution is very simple, just avoid Html.Checkbox and manually create the checkboxes in your view code like this:
<% foreach(var s in Model) { %>
<li><input type="checkbox" name="Sites" value="<%=s.Value%>" <% if (s.Selected) { %>checked="checked"<% } %> />
<label><%= s.Name %></label>
</li>
<% } %>
Hope this helps someone else!
When all else fails, read the source code. :) this is from HtmlHelper.cs:
// Render an additional <input type="hidden".../> for checkboxes. This
// addresses scenarios where unchecked checkboxes are not sent in the request.
// Sending a hidden input makes it possible to know that the checkbox was present
// on the page when the request was submitted.
I'm not exactly sure how useful that is, but at least you know the intention.
I think I found something on the web that is directly related to my question.

Resources