Getting data back on Html.ListBoxFor post in MVC - asp.net-mvc

It seems all the examples I can find use a ViewModel for some reason, so a MVC and not MVVM answer is what I'm looking for :)
Controller
List<PermOptions> have = new List<PermOptions>();
List<PermOptions> nothave = new List<PermOptions>();
...populate the lists here...
var set = new PermissionSet
{
ExtId = extid,
HaveList = have,
NotHaveList = nothave
};
return View(set);
View
#model path.to.model.PermissionSet
#{
var NotHave = new MultiSelectList(Model.NotHaveList, "Id", "Role");
}
#Html.ListBoxFor(model => model.NotHaveList, NotHave, new { #size = "30", id = "possible" });
#{
var Have = new MultiSelectList(#Model.HaveList, "Id", "Role");
}
#Html.ListBoxFor(model => model.HaveList, Have, new { #size = "30", id = "have" });
Everything works just fine displaying the initial lists and moving items, but when I submit the form the ListBoxFors are part of to the Post action, PermissionSet.HaveList and PermissionSet.NotHaveList are empty with a zero count. Thinking it was a select issue or format of return issue, I added javascript to select all the items in both boxes, and in the browser debug pane I can see that there are values in the submitted Form data that match up to various option values for NotHave and Have, but if in the Post action, I make a call to ViewData["NotHave"], it is also reporting empty.
What do I need to do to get the list of items in each ListBoxFor in my Post controller, preferrably as part of PermissionSet?

Related

Problems passing a list from ASP.NET MVC controller to a view

I'm experiencing a problem passing a list from a controller to a view. Doing it this way works fine but I don't want to be passing the entire table.
What I want to do is pass just the results of the studies query:
ViewBag.studyList = new SelectList(_context.Studies.OrderBy(p => p.Name), "Id", "Name");
but if I put studies instead of _context.Studies like this:
var studies = (from t in _context.Studies
where !((from s in _context.Studies
join sn in _context.StudyNodes on s.Id equals sn.StudyId
where sn.NodeId == id
select s.Id).ToList()).Contains(t.Id)
select new BundleNodeViewModel
{
StudyId = t.Id,
StudyName = t.Name
}).ToList();
ViewBag.studyList = new SelectList(studies.OrderBy(p => p.StudyName), "Id", "Name");
The code throws a null exception error in the view.
How can this be a problem? I need to pass the filtered results as per the studies query and not the entire list which is the only way it seems to work.
Can someone help please so I can pass studies and not _context.Studies.
Thanks for your help.
So your result from studies is list of BundleNodeViewMode and you want to list the item from there. Then you should tell the selectlist what is the Id and Name you are displaying from.
ViewBag.studyList = new SelectList((from s in studies.OrderBy(p => p.StudyName), select new {Id = s.StudyId, Name = s.StudyName}) , "Id", "Name");

Drop down list lose its value while post back in asp.net Mvc5 in partial view

This is a partial view. while submitting page is refreshed and my drop down value is gone.
#{
var pageName = ViewContext.RouteData.Values["action"].ToString();
ScanPaDataBaseApp.SCANHRConn dbConfig = new ScanPaDataBaseApp.SCANHRConn();
var MySalutList = dbConfig.Codes.ToList();
var SalutData = from Salut in dbConfig.Codes
where Salut.Typ.Trim() == "SALUT"
orderby Salut.SDes
select Salut;
SelectList GetSalutList = new SelectList(SalutData, "Cd", "sDes");
ViewBag.SalutList = GetSalutList;
#Html.DropDownList("Salutation", ViewBag.SalutList as SelectList, "Select Salut", new { Style = "width:236px; color:#858585;" })
Use #Html.DropdownListFor which automatically bind your list to model and you can use it. :)

DropDownList in my edit view mvc

