Html.DropDownListFor set selected value - asp.net

I create a #Html.DropDownListFor and populate it from the database. How can I set a selected value to the drop down?
My View:
#Html.DropDownListFor(m => m.Forms, new SelectList(Model.Forms, "FormsCreatorID", "FormName"),
"Select a Form", new { #class = "form-control" })
My Controller:
var forms = db.formscreators.Where(fp => fp.PropertyID == id || fp.PropertyID == 0)
.OrderByDescending(x => x.PropertyID).GroupBy(x => x.FormName).Select(x => x.FirstOrDefault()).ToList();
var viewModel = new ListFormsCreator { Forms = forms };
My ViewModel:
public class ListFormsCreator
{
public List<formscreator> Forms { get; set; }
}
My Database Model:
public partial class formscreator
{
public int FormsCreatorID { get; set; }
public string FormName { get; set; }
public int PropertyID { get; set; }
}
Thanks

You should add another property to your view model for the store/pass the selected option.
public class ListFormsCreator
{
public int SelectedFormId { set;get;}
public List<formscreator> Forms { get; set; }
}
Now in your GET action, you can set that value
var viewModel = new ListFormsCreator() { Forms = forms };
viewModel.SelectedFormId = 2 ; // This will select the option with 2 as FormsCreatorID
return View(viewModel);
And in the view use the lambda expression with that property as the first parameter of the DropDownListFor helper method.
#model ListFormsCreator
#Html.DropDownListFor(m => m.SelectedFormId ,
new SelectList(Model.Forms, "FormsCreatorID", "FormName"),
"Select a Form", new { #class = "form-control" })
The DropDownListFor helper method will use the value of SelectedFormId property and select the option which has the same value attribute value from the list of options of that SELECT element.
You can also remove the dependency on formscreator class from the view model, by replacing it with a list of SelectListItem
public class ListFormsCreator
{
public int SelectedFormId { set;get;}
public List<SelectListItem> Forms { get; set; }
}
Now in your GET action, you can use the Select method to generate the lsit of SelectListItem from your other collection.
var viewModel = new ListFormsCreator();
viewModel.Forms = someCollection.Select(a=>new SelectListItem {
Value=a.FormsCreatorId.ToString(),
Text=a.FormName})
.ToList();
viewModel.SelectedFormId = 2 ; // This will select the option with 2 as FormsCreatorID
return View(viewModel);
Assuming someCollection is a collection of formscreator objects
Now in the view code is much simpler
#Html.DropDownListFor(m => m.SelectedFormId, Model.Forms ,"Select a Form")

Conform with C#/.NET naming conventions:
Rename formscreator to FormsCreator
Replace ID with Id (as it's an abbreviation, not an initialism)
Rename ListFormsCreator to something like ListFormsCreatorViewModel so it's obvious it's a ViewModel type and not a Model/Entity type.
Modify your ViewModel to add a property to store the selected FormsCreatorId value:
public class ListFormsCreatorViewModel
{
[Required] // add or remove the 'Required' attribute as necessary
public int? SelectedFormsCreatorId { get; set; }
...
}
Set the SelectedFormsCreatorId property value in your controller action if necessary if you know what the value should be.
In your POST handler, ensure the SelectedFormsCreatorId value is maintained, either by directly passing-through the model action parameter back through the View(Object viewModel) method or manually repopulating it.
The view-model property in DropDownListFor should be the SelectedFormsCreatorId property. You do not need new SelectList(...)
#Html.DropDownListFor( m => m.SelectedFormsCreatorId, this.Model.Forms );

Update your viewModel and add an Int SelectId for the dropdown selected value.
In your controller:
var viewModel = new ListFormsCreator { SelectId = PropertyId, Forms = FormSelectList(forms, PropertyId.ToString()) };
I would create a function passing in a list:
public static SelectList FormSelectList(IEnumerable<formscreators> types, string selected = null)
{
return new SelectList(from f in forms
select new SelectListItem
{
Text = f.FormName,
Value = f.FormsCreatorID.ToString()
}, "Value", "Text", selected);
}
And in your .cshtml
#Html.DropDownListFor(m => m.PropertyId, Model.forms, "Select a Form", new { #class = "form-control", required = "required" })

You should generate a 'SelectListItem' list on the controller with setting 'Selected' value and pass it via ViewBag or ViewModel. In my sample, for simplicity, I used ViewBag.
Here is the shortened Controller:
public ActionResult Edit(int? id)
{
if (id == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
Album album = context.Albums.Find(id);
if (album == null)
{
return HttpNotFound();
}
ViewBag.GenreId = context.Genres.Select(
g => new SelectListItem()
{
Value = g.GenreId.ToString(),
Text = g.Name,
Selected = g.GenreId == album.GenreId ? true : false
}).ToList();
return View(album);
}
Here is the shortened View Code
#using MvcMusicStore2017.Models;
#model Album
#Html.DropDownList("GenreId", null, new { #class = "form-control" })

Related

Send Anonymous Type (List) to View in ASP.NET Core

I'm trying to send an anonymous type to my view.
The anonymous type is constructed in the following way:
public async Task<IActionResult> Historial()
{
return View(await _context.HechosLiquidador
.Select(c => new { Store = c.StoreID, LiqDate = c.FechaLFinLiq}).Distinct()
.AsNoTracking().OrderBy(s => s.LiqDate).ToListAsync());
}
The particularity of this case is that the result of the query is a list of items. How can I pass this to the view?
Should I construct a ViewModel? If that is the case, how can I populate that view model with the result of this query?
I have used a ViewModel as a solution to my problem.
ViewModel:
public class HistorialIndexData
{
public string StoreName { get; set; }
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime FechaLFinLiq { get; set; }
}
In the controller we will, at first, get the items that we want to list. Next we iterate through the object that contains those items and then store them on the ViewModel to finally be used to create a new list.
public async Task<IActionResult> Historial()
{
List<HistorialIndexData> newHistorial = new List<HistorialIndexData>();
var items = await _context.HechosLiquidador.Include(s => s.Stores)
.Select(c => new { Store = c.Stores.StoreName, LiqDate = c.FechaLFinLiq })
.Distinct()
.AsNoTracking().OrderBy(s => s.LiqDate)
.ToListAsync();
foreach(var itemtolist in items)
{
HistorialIndexData info = new HistorialIndexData
{
StoreName = itemtolist.Store,
FechaLFinLiq = itemtolist.LiqDate
};
newHistorial.Add(info);
}
return View(newHistorial);
}
Update the view to work with the ViewModel.
#model List<Application.Models.ApplicationviewModels.HistorialIndexData>

ASP.NET MVC ListBox does not show the selected list items

I am in a big trouble. I read 4 stackoverflow question and one blogpost. I have tried 5 different approach to view the selected items in a multiple selectlist.
I have no success.
The multiple selectlist is generated, but it does not select the items. I have no more idea.
Model:
public class EditableModel
{
public IList<Company> SelectedCompanies { get; set; }
public IList<SelectListItem> SelectListCompanies { get; set; }
}
Controller:
public ActionResult Edit(int id)
{
var service = _serviceDAL.GetEditableModel(id);
if (service!= null)
{
service.SelectListCompanies = GetSelectListCompanies(service.SelectedCompanies);
return View(service);
}
}
private IList<SelectListItem> GetSelectListCompanies(IList<Company> selectedCompanies)
{
List<SelectListItem> items = new List<SelectListItem>();
foreach (Companycompany in _companyService.GetCompanies())
{
items.Add(new SelectListItem
{
Value = company.CompanyId.ToString(),
Text = company.Name,
Selected = selectedCompanies.Any(x => x.CompanyId == company.CompanyId)
});
}
return items;
}
View
#Html.ListBox("SelectedCompanies", Model.SelectListCompanies, Model.SelectedCompanies.Select(x => x.CompanyId.ToString()) )
And nothing. The items in the select list is not selected...
I have tried this Multiselect, the same result, or this one as the current solution.
You cannot bind a <select multiple> to a collection of complex objects. It binds to, and posts back an array of simple values (the values of the selected options).
Your SelectedCompanies property needs to be IEnumerable<int> (assuming the CompanyId of Company is also int). Note also the Selected property of SelectListItem is ignored when binding to a property.
Your also using the same collection for the selected Companies and the list of all Companies which makes no sense. Your SelectListCompanies should be generated from your table of Company.
Model
public class MyViewModel
{
public IEnumerable<int> SelectedCompanies { get; set; }
public IEnumerable<SelectListItem> SelectListCompanies { get; set; }
}
Base on your current code for EditableModel, your code should be
public ActionResult Edit(int id)
{
var service = _serviceDAL.GetEditableModel(id);
....
MyViewModel model = new MyViewModel
{
SelectedCompanies = service.SelectedCompanies.Select(x => x.CompanyId),
SelectListCompanies = GetSelectListCompanies()
};
return View(model);
private IEnumerable<SelectListItem> GetSelectListCompanies()
{
var all companies = ... // call method to get all Companies
return companies.Select(x => new SelectListItem
{
Value = x.CompanyId.ToString(),
Text = x.Name
});
}
However, it look like you should be modifying your EditableModel and the GetEditableModel() code to return the correct data in the first place.

Use variable from controller in view ASP.NET MVC4

There is a model in my project
using System;
namespace Argussite.SupplierServices.ViewModels
{
public class UsersPage
{
public Guid SupplierId { get; set; }
public string SupplierFullName { get; set; }
public bool ActionsAllowed { get; set; }
}
}
I use my model in controller and set properties
public ActionResult Index(Guid id)
{
var supplierOfUser = Context.Suppliers.AsNoTracking()
//.Include(e => e.Supplier)
.FirstOrDefault(e => e.Id == id);
string SupplierId = id.ToString();
string SupplierFullName = supplierOfUser.FullName.ToString();
bool ActionsAllowed = supplierOfUser.Active;
return View();
}
and then I need to use that in view, but I don't know how to get my properties in the view?
Firstly your controller action needs to send that model instance to the view like this:
return View(supplierOfUser);
You need this at the top of your view:
#model Argussite.SupplierServices.ViewModels.UsersPage
Then all you need to do is whereever you want to use your model in the view do:
#Model.SupplierFullName
If you want to use other properties in the view that you can place them into a dynamic ViewBag variable like this:
ViewBag.supplierOfUser = supplierOfUser.FullName.ToString();
and then on your view you can use this value like this:
#ViewBag.supplierOfUser
Create a new UsersPage and assign the properties you already have to its properties, then pass the newly created UsersPage to the view:
public ActionResult Index(Guid id)
{
var supplierOfUser = Context.Suppliers.AsNoTracking()
//.Include(e => e.Supplier)
.FirstOrDefault(e => e.Id == id);
var usersPage = new UsersPage();
usersPage.SupplierId = id.ToString();
usersPage.SupplierFullName = supplierOfUser.FullName.ToString();
usersPage.ActionsAllowed = supplierOfUser.Active;
return View(usersPage);
}
In order to use your data from the controller to the view, you need to return the view with your model in parameter:
return View(supplierOfUser);
In your view, you'd also need to define the model:
#model YourModel
Note that you don't need to set your supplier info into other variables (only supplierOfUser is required).
Best way is to establish a strongly typed model in the view:
#model Argussite.SupplierServices.ViewModels.UsersPage
Then, just reference the properties on the model, e.g.
#Html.EditorFor(model => model.SupplierFullName)
It's hard to help you with exact code as I don't know what you want to do on your view, this is a general idea of how you're supposed to pass and use your model in your view
Controller
public ActionResult Index(Guid id)
{
var supplierOfUser = Context.Suppliers.AsNoTracking()
.FirstOrDefault(e => e.Id == id);
var usersPage = new UsersPage
{
SupplierId = supplierOfUser.Id,
SupplierFullName = supplierOfUser.FullName,
ActionsAllowed = supplierOfUser.Active
}
return View(usersPage ); // <-- Send viewmodel to view
}
VIEW
// Declare model
#model Argussite.SupplierServices.ViewModels.UsersPage
...
//Use your model here at will
#Html.DisplayFor(modelItem => item.FullName)
...
#Html.EditorFor(model => model.FullName)
#Html.ValidationMessageFor(model => model.FullName)

Extending #Html.DropDownListFor

I would like to use the following code by extending the #Html.DropDownListFor helper.
My controller gets a list, and I am adding a default value to the IEnumerable in my view model. However I don't want to write all of this every time I want a dropdown with a default value. So extending the helper seems logical.
public class SiteGetSitesViewModel
{
public string SelectedSiteId { get; set; }
public IEnumerable<SelectListItem> SiteListItems { get; set; }
}
public ActionResult GetSites()
{
List<SiteDto> sites = _siteService.GetSites();
const string defaultText = "Select a site";
const string defaultValue = "-1";
var siteGetSitesViewModel = new SiteGetSitesViewModel
{
SiteListItems = Enumerable.Repeat(new SelectListItem
{
Selected = true,
Text = defaultText,
Value = defaultValue
}, 1).Concat(sites.Select(s => new SelectListItem
{
Text = s.SiteName,
Value = s.SiteId.ToString()
}))
};
return PartialView("_GetSites", siteGetSitesViewModel);
}
Html.DropDownListFor supports adding a default value to the choices already, so there is no need to reinvent the wheel:
Use this overload:
http://msdn.microsoft.com/en-us/library/ee703567(v=vs.108).aspx
#Html.DropDownListFor(
m => m.Property,
GetSelectList(),
"defaultOption", // the text for the default option goes here
null
)

Dropdown list in asp.net

i've a view. in the view i've months field(nvarchar type in database) :
#Html.DropDownListFor(model => model.rent_month,
(IEnumerable<SelectListItem>)ViewBag.months)
i've a method in a model class (PostManager) to generate months list like:
public IEnumerable<SelectListItem> GetMyMonthList()
{
return CultureInfo.CurrentCulture.DateTimeFormat.MonthNames
.Select(m => new SelectListItem() { Text = m, Value = m });
}
i get months in get action by :
public ActionResult Create()
{
PostModel p = new PostModel();
ViewBag.months = pm.GetMyMonthList();
return View(p);
}
in my Model my month attributes:
[Required(ErrorMessage = "You Must Select a Month.")]
[Display(Name = "Select Rent Month")]
public string rent_month { get; set; }
in the post action:
public ActionResult Create(PostModel p)
{
if (ModelState.IsValid)
{
post post = new Models.DB.post();
post.rent_month = p.rent_month;
db.posts.AddObject(post);
db.SaveChanges();
}
}
it generates month in the dropdownlist correctly.But after submit the form it gives error:
The ViewData item that has the key 'rent_month' is of type 'System.String' but must be of type 'IEnumerable'
now what is the solution for this error... thanks in advance...
I believe this is happening because in your post action you are not populating the ViewBag again. Make sure you set ViewBag.months = pm.GetMyMonthList(); in your controller POST action similar to what you have done in GET action.
Better solution would be to have a IEnumerable<SelectListItem> MonthList property as part of the PostModel. Instead of loading the months from ViewBag you can access it directly by the MonthList property
In the PostModel
public IEnumerable<SelectListItem> MonthList
{
get
{
return pm
.GetMonthList()
.Select(a => new SelectListItem
{
Value = a.Id,
Text = a.MonthText
})
.ToList();
}
}
Then in the view
#Html.DropDownListFor(model => model.rent_month, Model.MonthList)
After EDIT to the question
Your PostModel class should be like this. I have moved your GetMyMonthList() implementation out of the PostManager class.
public class PostModel
{
[Required(ErrorMessage = "You Must Select a Month.")]
[Display(Name = "Select Rent Month")]
public string rent_month { get; set; }
public IEnumerable<SelectListItem> MonthList
{
get
{
return CultureInfo.CurrentCulture.DateTimeFormat.MonthNames
.Select(m => new SelectListItem() { Text = m, Value = m });
}
}
}
public class PostModel
{
[Required(ErrorMessage = "You Must Select a Month.")]
[Display(Name = "Select Rent Month")]
public string rent_month { get; set; }
public IEnumerable<SelectListItem> MonthList
{
get
{
return CultureInfo.CurrentCulture.DateTimeFormat.MonthNames
.Select(m => new SelectListItem() { Text = m, Value = m });
}
}
}

Resources