i am trying to get the value of selected check-box using model but not able to get as i want ;
Below is the table image
below is my code for this VIEW
And below is the code for result.I get null value
And below is my model declaration
public class RoleDetail
{
[Key]
public int RoleDetailID { get; set; }
public bool IsCreate { get; set; }
public bool IsDelete { get; set; }
public bool IsView { get; set; }
public bool IsEdit { get; set; }
public bool IsDownload { get; set; }
public string ControllerName { get; set; }
public System.DateTime CreateDate { get; set; }
public Int32 UserTypeId { get; set; }
}
public enum ControllerName
{
Account, Candidate, Career, ChooseUs, ContactUs, DocumentType, Employee, Gallery, GalleryType, GetTouch, Home, JobCategory, Jobs, Portfolio, ResumeUpload, RoleDetail, Services, User, UserRoleType
}
Replace the foreach loop in your view with a for:
#for (var i = 0; i < lst.Count; i++)
{
...
#Html.CheckBoxFor(x => lst[i].IsCreate)
#Html.CheckBoxFor(x => lst[i].IsView)
#Html.CheckBoxFor(x => lst[i].IsDelete)
...
}
For this to work make sure that the variable you are iterating over is an IList<T> or T[].
Also your controller action argument should be named accordingly:
public ActionResult Create(IEnumerable<RoleDetail> lst)
{
...
}
You should not be creating RoleDetail in the view. In the GET method create a List<RoleDetail>, populate it with the objects you want to display and return it to the view.
Controller
public ActionResult Create()
{
List<RoleDetail> model = new List<RoleDetail>();
// populate the collection, for example
foreach(var name in Enum.GetNames(typeof(ControllerName)))
{
model.Add(new RoleDetail()
{
ControllerName = name,
IsCreate = true // etc
});
}
return View(model);
}
public ActionResult Create(IEnumerable<RoleDetail> model)
{
}
View
#model List<RoleDetail>
#using(Html.BeginForm())
{
for(int i = 0; i < Model.Count; i++)
{
#Html.HiddenFor(m => m.ControllerName) // needed for postback
#Html.DisplayFor( => m.ControllerName)
#Html.CheckBoxFor(m => m.IsCreate)
....
}
<input type="submit" />
}
Side notes
Do not try to override the name (or value) attribute. The html
helper set these correctly for model binding (and in any case you
were only setting it to the value the helper generated anyway)
The reason the foreach loop does not work is your generating
duplicate name attributes (and also invalid html due to duplcate
id attributes). The for loop correctly generates the correct
names with indexers (e.g. <input name="[0].IsCreate " ..>, <input
name="[1].IsCreate " ..> etc.
You don't appear to be rendering controls for all of you model
properties so use a view model containing only those properties you
need to display/edit. What is a view model in MVC
You have public enum ControllerName so I suspect property
ControllerName in RoleDetail should be public ControllerName ControllerName { get; set; }?
And in future, post the code, not an image of it!
Related
I'm working on ASP.NET MVC web application, and I need to submit List<ProdColor> to Controller using checkboxs. Here is my code
Model
public partial class ProdColor
{
public int ProdColor_ID { get; set; }
public Nullable<int> P_ID { get; set; }
public Nullable<int> Color_ID { get; set; }
public virtual ProdctModelView ProdctModelView { get; set; }
}
public class ProdctModelView
{
public ProdctModelView()
{
this.ProductColors = new HashSet<ProdColor>();
}
public int P_ID { get; set; }
public string P_name { get; set; }
public virtual ICollection<ProdColor> ProductColors { get; set; }
}
Controller
public ActionResult Create()
{
ViewBag.colorlist = db.Colors.OrderBy(m => m.Color_name).ToList();
return View();
}
[HttpPost]
public ActionResult Create(ProdctModelView product, List<ProdColor> ProductColors)
{
Product prod = new Product();
//Save new product
db.Products.Add(prod);
db.SaveChanges();
foreach (var color in ProductColors)
{
color.P_ID = prod.P_ID;
db.ProdColors.Add(color);
}
db.SaveChanges();
return RedirectToAction("Index");
}
View
#model mvc4test.Models.ProdctModelView
#using (Html.BeginForm("Create", "CP_Product", FormMethod.Post))
{
#for (int i = 0; i < ViewBag.colorlist.Count; i++)
{
<input type="checkbox" id="#ViewBag.colorlist[i].Color_name" name="[#i].Color_ID" value="#ViewBag.colorlist[i].Color_id"/>
}
<input type="submit" value="Save" />
}
The problem is when submitting the checkboxes without selecting the first one, the value of List<ProdColor> become Null. So how should I get the correct values at the Controller.
You manually creating checkboxes with indexers. Unchecked checkboxes do not post back a value, so if any of the checkboxes are unchecked, you get non-consecutive indexers so model binding fails.
Your model (view model) needs to include a boolean property (say) public bool IsSelected { get; set; } so that in the view you can use the #Html.CheckBoxFor() method to strongly bind to your model.
#for (int i = 0; i < Model.ColorList.Count; i++)
{
#Html.HiddenFor(m => m.ColorList[i].Color_id)
#Html.CheckBoxFor(m => m.ColorList[i].IsSelected)
#Html.LabelFor(m => m.ColorList[i].IsSelected, Model.ColorList[i].Color_name)
}
The CheckBoxFor() method generates a checkbox with value="true" and an associated hidden input with value="false". If the checkbox is checked, both true and false are posted, but only the first (true) value is bound. If the checkbox is unchecked, the only false is posted.
Then in the POST method, you can get the ID's of the selected items using (say)
var selectedColors = product.ColorList.Where(c => c.IsSelected).Select(c => c.Color_id);
Note that you do not need a parameter in your POST method for List<ProdColor> ProductColors since parameter ProdctModelView product already contains all those values.
I started working with asp.net and I have encountered a problem when I try to edit multiple values from a table. I have a bookmark tables which is connected to another tag table, with an 1 : N relationship. My problem is when I want to edit already existing tags associated with an existing url. I can display them on the page but when I try to post the edited data I don't know how to pick it up in the controller. So far I have managed to send them back as a string but I doubt that is the solution since I have to edit all the data again later. I want to replace the existing values in the Tag table with the edited data. Here are my model and controller code snippets.
Bookmark model:
public int id { get; set; }
public string url { get; set; }
public virtual ICollection<Tag> tags { get; set; }
Tag model:
public int id { get; set; }
public string name { get; set; }
public virtual Bookmark bookmark { get; set; }
public string user { get; set; }
Controller:
public ActionResult Edit(int id)
{
var editBookmark = adc.Bookmarks.Single(x => x.id == id);
var query_where2 = from a in adc.Tags
where a.bookmark.id == id
select a;
BookmarkTag bkTag = new BookmarkTag();
bkTag.bookmark = new List<Bookmark>();
bkTag.bookmark.Add(editBookmark);
bkTag.tag = query_where2.ToList();
return View(bkTag.tag);
}
//
// POST: /SavedBookmark/Edit/5
[HttpPost]
public ActionResult Edit(int id, ICollection<FormCollection> tag)
{
try
{
return View();
}
catch
{
return View();
}
Html code:
#using (Html.BeginForm("edit", "SavedBookmark"))
{
#Html.AntiForgeryToken()
if (Model != null) {
var aa= Model.First();
#Html.TextBox("test2", aa.bookmark.url);
List<BookIT2.Models.Tag> allTags = new List<BookIT2.Models.Tag>();
allTags = Model.ToList();
for (int i = 0; i < allTags.Count; i++)
{
if (!allTags[i].name.IsEmpty())
{
#Html.TextBox(allTags[i].name, allTags[i].name);
#Html.Hidden(allTags[i].id.ToString(), allTags[i].id);
#Html.Hidden(allTags[i].user, allTags[i].user)
#Html.Hidden(allTags[i].bookmark.id.ToString(), allTags[i].bookmark.id.ToString())
}
}
#Html.Label("Additional tag")
#Html.TextBox("additionalTag")
<input type="submit" value="edit" />
}
In short: I can't get any values in the http post ICollection, it's always null.
Here is the updated code:
#using (Html.BeginForm("edit", "SavedBookmark"))
{
#Html.AntiForgeryToken()
if (Model != null)
{
for (int i = 0; i < Model.tag.Count; i++)
{
if (!Model.tag[i].name.IsEmpty()) {
#Html.Hidden(Model.tag[i].id.ToString(), Model.tag[i].id);
#Html.Label("name");
#Html.TextBox(Model.tag[i].name, Model.tag[i].name);
#Html.Hidden(Model.tag[i].bookmark.id.ToString(), Model.tag[i].bookmark.id);
#Html.Hidden(Model.tag[i].user, Model.tag[i].user);
}
}
#Html.TextBox(Model.bookmark.id.ToString(), Model.bookmark.url);
<input type="submit" value="edit" />
}
}
Model class:
public class TestBookmark
{
public Bookmark bookmark{get; set;}
public List<Tag> tag {get; set;}
}
[HttpPost]
public ActionResult Edit(TestBookmark edit)
{}
Don't really understand why you're doing it this way. I would like to suggest you totally different approach.
First:
Create a class with all the fields you want in your view.
Second:
Use this class as the MODEL in your View
Third:
In the controller, in the POST function user your class as the only one parameter of that function.
I have here a scenario. I want to make an HTTP POST action in the form so here's how I did it.
public class Item
{
public Item()
{
Storages = new HashSet<Storage>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Storage> Storages { get; set; }
-- remove some lines for brevity --
}
public class Storage
{
public int Id { get; set; }
public string Name { get; set; }
--- remove some lines for brevity --
}
So basically, An Item has many Storage And so I created viewmodel.
public class CreateStockViewModel
{
public string Name { get; set; }
public int StorageId { get; set; }
-- remove some lines for brevity --
}
In my Controller. I have this
[HttpGet]
public ActionResult Create()
{
ViewBag.Storages = _storageService.All
.OrderBy(i => i.Name)
.ToSelectList(s => s.Name, s => s.Id);
return View();
}
In my View:
#model Wsfis.Web.ViewModels.ItemViewModels.CreateStockViewModel
#Html.DropDownList("Storages")
Now my problem is, when I submit the form. And have Quick Watch to the model being passed. It is Null or 0
public ActionResult Create(CreateStockViewModel item)
{
// some code
}
In a nutshell,
When I submit the form all fields are being bind except for the #Html.DropDownList. Where did I missed?
Some additional side note:
They say Views should be strongly typed. Then what should I pass in View then? (A sample code would be great. Thanks)
As for the ToSelectList method I copy this code (I hope it's alright)
Any help would be much appreciated. Thanks.
Your form input has a different name to your property so the default model binder doesn't know how to bind your model.
You could pass in a different name to use to the DropDownList helper, however I prefer to use the strongly typed helpers:
#Html.DropDownListFor(m => m.StorageId, ViewBag.Storages as IEnumerable<SelectListItem>)
Try like this:
ViewBag.StorageId = _storageService.All
.OrderBy(i => i.Name)
.ToSelectList(s => s.Name, s => s.Id);
in view:
#Html.DropDownList("StorageId")
it will now post the drop down list selected value in CreateStockViewModel object's StorageId property.
Can't get all my ViewModel properties back after the postback (After user entered some values on HttpPost)
There are numerous questions here related to losing data or getting nulls after the postback
I tried some of them and played around on my case, I think the scenario is a bit different,
Using a PartialView or Editor Templates(except a list property), Always the returned result properties are null.
In partialView approach always all the properties are null, I think maybe I missed a piece.
In the "custom editor template approach for the type", I'll have just "EnteredNums" List returned. (Maybe because these are what the template have EditorFor for them, but what is the solution here if that's the case?)
Don't know weather if it's important here or not, the application also uses Unity. I don't think it be the problem here.
The HttpGet Passed model is the same as HttpPost : DataVm
The name of the action is also the same : ProcessEnteredData
=================== Controller and action
[HttpPost]
public ActionResult ProcessEnteredData(DataVm vm)
{
if (ModelState.IsValid)
{
foreach (NumType num in vm.EnteredNums)
{
int i1 = num.Score1;
int i2 = num.Score2;
string profTitle = vm.Profile.Title;
Repository.Context.EnteredNums.Add(num);
}
return RedirectToAction("ShowTable");
}
else
{
return View(vm);
}
}
==============
The Partial View of Custom Editor Template are similar :
#model xxxx.NumType
#Html.LabelFor(m => m.TheTitle)
#Html.TextBoxFor(m => m.Score1)
#Html.TextBoxFor(m => m.Score2)
#Html.HiddenFor(m => m.Profile)
// Profile or ProfileId - Just used to see could it bring the property back or not as a test
============
NumType Model
[Key]
public int NumTypeId { get; set; }
[ForeignKey("Profile")]
[Required]
public int ProfileId { get; set; }
public int Score1 { get; set; }
public int Score2 { get; set; }
public int BoxId { get; set; }
public Box Box { get; set; } // something not important here
public virtual Profile Profile { get; set; }
============
The ViewModel
public class DataVm
{
public Profile Profile { get; set; }
public string TheTitle { get; set; }
public List<NumType> EnteredNums { get; set; }
// In the Editor template approach it's the only item with data and others are null
public List<Box> Boxes { get; set; }
}
=========
View for PartialView approach :
#model xxxx.DataVm
#using (Html.BeginForm("ProcessEnteredData", "Profile", FormMethod.Post))
{
#Html.AntiForgeryToken()
Model.EnteredNums = new List<NumType>();
foreach(var box in Model.Boxes)
{
NumType num = new NumType();
num.Profile = Model.Profile;
num.Box = box;
int iCount = Model.EnteredNums.Count;
Model.EnteredNums.Add(num);
#Html.Partial("NumView", Model.EnteredNums[iCount]);
}
<input type="submit" value="Do Process" />
}
===================
View for Editor for approach :
// instead of #Html.Partial :
#Html.EditorFor(m => m.EnteredNums[iCount]);
I'm having an issue with properties being mapped from my View Model, to a nested View Model. My structure (slimmed down):
ViewModels:
public class PolicyViewModel
{
public int PolicyId { get; set; }
public NoteViewModel NoteVM { get; set; }
}
public class NoteViewModel
{
public int PolicyId { get; set; }
}
Policy Controller:
public ActionResult Adjustment(int policyId = 0, int historyId = 0)
{
GroupPolicyViewModel groupPolicyVM = new GroupPolicyViewModel();
// Automap all property values, then assign the policy Id to the nested controller?!
groupPolicyVM.NoteVM = new NoteViewModel { PolicyId = policyId };
return View(groupPolicyVM);
}
Note Controller
public int PolicyId { get; set; } // null
public JsonResult Get(int take, int skip, FilterExpression filter, NoteViewModel NoteVM)
{
// How do I get the PolicyId here?! NoteVM PolicyId is null
// This function is being called via jQuery from the Policy form and I obviously don't want to send the policyId via QueryString.
}
View
And, of course, in my View I have:
#Html.Partial("_Notes", Model.NoteVM)
#Html.HiddenFor(model => model.PolicyId)
#Html.HiddenFor(model => model.NoteVM.PolicyId) // also tried this with no success!
I guess this should be a pretty popular thing to do, but I can't figure out what I'm doing wrong. Any ideas? I'm doing it this way as I'll need the Note partial view for multiple pages.