I'm trying to move over to MVC from webforms, and to be honest, it's not going very well.
I need a DropDownList populated with values from my database, and I'm having a hard time understanding how to do this.
I'm thinking, that I need to create a model,using entity framework, and refer my DropDownList to that? But how do I point it to that model?
Also, if I make a model, from a database table, how do I adjust the select command, so I only get certain values, and not the entire table?
I know this is kind of a broad question, and I have no examples listed, but I've had a really hard time, finding information I could understand, with regards to my issue.
I would start from this this should get you the project created if you have not done so so you can have the model ready
http://msdn.microsoft.com/en-us/data/gg685489
in order to create a dropdownlist here is an example
ViewBag.dropdownlist = new SelectList(db.tablename, "Valuefiled", "NameGField");
where Valuefiled=name of a column in your database that you want to use for values
"NameGField"=name of a column in your database that you want to use for names
getting drop down list to view
#Html.DropDownList("dropdownlist")
How About this
Your ViewModel
public class CategoryViewModel
{
public Category Category { get; set; }
public IEnumerable<SelectListItem> CategoryTitles { get; set; }
}
Your Controller
public ActionResult Create()
{
var categoryviewmodel = new CategoryViewModel();
categoryviewmodel.Category = new Category();
var list = categoryRepository.AllCategoryTitles().ToList().Select(t => new SelectListItem
{
Text = t.CategoryName,
Value = t.CategoryID.ToString()
})
.ToList();
list.Insert(0, new SelectListItem { Value = "0", Text = "Please Selext" });
categoryviewmodel.CategoryTitles = list;
return View(categoryviewmodel);
}
Your Repository
public IQueryable<Category> AllCategoryTitles()
{
var query = context.Categories.Where(m => m.ParentCategoryID == null && m.IsActive==true);
return query;
}
Your View
#Html.DropDownListFor(model => model.CategoryParentID, Model.CategoryTitles)
You can use a viewModel. Here is an example solution with some assumptions. Refer to the dropdownlist (here in the dropdown I am listing departments of type "InBound"
Employee Model
public class EmployeeModel
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int DeptId { get; set; }
}
Department Model
public class DepartmentModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Type { get; set; }
}
ViewModel (to be passed into the view)
public class EmployeeViewModel
{
public EmployeeModel Employee { get; set; }
public IEnumerable<DepartmentModel> Departments { get; set; }
}
Controller
public ActionResult Index()
{
EmployeeViewModel vm = new EmployeeViewModel();
//This is hardcoded. However you will write your own method to pull the department details with filtering
List<DepartmentModel> departments = new List<DepartmentModel>() { new DepartmentModel { Id = 1, Name = "Accounts", Type = "InBound" }, new DepartmentModel { Id = 2, Name = "Finance", Type = "OutBound" }, new DepartmentModel { Id = 3, Name = "HR", Type = "InBound" } };
vm.Departments = departments.Where(d => d.Type == "InBound");
return View(vm);
}
View
#model Test1.ViewModels.EmployeeViewModel
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
#using (Html.BeginForm())
{
#Html.HiddenFor(model => model.Employee.Id);
<table>
<tr>
<td>#Html.LabelFor(model => model.Employee.FirstName)</td>
<td>#Html.EditorFor(model => model.Employee.FirstName)</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.Employee.LastName)</td>
<td>#Html.EditorFor(model => model.Employee.LastName)</td>
</tr>
<tr>
<td>#Html.Label("Department")</td>
<td>#Html.DropDownListFor(model => model.Employee.DeptId, new SelectList(Model.Departments, "Id", "Name"))</td>
</tr>
</table>
}
Related
I am trying to create an edit form which includes a selectlist that gets the data from the database. I am unable to display the form since I cannot map the viewmodel with the actual model using Automapper.
Contact.cs:
public int ContactId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string? EmailAddress { get; set; }
public int CompanyId { get; set; }
[ForeignKey("CompanyId")]
public Company Company { get; set; }
ContactEditViewModel.cs:
public int ContactId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string? EMailAddress { get; set; }
[Range(1, int.MaxValue, ErrorMessage = "Please select a company.")]
public int CompanyId { get; set; }
public SelectList? Company { get; set; }
Edit View
<div class="form-group">
<label asp-for="Company" class="control-label"></label>
<div class="input-group mb-3">
<select asp-for="CompanyId" class="form-select" asp-items="#Model.Company"></select>
</div>
</div>
ContactsController Edit Action:
public async Task<IActionResult> Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var contact = await _context.Contacts.FirstOrDefaultAsync(c => c.ContactId == id);
var model = new ContactEditVM
{
Company = new SelectList(_context.Companies, "CompanyId", "CompanyName"),
};
//var contact = mapper.Map<ContactEditVM>(await contactRepository.GetAsync(id));
mapper.Map(model, contact);
if (contact == null)
{
return NotFound();
}
//ViewData["CompanyId"] = new SelectList(_context.Companies, "CompanyId", "CompanyName", contact.Company);
return View(model);
}
MappingConfiguration
public class MapConfig : Profile
{
public MapConfig()
{
CreateMap<Contact, ContactListVM>().ReverseMap();
CreateMap<Contact, ContactCreateVM>().ReverseMap();
CreateMap<Contact, ContactEditVM>().ReverseMap();
}
}
The error I get is:
AutoMapperMappingException: Missing type map configuration or unsupported mapping.
Mapping types:
SelectList -> Company
Microsoft.AspNetCore.Mvc.Rendering.SelectList -> ENV.Data.Company
Destination Member:
Company
...
If I create a new instance of my viewmodel and assign values to it manually, without using Automapper, it works as intended. So what is wrong with my mapping?
Does it work if you outcomment the "Company" from your Contact.cs and outcomment the "Company" from your ContactEditViewModel.cs?
I think you need to define a mapping which tells autoMapper how to map a "SelectedList?" to a "Company".
For Example:
var autoMapperConfig = new MapperConfiguration(cfg =>
{
cfg.CreateMap<WalletData/*Source*/, BP_WalletDTO/*Destination*/>()
.ForMember(dest => dest.Id, memberOptions => memberOptions.MapFrom(src => src.Id))
.ForMember(dest => dest.Type, memberOptions => memberOptions.MapFrom(src => src.Type))
.ForMember(dest => dest.Attributes, memberOptions => memberOptions.MapFrom(src => new BP_WalletAttributesDTO
{
CryptocoinId = src.Attributes.Cryptocoin_id,
CryptocoinSymbol = src.Attributes.Cryptocoin_symbol,
Balance = src.Attributes.Balance,
IsDefault = src.Attributes.Is_default,
Name = src.Attributes.Name,
PendingTransactionsCount = src.Attributes.Pending_transactions_count,
Deleted = src.Attributes.Deleted,
IsIndex = src.Attributes.Is_index,
}));
});
Maybe this helps
i have a view that is bound with the IEnumerable<ProductCategoryViewModel>
in this view there is a drop down box with the values search type values so i can search a product category by either code or name.
here is the controller:
public ActionResult Index()
{
List<SelectListItem> list = new List<SelectListItem> {
new SelectListItem {Text="By Code", Value="1", Selected=true},
new SelectListItem {Text="By Name", Value="2"}
};
var categories = _db.mt_ProductCategories
.Select(
p => new ProductCategoriesViewModel
{
Id = p.Id,
Name = p.CatName,
CatCode = p.CatCode, SearchTypes=list
});
if (Request.IsAjaxRequest())
{
return PartialView("_ProductCategoryList", categories);
}
return View(categories);
}
here is the ViewModel
public class ProductCategoriesViewModel
{
public int Id { get; set; }
public string CatCode { get; set; }
public string Name { get; set; }
public IEnumerable<SelectListItem> SearchTypes { get; set; }
public string SearchType { get; set; }
}
here is view
#model IEnumerable<eComm1.Models.ProductCategoriesViewModel>
#using (Ajax.BeginForm("Search", "ProductCategory",
new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "prod-grid",
InsertionMode = InsertionMode.Replace,
OnSuccess = "loaddivdata"
}))
{
//i need to put the drop down here but since i passed a collection it does not show the property "SearchType". the code should be like below but errors
#Html.DropDownListFor(m=>m.SearchType, Model.SearchTypes)
}
How do i access the property SearchType in my current view?
You need a view model that has properties for SearchType and SearchType and in the view use a single instance of that view model (and initially generate the list of ProductCategories by calling #Html.Action()).
public class ProductSearchVM
{
public string searchText { get; set; }
public string SearchType { get; set; }
public IEnumerable<SelectListItem> SearchTypes { get; set; }
}
and in the controller
public ActionResult Index()
{
ProductSearchVM model = new ProductSearchVM
{
SearchType = "1", // this is how you set the selected value
SearchTypes = new List<SelectListItem>
{
new SelectListItem { Text = "By Code", Value = "1" }, // no point adding Selected = true; - its ignored by the HtmlHelper
new SelectListItem { Text = "By Name", Value = "2" }
}
};
return View(model)
}
and in the view
#model ProductSearchVM
#using (Ajax.BeginForm("Search", "ProductCategory", new AjaxOptions { ... }))
{
#Html.DropDownListFor(m => m.SearchType, Model.SearchTypes)
#Html.TextBoxFor(m => m.searchText)
}
<div id="prod-grid">
#Html.Action("Search", "ProductCategory") // optionally add new { searchType = "1" }?
</div>
I've been trying to populate a dropdownlist for a while now and would appreciate some help. I have my model and viewmodel and my trying to populate the Dropdownlist and send it to the view so a user can choose a cartype and click submit.
public class Cars
{
public int CarId { get; set; }
public string Name { get; set; }
}
public class CarViewModel
{
public int SelectedCarId { get; set; }
public IEnumerable<SelectListItem> CarTypes;
}
public ActionResult FillDropDown()
{
var model = new ViewModel();
model.CarTypes = (from s in context.CarTypes
select new SelectListItem()
{
Text = s.Name,
Value = SqlFunctions.StringConvert((double)s.Id).Trim(),
}).ToList<SelectListItem>();
return View(model);
}
So I would like some help how to render this in the view. I tried the following but I get a nullreference exception.
#Html.BeginForm("FillDropDownList","Home", FormMethod.Post,null)
{
#Html.DropDownListFor(x => x.SelectedCarId, Model.CarTypes);
<input type="submit" value="submit" />
}
Try to use CarViewModel instead of ViewModel.
public ActionResult FillDropDown()
{
var model = new CarViewModel(); //CarViewModel instead of ViewModel
model.CarTypes = (from s in context.CarTypes
select new SelectListItem()
{
Text = s.Name,
Value = SqlFunctions.StringConvert((double)s.Id).Trim(),
}).ToList<SelectListItem>();
return View(model);
}
EDIT:
Change your IEnumerable property in CarViewModel into SelectList
public class CarViewModel
{
public int SelectedCarId { get; set; }
public SelectList CarTypes;
}
Make sure the SelectListItem is not null, in the FillDropDown() method.
I have a custom model (let's say CustomModel) for populating my razor DropDownList in the view:
namespace MyNamespace.Models
{
public class SelectListItem
{
public string Value { get; set; }
public string Text { get; set; }
}
public class ComponentTypeModel
{
private readonly List<ComponentType> componentTypes;
[Display(Name = "Component Type")]
public int SelectedCompTypeId { get; set; }
public IEnumerable<SelectListItem> CompTypeItems
{
get
{
var allCompTypes = componentTypes.Select(f => new SelectListItem
{
Value = f.Id.ToString(),
Text = f.Name
});
return allCompTypes;
}
}
public IEnumerable<SelectListItem> DefaultCompTypeItem
{
get
{
return Enumerable.Repeat(new SelectListItem
{
Value = "-1",
Text = "Select a component type"
},
count: 1);
}
}
}
}
Then in my view I do the following using razor:
#model MyNamespace.Models.CustomModel
#Html.LabelFor(m => m.SelectedCompTypeId);
#Html.DropDownListFor(m => m.SelectedCompTypeId, Model.CompTypeItems);
but the second argument Model.CompTypeItems in line:
#Html.DropDownListFor(m => m.SelectedCompTypeId, Model.CompTypeItems);
is generating a compilation error saying that it is not valid. Any ideas?
I think you are complicating yourself.
Just use this model:
public class ComponentTypeModel
{
public int? SelectedComp {get; set;}
public SelectList DDLCompTypes {get; set;}
}
Then in your controller:
var model = new ComponentTypeModel();
model.DDLCompTypes = new SelectList(theComponentTypes, "Id","Name");
//If you need to set some value in the DropDownValue (for instance in the Edit view) you do:
model.DDLCompTypes = new SelectList(theComponentTypes, "Id","Name", model.SelectedComp);
Then in your View:
#Html.DropDownFor(x => x.SelectedComp, Model.DDLCompTypes, "Select a component type" )
I have a strange problem and I don't know if this is actually possible.
What I want is, to be able to list all the values from my model and and edit them directly in the list.
Here's what I have:
Model Linker:
public class StoreLinkerModel
{
//public Guid? id { get; set; }
public IEnumerable<Stores> StoresAndOpeninghours { get; set; }
}
public class Stores
{
public long ID { get; set; }
public string StoreName { get; set; }
public string Address { get; set; }
public string Zip { get; set; }
public string City { get; set; }
}
My Controller:
public ActionResult Overview()
{
var model = new StoreLinkerModel
{
StoresAndOpeninghours = new[]
{
new Stores()
{
ID = 0,
Address = "Enghavevej 70"
},
new Stores()
{
ID=1,
Address = "Løngangsgade 30"
},
}
};
return View(model);
}
[HttpPost]
public ActionResult Overview(StoreLinkerModel model)
{
if (ModelState.IsValid)
{
var x = "go go go";
}
return RedirectToAction("Overview");
}
My overview.aspx page:
#model streetoffrs.web.Models.StoreLinkerModel
#{
ViewBag.Title = "Overview";
Layout = "~/Views/Shared/_dashboard.cshtml";
}
#Html.EditorFor(x => x.StoresAndOpeninghours)
and my EditorTemplate stores.aspx
#model streetoffrs.web.Models.Stores
#using (Html.BeginForm("Overview", "Dashboard", FormMethod.Post, new { name = "id" + #Html.DisplayFor(m => m.ID) }))
{
#Html.EditorFor(x => x.Address)
<input type="submit" class="left btn btn-primary" value="Ret butiksdata">
}
<br />
The list is being generated as it should, and when I hit the first button at the first editorfor it will post the model to my controller, but when I push the 2nd button, the model is null, but the first button still works!
Is this possible at all, if yes what am I missing, if not, tell me how I can accomplish this.
thanks in advance!
you need edit post action like this:
[HttpPost]
public ActionResult Overview(StoreLinkerModel model)
{
if (ModelState.IsValid)
{
var x = "go go go";
}
return View(model);
}
the RedirectToAction will be go to the first Overview Action,so you will be lost the data.