Drop down list isn't working - c#

Controller:
OnePersonAllInfoViewModel vModel = new OnePersonAllInfoViewModel();
vModel.PreferredContactType = new PreferredContactType();
ViewBag.PrefContactTypes = new SelectList(dbEntities.PreferredContactTypes
.OrderBy(pct => pct.PreferredContactTypeID),
"PreferredContactTypeID", "PreferredContactType1",
vModel.PreferredContactType.PreferredContactTypeID);
View:
<div class="editor-label">
#Html.LabelFor(model => model.PreferredContactType.PreferredContactTypex)
</div>
#Html.DropDownListFor(model => model.PreferredContactType.PreferredContactTypeID,
ViewBag.PrefContactTypes as SelectList)
And I get this error on post back... There is no ViewData item of type 'IEnumerable' that has the key 'PreferredContactType.PreferredContactTypeID'
Any thoughts? Thanks!

In your HttpPost controller action you must repopulate the ViewBag.PrefContactTypes property the same way you did in your GET action if you redisplay the same view:
[HttpPost]
public ActionResult Process(OnePersonAllInfoViewModel model)
{
ViewBag.PrefContactTypes = ...
return View(model);
}
Also you seem to have defined some class that is suffixed with ViewModel. This leaves the reader to believe that you are using view models in your application and in the very next line you use ViewBag. Why? Why not take full advantage of the view model and its strong typing?
Just like this:
public class OnePersonAllInfoViewModel
{
public int PreferredContactTypeID { get; set; }
public IEnumerable<PreferredContactType> PrefContactTypes { get; set; }
}
and then in your GET action:
public ActionResult Index()
{
var model = new OnePersonAllInfoViewModel();
model.PrefContactTypes = dbEntities
.PreferredContactTypes
.OrderBy(pct => pct.PreferredContactTypeID)
.ToList();
return View(model);
}
then the view:
#Html.DropDownListFor(
model => model.PreferredContactTypeID,
Model.PrefContactTypes
)
and the POST action:
[HttpPost]
public ActionResult Index(OnePersonAllInfoViewModel model)
{
if (!ModelState.IsValid)
{
// the model is invalid => we must redisplay the same view =>
// ensure that the PrefContactTypes property is populated
model.PrefContactTypes = dbEntities
.PreferredContactTypes
.OrderBy(pct => pct.PreferredContactTypeID)
.ToList();
return View(model);
}
// the model is valid => use the model.PreferredContactTypeID to do some
// processing and redirect
...
// Obviously if you need to stay on the same view then you must ensure that
// you have populated the PrefContactTypes property of your view model because
// the view requires it in order to successfully render the dropdown list.
// In this case you could simply move the code that populates this property
// outside of the if statement that tests the validity of the model
return RedirectToAction("Success");
}

Related

How can i Send my list From my controller to my DropDownList in the View?

