Get the selected value of a DropDownList. Asp.NET MVC - c#

I'm trying to populate a DropDownList and to get the selected value when I submit the form:
Here is my model :
public class Book
{
public Book()
{
this.Clients = new List<Client>();
}
public int Id { get; set; }
public string JId { get; set; }
public string Name { get; set; }
public string CompanyId { get; set; }
public virtual Company Company { get; set; }
public virtual ICollection<Client> Clients { get; set; }
}
My Controllers :
[Authorize]
public ActionResult Action()
{
var books = GetBooks();
ViewBag.Books = new SelectList(books);
return View();
}
[Authorize]
[HttpPost]
public ActionResult Action(Book book)
{
if (ValidateFields()
{
var data = GetDatasAboutBookSelected(book);
ViewBag.Data = data;
return View();
}
return View();
}
My Form :
#using (Html.BeginForm("Journaux","Company"))
{
<table>
<tr>
<td>
#Html.DropDownList("book", (SelectList)ViewBag.Books)
</td>
</tr>
<tr>
<td>
<input type="submit" value="Search">
</td>
</tr>
</table>
}
When I click, the parameter 'book' in the Action is always null.
What am I doing wrong?

In HTML a dropdown box sends only simple scalar values. In your case that would be the id of the selected book:
#Html.DropDownList("selectedBookId", (SelectList)ViewBag.Books)
and then adapt your controller action so that you will retrieve the book from the id that gets passed to your controller action:
[Authorize]
[HttpPost]
public ActionResult Action(string selectedBookId)
{
if (ValidateFields()
{
Book book = FetchYourBookFromTheId(selectedBookId);
var data = GetDatasAboutBookSelected(book);
ViewBag.Data = data;
return View();
}
return View();
}

You can use DropDownListFor as below, It so simpler
#Html.DropDownListFor(m => m.Id, new SelectList(Model.Books,"Id","Name","1"))
(You need a strongly typed view for this -- View bag is not suitable for large lists)
public ActionResult Action(Book model)
{
if (ValidateFields()
{
var Id = model.Id;
...
I think this is simpler to use.

Related

How Post the list of items from PartialView to controller?

This is quite simple situation actually, but I can't get how to make this work. So, there is list of checkboxes rendered in PartialView. Data passed from parent ViewModel to child ViewModel in PartialView. All these wrapped by form, unfortunately I can't get the data from PartialView.
Parent ViewModel:
public class UserProgramsViewModel
{
public int Id { get; set; }
[Required(ErrorMessage = "Введите название")]
[DisplayName("Название")]
public string ProgramName { get; set; }
[DisplayName("Пользователь")]
public string UserName { get; set; }
[DisplayName("Пользователь")]
public int UserId { get; set; }
[DisplayName("Дни Программы")]
public ICollection<ProgramDaysDTO> ProgramDays { get; set; }
public IEnumerable<DaysViewModel> Days { get; set;} //Passed to Partial
}
Child ViewModel:
public class DaysViewModel
{
public int Id { get; set; }
public string DayName { get; set; }
}
Parent View:
#Html.Partial("Days", Model.Days)
PartialView (here we are using attribute name 'Days' to bind it to Parent model)
#model IEnumerable<BBN.Admin.ViewModels.DaysViewModel>
<ul class="list-group col-lg-2">
#foreach (var item in Model)
{
<li class="list-group-item"><input type="checkbox" name="Days" value="#item.Id" /> #item.DayName</li>
}
</ul>
Controller:
[HttpPost]
[RBAC]
public async Task<ActionResult> Create(UserProgramsViewModel model)
{
var groups = await _us.GetAll();
ViewBag.Users = groups.Select(x => new SelectListItem
{
Text = x.Login,
Value = x.Id.ToString()
});
var dto = new UserProgramsDTO
{
ProgramName = model.ProgramName,
UserId = model.UserId,
Days = model.Days
};
var result = await _ps.Create(dto);
if (result.IsSuccess == (BLL.Utilities.Enums.IsSuccess)Enums.IsSuccess.Success) return RedirectToAction("Index");
else return View("Create");
}
You can use FormCollection. Assign item.DayName to input's name attribute:
PartialView(fragment):
<li class="list-group-item">
<input type="checkbox" name="#(item.DayName)Days" #if (item.Id > 0) { <text>checked</text> } /> #item.DayName
</li>
Then process FormCollection parameter and fill model's Days property with it's help:
Controller:
[HttpPost]
[RBAC]
public async Task<ActionResult> Create(UserProgramsViewModel model, FormCollection formCollection)
{
model.Days = new List<DaysViewModel>();
foreach(var key in formCollection.AllKeys.Where(x => x.Contains("Days")))
model.Days.Add(new DaysViewModel { Id = formCollection[key] == "on" ? 1 : 0, DayName = key.Replace("Days", "")} );
//other stuff...
}
Have you set values for "Days" in your parent view from controller?
like Suppose your parent view name is "Parent" then you should write like this,
public ActionResult Parent()
{
UserProgramsViewModel loUser = new UserProgramsViewModel();
//Assign Your values here
View(loUser);
}
So may be you will not get Null value here.

Form submission in partial views in MVC

I am developing a simple mvc application . The code is as follows:
Model .cs:
public class CustomModel
{
public IEnumerable<lang> lstlang { get; set; }
public IEnumerable<org> lstOrg { get; set; }
}
public class lang
{
public int langid { get; set; }
public string langName { get; set; }
}
public class org
{
public int orgId { get ;set;}
public string orgName { get; set; }
}
Controller.cs
public Action Index()
{
// Get data from database and fill the model
var model = new CustomModel();
return View(model);
}
public Action Partial()
{
// Get data from database and fill the model
var model = new CustomModel();
return PartialView(model);
}
[HttpPost]
public Action Partial(FormCollection frm, CustomModel model)
{
// Get data from database and fill the model
var model = new CustomModel();
return PartialView(model);
}
Index.cshtml
#model CustomModel
#Html.TextboxFor(x => x.lang.FirstOrDefault().id);
<input type="button" id="btn" />
#Html.RenderPartial("Partial", model)
Partial.cshtml
#model CustomModel
#Html.TextboxFor(x => x.lang.FirstOrDefault().id);
<input type="submit" id="submit" />
The thing is, when I click the submit button in the Partial.cshtml page, and examine the model in httppost method in public Action Partial(FormCollection frm, CustomModel model), the model contains null for both lists lstlang and lstOrg, but the formcollection[0] will give the selected textbox value.
What am I missing, or is this the right way of using partial views?
Don't use FirstOrDefault(). If you want to post something back to the front end with collections, you'll need to use indexing.
Public class CustomModel
{
public ICollection<lang> lstlang { get; set; }
public ICollection<org> lstOrg { get; set; }
}
#HTML.textboxfor(x=>x.lang[0].id);

Fill one property of class by selecting one value on dropdownlist of another model

I have a class Client that have some properties in particular one is restriction_type. Also, I create another class Restriction with an ID and a name properties. The name property correspond to the restriction_type.
Then I display the name of all restrictions in my database in the dropdown list:
#Html.ActionLink("Create New", "Create")
#using (Html.BeginForm("AddRestrictions","Restrictions",FormMethod.Get)){
<p> Type de restriction:
#Html.DropDownList("ClientRestr_type", "All")
</p>
<input type="submit"value="Ajouter"/>
}
That is my controller:
public ActionResult AddRestriction(string ClientRestr_type, Restriction restriction)
{
var RestrLst = new List<string>();
var RestrQry = from d in db.Restrictions
orderby d.name
select d.name;
RestrLst.AddRange(RestrQry.Distinct());
ViewBag.ClientRestr_type = new SelectList(RestrLst);
var clients = from c in db.Restrictions select c;
if (string.IsNullOrEmpty(ClientRestr_type))
return View();
else
{
if (ModelState.IsValid)
{
// Here I have maybe to find the way to solve my problem
}
}
So I want to add the name property of Restriction in the restriction_type property of my Model Client.
Model Client:
public class Client
{
[Required]
public int ID
{
get;
set;
}
[Required]
public string compte
{
get;
set;
}
[Required]
public string portefeuille
{
get;
set;
}
[Required]
public String restriction_type
{
get;
set;
}
[Required]
public Boolean etat
{
get;
set;
}
public Boolean decision
{
get;
set;
}
Model Restriction:
public class Restriction
{
public int restrictionID
{
get;
set;
}
public string name
{
get;
set;
}
}
What do you think about my GetRestrictions() method
private SelectList GetRestrictions()
{
var RestrLst = new List<string>();
var RestrQry = from d in db.Restrictions
orderby d.name
select d.name;
RestrLst.AddRange(RestrQry.Distinct());
return new SelectList(RestrLst);
}
But unfortunately I have an error: Impossible to convert System.Web.Mvc.SelectList to MyApp.Models.Client at line:
model.RestrictionList = GetRestrictions();
I don't understand why
Thank you for your help!
A simplified example:
View model
public class ClientVM
{
public Client Client { get; set; }
public SelectList RestrictionList { get; set; }
}
Controller
[HttpGet]
public ActionResult Create()
{
ClientVM model = new ClientVM();
model.Client = new Client();
model.RestrictionList = GetRestrictions(); // your code to return the select list
return View("Edit", model);
}
[HttpGet]
public ActionResult Edit(int ID)
{
ClientVM model = new ClientVM();
model.Client = // call database to get client based on ID
model.RestrictionList = GetRestrictions();
return View(model);
}
[HttpPost]
public ActionResult Edit(ClientVM model)
{
if (!ModelState.IsValid)
{
model.RestrictionList = GetRestrictions();
return View(model);
}
Client client = model.Client;
// Save and redirect
....
}
View
#model YourNamespace.ClientVM
#using (Html.BeginForm() {
#Html.TextBoxFor(m => m.Client.ID)
#Html.TextBoxFor(m => m.Client.compte)
...
#Html.DropDownListFor(m => m.Client.restriction_type, Model.RestrictionList)
<input type="submit" value="Save" />
}

asp.net mvc binding between the model and the view

I am new to asp.net mvc . This is how my model looks like:
[Bind(Exclude = "JournalId")]
public class Journal
{
[ScaffoldColumn(false)]
public int JournalId { get; set; }
[DisplayName("Customer")]
public int CustomerId { get; set; }
[DisplayName("Till")]
public int TillId { get; set; }
[Required(ErrorMessage = "A Journal name is required")]
[StringLength(160)]
public string Name { get; set; }
[DisplayName("Journal creation date")]
public DateTime Date { get; set; }
[DisplayName("Journal creation time")]
public DateTime Time { get; set; }
public virtual Customer Customer { get; set; }
public virtual Till Till { get; set; }
}
[Bind(Exclude = "CustomerId")]
public class Customer
{
[ScaffoldColumn(false)]
public int CustomerId { get; set; }
[Required(ErrorMessage = "A customer name is required")]
[StringLength(160)]
public string Name { get; set; }
[StringLength(250)]
public string Address { get; set; }
}
[Bind(Exclude = "TillId")]
public class Till
{
[ScaffoldColumn(false)]
public int TillId { get; set; }
[Required(ErrorMessage = "A till no is required")]
[StringLength(160)]
public string TillNo { get; set; }
[StringLength(100)]
public string TillOperator { get; set; }
}
This is how my one of my controller's action is defined:
public ViewResult Index()
{
var journals = db.Journals.AsEnumerable<Journal>();
ViewData["journals"] = journals;
return View();
}
and the view :
#model IEnumerable<ErikDemo.Models.Journal>
#foreach (var item in (IEnumerable<ErikDemo.Models.Journal>)ViewData["journals"]) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Customer.Name)
</td>
<td>
#Truncate(item.Till.TillNo, 25)
</td>
<td>
#Truncate(item.Name, 25)
</td>
<td>
#Html.DisplayFor(modelItem => item.Date)
</td>
<td>
#Html.DisplayFor(modelItem => item.Time)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.JournalId }) |
#Html.ActionLink("Details", "Details", new { id=item.JournalId }) |
#Html.ActionLink("Delete", "Delete", new { id=item.JournalId })
</td>
</tr>
Although when I am debugging I can see in the controller that the list passed to the View is not empty, and also I see that the ViewData["journals"].Local in a watch is not empty, nothing gets displayed. I have also used the View.Model and return View(journals.ToList()) to send data to the View, but nothing seems to work. What is the issue here? Been on that half a day.
This is wrong: (Well it can be done like this, but I think you want to pass a model)
public ViewResult Index()
{
var journals = db.Journals.AsEnumerable<Journal>();
ViewData["journals"] = journals;
return View();
}
Try this:
public ViewResult Index()
{
var journals = db.Journals.AsEnumerable<Journal>();
return View(journals); //You just passed journals as a model
}
Also if you are using mvc 3 you can use ViewBag instead of ViewData
Example:
ViewData["Journal"] = "my string";
is the same as
ViewBag.Journal = "my string";
The ViewBag is dynamic, so you can use dot notation.
Additionally
This code:
#model IEnumerable<ErikDemo.Models.Journal>
#foreach (var item in (IEnumerable<ErikDemo.Models.Journal>)ViewData["journals"])
Should be like this:
#model IEnumerable<ErikDemo.Models.Journal>
#foreach (var item in Model)
Update:
I'm not sure what you're doing with this db.Journals.AsEnumerable<Journal>();
You should have a method somewhere that gets data from a table or table(s) and returns Journals. So lets say this all comes from one table in a database:
public class JournalViewModel
{
public IEnumerable<Journals> GetJournals()
{
using(var db = new ErikDataContext())
{
return db.Journals.ToList();
}
}
}
Then in the action:
public ViewResult Index()
{
var journals = new JournalsViewModel.GetJournals();
return View(journals); //You just passed journals as a model
}
Did you forget the <table> tag? If you haven't viewed the source of your page as it is rendered, I would recommend that you do this as a next step.

ASP.NET MVC - Modelbinding with Dropdownlist

Is it possible to have a single view model with a list that is used for a dropdownlist and also get the selected value of the dropdownlist from the view model when I post a form?
If so, how can I do this?
Sure, as always start by defining your view model:
public class MyViewModel
{
public int? SelectedItemValue { get; set; }
public IEnumerable<Item> Items { get; set; }
}
public class Item
{
public int? Value { get; set; }
public string Text { get; set; }
}
then the controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
// TODO: Fill the view model with data from
// a repository
Items = Enumerable
.Range(1, 5)
.Select(i => new Item
{
Value = i,
Text = "item " + i
})
};
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
// TODO: based on the value of model.SelectedItemValue
// you could perform some action here
return RedirectToAction("Index");
}
}
and finally the strongly typed view:
<% using (Html.BeginForm()) { %>
<%= Html.DropDownListFor(
x => x.SelectedItemValue,
new SelectList(Model.Items, "Value", "Text")
) %>
<input type="submit" value="OK" />
<% } %>

Categories