Checkbox filter problem when null - asp.net-mvc

I have an array of checkboxes, and trying to filter them, but when no checkbox is checked, it throws an System.ArgumentNullException
public ActionResult UserEdit(string[] UsergroupIDs)
{
IEnumerable<Usergroup> userUsergroups =
UsergroupIDs.Where(x => x != "false")
.Select(x => (Usergroup)_ug.GetUsergroups(int.Parse(x)).FirstOrDefault());
How should I modify this one?
/M

Set the value to an empty list initially, then change it to the results of your query if the paremeters isn't null. Or, you could modify your view to include hidden fields for each checkbox that has the default (false) property so that parameter is never null. The latter is what the Checkbox helper method does so using it would also solve your problem. Even better, do both.
public ActionResult UserEdit(string[] UsergroupIDs)
{
IEnumerable<Usergroup> userUsergroups = new List<UserGroup>();
if (UsergroupIDs != null)
{
userUsergroups = UsergroupIDs.Where(x => x != "false")
.Select(x => (Usergroup)_ug.GetUsergroups(int.Parse(x)).FirstOrDefault());
}
...
}

Related

Setting a preselected item for html.dropdownlistfor

I have a a html.dropdownlistfor which list around 900 items
Html.DropDownListFor(m => m.ParentWebContentID, null, "Choose...", htmlAttributes: new { #class = "form-control" })
I want it to have a preselected item and thought the 3rd parameter ("Choose...") was for this.
So I arranged for a ViewBag variable to hold a value (ChosenParentWebContentId)
like this
public ActionResult Create(int? id)
{
if (!AccountController.IsInRole(System.Web.HttpContext.Current.User.Identity.Name, "admin"))
{
return RedirectToAction("Index");
}
ViewBag.ParentWebContentID = GetWebContentListwithGroup(null);
if(id != null)
{
ViewBag.ChosenParentWebContentID = db.WebContent.FirstOrDefault(x => x.WebContentID == id).ParentWebContentID;
}
ViewBag.WebContentTypeID = db.WebContentType.ToList();
ViewBag.ContentTypeID = id;
ViewBag.LanguageCode = new SelectList(db.WebLanguage, "LanguageCode", "DisplayName");
ViewBag.CreatedByUserID = new SelectList(db.AspNetUsers, "Id", "Email");
ViewBag.LastEditedByUserID = new SelectList(db.AspNetUsers, "Id", "Email");
ViewBag.DetailList = db.WebContentDetail.Where(x => x.WebContentID == id).ToList();
return View();
}
I tried changing "choose..." with the ViewBag variable but it didn't work. Is there any other way to do this?
I couldn't find any help on other examples around internet.
When you use Html.DropDownListFor (or any of the *For family of helpers), the value comes from the value of the bound property. Actually, it's a little more complex than that. The value comes from the value of the bound property in ModelState.
So, if you want an item to be automatically selected, then you need to set ParentWebContentID to the value you want selected. Plain and simple. However, once a post is made, the select value will always be what was posted, even if you set ParentWebContentID to a different value. Also worth bearing in mind: Request, ViewBag and ViewData all participate in defining the values in ModelState. As a result, if for example you had an action that had a param named parentWebContentID (case-insensitive), that value from the request would always take precedence over any value you set on the model explicitly.

Using TryUpdateModel to save an object on Edit Post with FormCollection

I'm not sure I understand the best way of doing this.
If I have a model with a large number of fields, then do I have to explicitelly list every one of them in a whitelist under TryUpdateModel, or can I just pass the ForCollection.
The following code doesn't save my edits, is my only alternative to list all my fields one by one?
public ActionResult Edit(int id, FormCollection form)
{
var jobToUpdate = db.Jobs
.Include(x => x.JobNotes)
.Where(x => x.JobID == id)
.SingleOrDefault();
if (TryUpdateModel(jobToUpdate, form))
{
db.Entry(jobToUpdate).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Details", new { id = model.Job.JobID });
}
return RedirectToAction("Details", new { id = model.Job.JobID })
}
Secondly, what is the best way to get a list of just the fields that have changed. If the only field that the user changes is the FirstName field, I'd like to record that in an audit log.
Thanks for your help!
If there are fields on your model that aren't in the form and you don't want users to change then you can use an exclude list. The choice to use an include or exclude list will depend which is largest. An include list is more secure as if you forget to include something it can't be changed. Not using an include, or exclude list will leave you vulnerable to model stuffing where users can post extra values to change details they shouldn't be able to.
public ActionResult Edit(int id, FormCollection form)
{
var jobToUpdate = db.Jobs
.Include(x => x.JobNotes)
.Where(x => x.JobID == id)
.SingleOrDefault();
if (TryUpdateModel(jobToUpdate, String.Empty, null, new [] {"SecretField"}, form))
{
db.SaveChanges();
return RedirectToAction("Details", new { id = model.Job.JobID });
}
// Model not saved - send them back to edit page for corrections
return View(jobToUpdate);
}
If the model is not saved you should not redirect. Show them the same page and make sure your edit view shows model errors.
The most likely reason your code is not saving the model is you're trying to insert a value that is not valid.

How to remove model state error for dropdown with selected option label in mvc?

I am working on a MVC project.I have a view having a dropdownlist with an option label "Select Task".Now the integer property bound with this dropdown is not a required field.
But then too after I try to save, I get the dropdown having a red border showing that it is required. When I analysed, I found that the option label has value null.
Using firebug when I entered 0 for the value of option label, the view was saved with no model state error. Am I doing something wrong ? How to avoid it ?
View
#Html.DropDownListFor(model => model.projecttaskid, new SelectList((IList<SelectListItem>)ViewData["MyTasks"], "Value", "Text"),"Select Task", new { #class = "span2" })
Model public int projecttaskid { get; set; } Controller It doesn't reach the controller action.
projecttaskid is not nullable. Unless you provide a default value for the drop down list, the model will not bind properly, which is why you are getting validation error even though the model field is not marked as [required].
Edit: by default value I mean an item in the list with a value of 0, since the default value for projecttaskid is 0.
For instant, you use an overload of DropDownListFor with the optionLabel argument (your "Select Task" argument.
If no item is selected, this will be taken as the "selected option", and return a null value for model.projecttaskid.
The easiest way would be to add an element with a 0 value when you create your list (ViewData["MyTasks"])
With, for example :
Value = 0;
Text = "Select Task;
And use an overload of DropDownListFor without the optionLabel.
[By the way, usage of ViewModels instead of ViewData would be a good thing, but that's another problem]
*EDIT *
We do use some extension methods to manage these cases :
public static IEnumerable<SelectListItem> ToSelectListItem<T, TValue, TText>(
this IEnumerable<T> enumerable,
Func<T, TText> text,
Func<T, TValue> value)
{
return enumerable.Select(item => new SelectListItem
{
Text = text(item).ToString(),
Value = value(item).ToString()
}).AsEnumerable();
}
public static IEnumerable<SelectListItem> WithDefaultZeroValue(this IEnumerable<SelectListItem> selectListItems, string chooseText/* = ChooseText*/)
{
IList<SelectListItem> items = selectListItems.ToList();
items.Insert(0, new SelectListItem { Value = "0", Text = chooseText });
return items.AsEnumerable();
}
usage
var myList = mySourceForDropDown.ToSelectListItem(m => m.TextField, m => m.ValueField)
.WithDefaultZeroValue("SelectTask")
use this:
#Html.DropDownListFor(model => model.Type, new SelectList(Enum.GetNames(typeof(Enums.TenderType))), new Dictionary<string, object>() { { "data-val", "false" } })

accessing viewbag in the view

net MVC. I have assigned a list of objects to the viewbag property can anyone please tell me as to how i can get the list in the view to use it in the drop down list? here is my controller code & view code
Controller:
public ActionResult GetSection(int sectionId,int contactId)
{
ContactDetailSectionModel contactDetailSection = new ContactDetailSectionModel { SectionId = sectionId,ContactId=contactId };
contactDetailSection.FetchAllSubsections();
ContactDetailSectionModel customSections = new ContactDetailSectionModel();
customSections.FetchCustomSubSections();
if(customSections != null && customSections.ContactDetailSubSections != null)
{
ViewBag.CustomSubSections = customSections.ContactDetailSubSections;
}
return PartialView("~/Views/Contacts/Details/EditSection.cshtml", contactDetailSection);
}
View Code:
#Html.DropDownListFor(m => m.ContactDetailSubSections[1], new SelectList(ViewBag.CustomSubSections , "Name", "Name",Model.ContactDetailSubSections[1].Name))
#Html.TextAreaFor(m => m.ContactDetailSubSections[1].Text)
I think the first parameter in your #Html.DropDownlist should be string or some scalar quantity it cannot be a collection.

At edit in webgrid in mvc3 why ModelState.IsValid is false as condition is true?

[HttpPost]
public ActionResult Index(SecurityMappingModel objModel)
{
//edit code
if (objModel.Id != Guid.Empty)
{
if (ModelState.IsValid)
{
mappings = (List<SecurityMappingModel>)Session["Mappings"];
var objRemove = mappings.FirstOrDefault(m => m.Id == objModel.Id);
if (objRemove != null)
{
mappings.Remove(objRemove);
mappings.Add(objModel);
ViewBag.Mappings = mappings;
}
Session["Mappings"] = mappings;
return RedirectToAction("Index");
}
inside objModel one of the field is having value 0 as it is a textfield i'm putting value into it but inside Controller oject objModel showing that field value is zero :( :( why???
Apparently one of your model values is not valid. You should be able to find out which one by looking at the items in ModelState.Values. Each item has an Errors property.
The result of this line should contain at least one item:
var errors = ModelState.Values.Where(value=>value.Errors.Any());

Resources