i know it should look like this
#Html.DropDownList("yourDropName", listItems, new { #class = "form-control" })
but i can't figure it out how should i do it
in my controller i passed a list to it which was initialized in my model layer and in my View_Model i simply get it from model and pass it to my controller
this is in my model
public List<int?> TeamId()
{
ListTeam = new List<int?>();
using (var context = new EF_Model.DigikalaHREntities())
{
//var p = context.Members.Any(c => c.TeamId);
var p = from c in context.Members
where c.TeamId.HasValue
select new { c.TeamId };
return p.Select(m => m.TeamId).ToList();
}
}
i have 2 Classes in my view model first one is just entities with some Data Annotation and second one is the class which i get my methods from my Model
so this is my View model layer(i didn't passed this one to my View)
public List<int?> GetTeamId()
{
Ref_CRUD = new Models.CRUD.Member();
return Ref_CRUD.TeamId();
}
my controller
#region [- Get -]
public ActionResult Create()
{
Ref_Member = new View_Model.Buisiness.Member();
return View(Ref_Member.GetTeamId());
}
this is my View
#model DigikalaHR.View_Model.Entitys.Member
.
.
.
.
<div class="form-group">
#Html.LabelFor(model => model.TeamId, "TeamId", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
//don't know how to use one of These two lines and which one i should use
#*#Html.DropDownList("TeamId",new SelectList(enum.(typeof())),htmlAttributes: new {#class="form-control" })*#
#*#Html.DropDownListFor(m => m.TeamId,new SelectList(Enum.GetValues(typeof(id))),"GetTeamId")*#
#Html.ValidationMessageFor(model => model.TeamId, "", new { #class = "text-danger" })
</div>
</div>
How can i Send my list From my controller to my DropDownList in the View?
I think you are mixing things up here. Your view models should be models specific to the view and those are simply dumb POCO classes for data tranfer. No business logic or those has no idea about what your data access technology / entity classes are. Do not mix view models with entity classes.
So in your case, if your view is to create a member, you should have a view model with properties which are absolutely needed in the view (for input elements)
public class CreateMemberVm
{
public string FirstName { set;get;}
public int? SelectedTeamId { set;get;}
public List<SelectListItem> Teams { set;get;}
// Add other properties as needed by the view.
}
Add other properties to your view model as needed by the view. There is no reason to blindly add all the properties from your entity class to your view models.
Now in your GET action, you initialize an object of this view model, popualte the Teams property with a list of SelectListItem objects (we will use this in the view to build the SELECT element options) and send the object to the vieww
public ActionResult Create()
{
var vm = new CreateMemeberVm();
vm.Teams = GetTeamItems();
return View(vm);
}
public List<SelectListItem> GetTeamItems()
{
using (var db = new EF_Model.DigikalaHREntities())
{
return db.Teams
.Select(a=>new SelectListItem {
Value=a.TeamId.ToString(),
Text=a.TeamName
})
.ToList();
}
}
Now in your view, which should be strongly typed to our view model, you can use the DropDownListFor helper method to render the SELECT element.
#model CreateMemberVm
#using(Html.BeginForm())
{
#Html.LabelFor(a=>a.FirstName)
#Html.TextBoxFor(a=>a.FirstName)
#Html.LabelFor(a=>a.SelectedTeamId)
#Html.DropDownListFor(m => m.SelectedTeamId, Model.Teams, "Select team")
<input type="submit" />
}
You can use the same view model class as the parameter of your HttpPost action method and now when user submits the form after filling the form, the SelectedTeamId property and the FirstName property will be populated from the form data and you can use those to save to your table
[HttpPost]
public ActionResult Create(CreateMemeberVm model)
{
// check model.FirstName and model.SelectedId
// to do : Save as needed
// to do : return something
}
If you want to preselect an item in your view (for the case of edit member use case), all you have to do is, set the SelectedTeamId property of your view model to whatever you have in your db
public ActionResult Edit(int id)
{
var m = db.Members.Find(id);
var vm = new CreateMemeberVm() { FirstName = m.FirstName, SelectedTeamId=m.TeamId};
vm.Teams = GetTeamItems();
return View(vm);
}

TextBoxFor default value and keep edited value after validation fail

Razor code like:
#Html.TextBoxFor(Model => Model.Name, new { #Value = student.t_Name })
and I using .NET MVC's model validation in Controller,
if (ModelState.IsValid)
{
return RedirectToAction("B");
}
else
{
return View(); // when validation failed
}
My situation is I have a edit function, for example:
original data:
birthday: 1992-05-26
after edited:
birthday: 1992-05-32
after I submit this to Controller and make model validation, it will validate fail, and return to previous view(the view before form submit),
I want it shows
birthday:1992-05-32
instead of
birthday:1992-05-26
You should set ViewModel values that come to your controller like this:
public ActionResult YourControllerMethod(YourViewModel model)
{
if (ModelState.IsValid)
{
return RedirectToAction("B");
}
else
{
ViewData.Model = model; //where model is your controller model
return View(); // when validation failed
}
}
You would need to pass the current posted model instance back to view when returning back View something like:
public ActionResult YourAction(SomeModel model)
{
if (ModelState.IsValid)
{
return RedirectToAction("B");
}
else
{
return View(model);
}
}

I Can't get a DropDownList to populate from table. EF and MVC4

I believe this will create a list in my HomeController. But not sure what calls it or where it goes in the Controller beside maybe the first Add ActionResult (GET method).
public static IEnumerable<SelectListItem> items()
{
using (oesacEntities_compact db = new oesacEntities_compact())
{
var query = from s in db.tblSponsors select new { s.SponsorID, s.BizName };
return query.AsEnumerable()
.Select(x => new SelectListItem
{
Value=x.SponsorID.ToString(),
Text = x.BizName
}).ToList();
}
}
I can't seem to send it to the Add view or to reference it from the Add view:
<div class="editor=field">
#Html.DropDownListFor(model => model.SponsorID,IEnumerable<SelectListItem> SelectList);
</div>
It seems so simple in other coding languages. I want to populate a pulldown with about 200 sponsor ID's for value, BizNames for text. For now at least. God help me after that when I want to show an Edit view with the value selected.
thankyou stackoverflow
You need to pass the SelectList to your view. Ideally your view model should include a property for the SelectList but you can (yuk) use ViewBag, for example
View Model
public class MyViewModel
{
public int SponsorID { get; set; }
// other properties
public SelectList SponsorList { get; set; }
}
Controller
public ActionResult SomeThing()
{
MyViewModel model = new MyViewModel();
// assign the select list
var sponsors = from s in db.tblSponsors;
model.SponsorList = new SelecList(sponsors, "SponsorID", "BizName");
return View(model);
}
View
#Html.DropDownListFor(model => model.SponsorID, Model.SponsorList);
or if you assigned the select list to ViewBag
#Html.DropDownListFor(model => model.SponsorID, (SelectList)ViewBag.SponsorList);

How do I keep the clicked state of a checkbox in asp.net

I'm really having problems with keeping the state of my checkbox in my mvc4 application. I'm trying to send its value down to my controller logic, and refresh a list in my model based on the given value, before I send the model back up to the view with the new values. Given that my checkbox is a "show disabled elements in list" type function, I need it to be able to switch on and off. I've seen so many different solutions to this, but I can't seem to get them to work :(
Here's a part of my view:
#model MyProject.Models.HomeViewModel
<div class="row-fluid">
<div class="span12">
<div class="k-block">
<form action="~/Home/Index" name="refreshForm" method="POST">
<p>Include disabled units: #Html.CheckBoxFor(m => m.Refresh)</p>
<input type="submit" class="k-button" value="Refresh" />
#* KendoUI Grid code *#
</div>
</div>
HomeViewModel:
public class HomeViewModel
{
public List<UnitService.UnitType> UnitTypes { get; set; }
public bool Refresh { get; set; }
}
The HomeViewController will need some refactoring, but that will be a new task
[HttpPost]
public ActionResult Index(FormCollection formCollection, HomeViewModel model)
{
bool showDisabled = model.Refresh;
FilteredList = new List<UnitType>();
Model = new HomeViewModel();
var client = new UnitServiceClient();
var listOfUnitsFromService = client.GetListOfUnits(showDisabled);
if (!showDisabled)
{
FilteredList = listOfUnitsFromService.Where(unit => !unit.Disabled).ToList();
Model.UnitTypes = FilteredList;
return View(Model);
}
FilteredList = listOfUnitsFromService.ToList();
Model.UnitTypes = FilteredList;
return View(Model);
}
You return your Model to your view, so your Model properties will be populated, but your checkbox value is not part of your model! The solution is to do away with the FormCollection entirely and add the checkbox to your view model:
public class HomeViewModel
{
... // HomeViewModel's current properties go here
public bool Refresh { get; set; }
}
In your view:
#Html.CheckBoxFor(m => m.Refresh)
In your controller:
[HttpPost]
public ActionResult Index(HomeViewModel model)
{
/* Some logic here about model.Refresh */
return View(model);
}
As an aside, I can't see any reason why you'd want to add this value to the session as you do now (unless there's something that isn't evident in the code you've posted.

Do I need a custom modelbinder for my Create Action?

I have been doing a bit of research on this but, I am having a little trouble understanding when modelbinding is needed in MVC 3. I have created a ViewModel to supply data to my Create view.
public class InvitationRequestViewModel
{
public InvitationRequest InvitationRequest { get; private set; }
public IEnumerable<SelectListItem> EventsList { get; private set; }
public string EventId { get; set; }
public InvitationRequestViewModel(InvitationRequest request)
{
InvitationRequest = request;
EventsList = new SelectList(MyRepositoryAndFactory.Instance.FindAllEvents()
.Select(events => new SelectListItem
{
Value = events.ID.ToString(),
Text = String.Format("{0} - {1} - {2}", events.Name, events.Location, events.StartDate.ToShortDateString())
}
), "Value", "Text");
}
}
My InvitationRequest controller has the following Action methods
public ActionResult Create()
{
InvitationRequest request = new InvitationRequest(User.Identity.Name);
return View(new InvitationRequestViewModel(request));
}
[HttpPost]
public ActionResult Create(InvitationRequestViewModel newInvitationRequest)
{
try
{
if (!ModelState.IsValid) return View(newInvitationRequest);
newInvitationRequest.InvitationRequest.Save();
MyRepositoryAndFactory.Instance.CommitTransaction();
return RedirectToAction("Index");
}
catch
{
ModelState.AddModelError("","Invitation Request could not be created");
}
return View(newInvitationRequest);
}
I can reach the Create view with no problems and the DDL is populated with a list of available events. My problem is that I was expecting the InvitationRequestViewModel to be mapped to the HttpPost Create method. Instead, I just get an error saying "The website cannot display the page".
When I use the signature:
public ActionResult Create(FormCollection collection){ }
then I can see the posted values. I had hoped not to have to do my own mapping code in the controller.
Is a custom ModelBinder the answer?
EDIT
I am using a strongly typed View of type InvitationRequestViewModel and this is the DDL code
<div class="editor-label">
#Html.LabelFor(model => model.InvitationRequest.Event)
</div>
<div class="editor-field">
#Html.DropDownListFor(x => x.EventId, Model.EventsList)
</div>
You have to specify a parameterless constructor for the InvitationRequestViewModel so the default model binder can instantiate it.

Categories