i have List view and in every rows it has the "Actualizar" link action and that one takes me to the edit view in which i have some dropdownLists available for updating my existing data but my big problem is that i want the dropdownlist to first load the data is save. how can i set the dropdownlist to load the data of the model a return and let me choose other options
controller:
public ActionResult ActualizarDispositivo(int id )
{
dropDown();
var equipo= _db.equipo.Include(m=>m.marca).Include(mo=>mo.modelo.Single(b => b.idEquipo==id);
ViewBag.idMarca = _db.marca.ToList().Select(Mar => new SelectListItem
{
Value = Mar.idMarca.ToString(),
Text = Mar.Descripcion.ToString(),
Selected = true
});
return View("ActualizarDispositivo",equipo);
}
in the edit view i have this
#Html.DropDownListFor(m=>m.idMarca,(IEnumerable<SelectListItem>)ViewBag.idMarca)
The code you are using should work, if you simply remove the Selected = true. Currently you are setting all of the DropDownList's values to selected.
I'm not sure which performs better, but I do find it more readable to create a select list using:
ViewBag.idMarca = new SelectList(_db.marca.ToList(), "idMarca", "Descripcion");
And then, there may be no need to cast. (Unsure, I avoid the use of ViewBag)
#Html.DropDownListFor(m=>m.idMarca, ViewBag.idMarca)

get the value of another table in a DropDownList in asp.net-MVC

so I have 3 table(a example):
Dispositivos{idDisp, DispName} that has a relationship with
Configuracion{idConfig, Configname, FK_idDispotivio} which (Configuracion) has a relationship with
Periferico{idPeriferico , name, FK_idConfiguracion}
so what Iam trying to achieve is in my view where I create a Periferico in my DropDownList for my FK_idConfiguracion field I wanna get the Dispositivo.DispName to show in my view to the user (is just a practical example for I want. for you can undestand more easily )
I thought can do this way but can't get an error saying that configuracion dont have DispName, so how can get the DipsName to show that in my DropDownList in my periferico view?
Controller:
ViewBag.Configuracion_IdConfiguracion = new SelectList(db.Configuracion.Include("Dispositivo"), "idConfig", "DispName");
View:
<div class="editor-field">
#Html.DropDownList("Configuracion_IdConfiguracion")
</div>
You could write a new query to do this:
var items = from c in db.Configuracion
select new { Id = c.idConfig, Display = c.Dispositivo.DispName };
Then you could use that to feed your dropdown list:
ViewBag.Configuracion_IdConfiguracion = new SelectList(items, "Id", "Display");

ASP.MVC 1.0 Checkbox values with ViewModel and for specific ID

All,
I've read through a lot of posts about Checkboxes and ASP.MVC but I'm not that much wiser.
My scenario:
I have a strongly typed View where I pass a collection of summary objects to the view for rendering in a for-each. This summary object contains label data based on a unique id. I also add a checkbox to the row so do so via:
<td>
<%= Html.CheckBox("markedItem", Model.MarkedItem, new { TrackedItemId = Model.Id })%>
</td>
When I perform a POST to get the submitted results my action method takes the strongly typed ViewModel back but the original summary object that I used to create the list is not populated.
Ok, this is annoying, but I can understand why so I'll live with it.
What I then do is to add a new property to my ViewModel called "MarkedItem" which is a string collection.
On postback this marked item is filled with the before and after states if the checkbox has changed but nothing to tell me which key they were for. Just to clarify, if I send this
TrackedItemId = A, Value = false
TrackedItemId = B, Value = true
TrackedItemId = C, Value = false
and set the page to this:
TrackedItemId = A, Value = true
TrackedItemId = B, Value = true
TrackedItemId = C, Value = false
I will get back this:
MarkedItem[0] = true
MarkedItem[1] = false
MarkedItem[2] = true
MarkedItem[3] = false
in other words [0] is the new value and [1] is the old value, [2] and [3] represent values that haven't changed.
My questions are:
Is this right - that I get before and after in this way? Is there any way to only send the latest values?
How can I get hold of the custom attribute (TrackedItemId) that I've added so that I can add meaning to the string array that is returned?
So far I like MVC but it not handling simple stuff like this is really confusing. I'm also a javascript noob so I really hope that isn't the answer as I'd like to return the data in my custom viewmodel.
Please make any explanations/advice simple :)
<p>
<label>
Select project members:</label>
<ul>
<% foreach (var user in this.Model.Users)
{ %>
<li>
<%= this.Html.CheckBox("Member" + user.UserId, this.Model.Project.IsUserInMembers(user.UserId)) %><label
for="Member<%= user.UserId %>" class="inline"><%= user.Name%></label></li>
<% } %></ul>
and in the controller:
// update project members
foreach (var key in collection.Keys)
{
if (key.ToString().StartsWith("Member"))
{
int userId = int.Parse(key.ToString().Replace("Member", ""));
if (collection[key.ToString()].Contains("true"))
this.ProjectRepository.AddMemberToProject(id, userId);
else
this.ProjectRepository.DeleteMemberFromProject(id, userId);
}
}
With thanks to Pino :)
ok, one hack I've come up with - I really hate that I have to do this but I don't see another way round it and I'm sure it will break at some point.
I've already implemented by own ModelBinder to get round some other issues (classes as properties for example) so have extended it to incorporate this code. We use Guid's for all our keys.
If there are any alternatives to the below then please let me know.
Html
<%= Html.CheckBox("markedItem" + Model.Id, false)%>
C#
(GuidLength is a const int = 36, Left and Right are our own string extensions)
//Correct checkbox values - pull all the values back from the context that might be from a checkbox. If we can parse a Guid then we assume
//its a checkbox value and attempt to match up the model. This assumes the model will be expecting a dictionary to receive the key and
//boolean value and deals with several sets of checkboxes in the same page
//TODO: Model Validation - I don't think validation will be fired by this. Need to reapply model validation after properties have been set?
Dictionary<string, Dictionary<Guid, bool>> checkBoxItems = new Dictionary<string, Dictionary<Guid, bool>>();
foreach (var item in bindingContext.ValueProvider.Where(k => k.Key.Length > GuidLength))
{
Regex guidRegEx = new Regex(#"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$");
if (guidRegEx.IsMatch(item.Key.Right(GuidLength)))
{
Guid entityKey = new Guid(item.Key.Right(GuidLength));
string modelKey = item.Key.Left(item.Key.Length - GuidLength);
Dictionary<Guid, bool> checkedValues = null;
if (!checkBoxItems.TryGetValue(modelKey, out checkedValues))
{
checkedValues = new Dictionary<Guid, bool>();
checkBoxItems.Add(modelKey, checkedValues);
}
//The assumption is that we will always get 1 or 2 values. 1 means the contents have not changed, 2 means the contents have changed
//and, so far, the first position has always contained the latest value
checkedValues.Add(entityKey, Convert.ToBoolean(((string[])item.Value.RawValue).First()));
}
}
foreach (var item in checkBoxItems)
{
PropertyInfo info = model.GetType().GetProperty(item.Key,
BindingFlags.IgnoreCase |
BindingFlags.Public |
BindingFlags.Instance);
info.SetValue(model, item.Value, null);
}

Resources