I'm trying to use the user selected item from the DropDownList to create a new entry in my Database table that is related/linked?(Not sure of correct wording for this) to the DropDownList item.
Here are my Models
public class TaskInstance
{
public int Id { get; set; }
public DateTime DueDate { get; set; }
public int HowMany { get; set; }
public Task TaskId { get; set; }
public virtual Task Task { get; set; }
}
public class TaskInstanceViewModel
{
[DataType(DataType.DateTime)]
public DateTime DueDate { get; set; }
public int HowMany { get; set; }
public IEnumerable<SelectListItem> TaskList { get; set; }
public virtual ICollection<Task> Task { get; set; }
}
public class Task
{
public Task()
{
TaskInstance = new HashSet<TaskInstance>();
}
public int Id { get; set;}
public string Name { get; set; }
public string Unit { get; set; }
public virtual ICollection<TaskInstance> TaskInstance { get; set; }
}
Controllers
public ActionResult Create()
{
var model = new TaskInstanceViewModel();
model.TaskList = db.Task.ToList().Select(x => new SelectListItem
{
Value = x.Id.ToString(),
Text = x.Name
}).ToList();
return View(model);
}
// POST: TaskInstances/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(TaskInstanceViewModel model)
{
if (ModelState.IsValid)
{
var taskinstance = new TaskInstance { DueDate = model.DueDate };
db.TaskInstance.Add(taskinstance);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(model);
}
View - This is the only one I need to show I think, the others are just fields
#Html.DropDownListFor(x => Model.TaskList, (SelectList)Model.Task)
On the controller where it says var taskinstance = new TaskInstance { DueDate = model.DueDate }; Would be where i need to use the selected item from the User but I have no idea how to get it, i've looked through a lot of posts but most of them is just how to make the DropDownList in the first place but not how to use it(Being a link to another table) with a new database entry.
I'd also like to mention that I am still new to MVC so feel free to point out if im going about this the wrong way
Add a new property of type int to store the selected task from the dropdown. Remember view models are specific to the view.so keep only those properties you absolutely need in the view, in your view model.
public class TaskInstanceViewModel
{
public DateTime DueDate { get; set; }
public int HowMany { get; set; }
public IEnumerable<SelectListItem> TaskList { get; set; }
public int SelectedTask {set;get;} // new property
}
And in your view
#model TaskInstanceViewModel
#using(Html.BeginForm())
{
<label> How many</label>
#Html.TextBoxFor(s=>s.HowMany)
<label>Due date</label>
#Html.TextBoxFor(s=>s.DueDate)
<label>Task</label>
#Html.DropDownListFor(s => s.SelectedTask, Model.TaskList)
<input type="submit" />
}
And in your HttpPost action, you can use the SelectedTask property value which will have the Id of the task selected
[HttpPost]
public ActionResult Create(TaskInstanceViewModel model)
{
if (ModelState.IsValid)
{
var taskinstance = new TaskInstance { DueDate = model.DueDate ,
TaskId=model.SelectedTask };
db.TaskInstance.Add(taskinstance);
db.SaveChanges();
return RedirectToAction("Index");
}
model.TaskList = db.Task.ToList().Select(x => new SelectListItem
{
Value = x.Id.ToString(),
Text = x.Name
}).ToList();
return View(model);
}
It seems to me that you need you point to a property that represents the selected item in the dropdown. The dropdown items is IEnumerable<SelectListItem> why isn't the selected item a property of type SelectListItem?
Add a property to your view model:
public class TaskInstanceViewModel
{
[DataType(DataType.DateTime)]
public DateTime DueDate { get; set; }
public int HowMany { get; set; }
public IEnumerable<SelectListItem> TaskList { get; set; }
public virtual ICollection<Task> Task { get; set; }
//add this property:
public SelectListItem SelectedItem { get; set; }
}
And modify the view:
#Html.DropDownListFor(x => Model.TaskList, Model.SelectedItem )
Related
I have my ViewModel, and I have my controller to display from the ViewModel correctly, however I'm not sure how I would make the ViewModel editable, as to send the edited data back to the Model. I only want to edit the OrderArchiveViewModel, not the details
ViewModel;
public class OrderArchiveViewModel
{
public int OrderId { get; set; }
public System.DateTime OrderDate { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
public decimal Total { get; set; }
public bool HasBeenShipped { get; set; }
public List<OrderDetailArchive> Details { get; set; }
}
public class OrderDetailArchive
{
public string Title { get; set; }
public string Colour { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
}
Controller;
[Authorize(Roles = "Administrator")]
public ActionResult Index()
{
List<T_shirt_Company_v3.ViewModels.OrderArchiveViewModel> list = (from o in new TshirtStoreDB().Orders
.OrderBy(o => o.OrderDate)
.Select(o => new OrderArchiveViewModel()
{
OrderId = o.OrderId,
Address = o.Address,
FirstName = o.FirstName,
LastName = o.LastName,
City = o.City,
OrderDate = o.OrderDate,
PostalCode = o.PostalCode,
Total = o.Total,
HasBeenShipped = o.HasBeenShipped,
Details = (from d in o.OrderDetails
select new OrderDetailArchive
{
Colour = d.Product.Colour,
Quantity = d.Quantity,
Title = d.Product.Title,
UnitPrice = d.UnitPrice
}).ToList()
}).ToList()select o).ToList();
ViewBag.ShippedMessage = list.Where(w => w.HasBeenShipped).Any() ? "Order has been shipped" : "Order is being processed";
return View(list);
}
I can suggest you to make an another two actions.
public ActionResult Edit(int id)
where you will get the Order by it's Id, map to ViewModel and pass it to the view where you will have textboxes for editing. Create another one Action for accepting post request with updated model:
[HttpPost]
public ActionResult Edit(OrderArchiveViewModel model)
When the the edit page is submitted you will have a updated model with the new data, then find your model in database by Id and update the properties.
Can u send the code of your View to get more clarification?
The already given answer could be done by redirect to a page for editing purpose.
Do you want to show the Editing fields above the Grid?
For this purpose, you can add New ViewModel like
public class NewViewModel
{
public OrderArchiveViewModel OrderArchiveViewModel { get; set; }
public List<OrderArchiveViewModel> OrderArchiveViewModelList { get; set; }
}
And you can send data using this NewViewModel to View containing both editable OrderArchiveViewModel depending on the Id and also the List of OrderArchiveViewModel by assigning the list present in Index() action.
I used scaffolding to create the Index, Details, Create, Edit and Delete views and the controller. I have two view models (Parent / Child) relation. In my Index view I want to display the list of Teams as well as some information on the players (Parent / child). For example I want to display in the Index view the teams with the players count per team and last players that was modified. I am not sure where to begin.
Example:
(Team) Red -- (Last Modified) 01/02/2015 -- (Number Players) 10 and so on.
Team ViewModel
public class TeamVM
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime? LastActivity { get; set; }
public string NumberPlayers { get; set; }
public IList<PLayerVM> PlayerVM { get; set; }
}
Player ViewModel
public class PlayerVM
{
public int ID { get; set; }
public int TeamID { get; set; }
public string PlayerInfo { get; set; }
public DateTime? CreateDate { get; set; }
}
Other ViewModel
public class TeamViewModel
{
public List<Team> Teams{ get; set; }
}
Controller
public ActionResult Index()
{
TeamViewModelviewModel = new TeamViewModel();
viewModel.Teams= db.Teams.ToList();
return View(viewModel);
}
db.Products.ToList()?? I assume that is where you mean db.Teams.ToList()?
You are using viewmodels, so you should map the db data to your viewmodels first:
public ActionResult Index()
{
var teams = db
.Teams
.Include("Players") // Assuming your Team entity has a collection of Players
.SelectMany(t => new TeamVM {
ID = t.ID,
// etc..
})
.ToList();
return View(new TeamViewModel { Teams = teams });
}
model:
public class TeamVM
{
public int ID { get; set; }
public string Name { get; set; }
public DateTime? LastActivity { get; set; }
public IList<PLayerVM> PlayerVM { get; set; }
public int NumberPlayers {
get { return PlayerVM.Count(); }
}
}
Then in your view:
#model MyProject.Models.TeamViewModel
<table>
#foreach(var team in Model.Teams.ToList()) {
<tr>
<td>#team.Name</td> // Name
<td>#team.NumberPlayers</td> // Playercount
<td>#team.PlayerVM.Max(p => p.LastActivity).LastActivity</td> // Last edited
</tr>
}
</table>
I am trying to get a drop-down from a database to work. I did not get too far. I am trying to do it using viewModel and not use Magic String. I have a feeling I am not too far off. Could some please take a look and see what I am missing or doing wrong?
I am getting a compiling error at this line in the controller: viewModel.Courts = CourtList,
I am pretty sure it is wrong but I am running of ideas on how to do this.
Domain Models:
public class Parent
{
public int ParentID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual Court Court { get; set; }
//public IEnumerable<SelectListItem> Courts { get; set; }
public virtual ICollection<Child> Childs { get; set; }
}
public class Court
{
public int CourtId { get; set; }
public string CourtName { get; set; }
public virtual ICollection<Parent> Parents { get; set; }
}
View Model:
public class ParentVM
{
public int ParentID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
//public int CourtId { get; set; }
//public string CourtName { get; set; }
public virtual Court Court { get; set; }
//public virtual IEnumerable<Court> CourtList { get; set; }
public IEnumerable<SelectListItem> Courts { get; set; }
public IList<ChildVM> Children { get; set; }
}
Controller:
// GET: Parents/Create
public ActionResult Create()
{
IEnumerable<SelectListItem> CourtList = db.Courts.ToList().Select(x => new SelectListItem
{
Value = x.CourtId.ToString(),
Text = x.CourtName,
});
//ViewBag.CourtList = new SelectList(db.Courts, "CourtId", "CourtName");
ParentVM viewModel = new ParentVM()
{
Children = new List<ChildVM>()
{
new ChildVM(){Name="", DOB="", Address=""},
//new ChildVM(){Name="2", DOB="2", Address="222"},
//new ChildVM(){Name="3", DOB="3", Address="3"},
},
viewModel.Courts = CourtList,
};
return View(viewModel);
}
// POST: Parents/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ParentVM viewModel)
{
if (ModelState.IsValid)
{
var parent = new Parent()
{
FirstName = viewModel.FirstName,
LastName = viewModel.LastName
};
db.Parents.Add(parent);
foreach (ChildVM item in viewModel.Children)
{
var child = new Child()
{
Name = item.Name,
DOB = item.DOB,
Address = item.Address
};
db.Childs.Add(child);
}
//Parent parent = new Parent();
//var employee = AutoMapper.Mapper.Map<Parent, ParentVM>(parent);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
View:
#Html.DropDownList("Courts", (IEnumerable<SelectListItem>)Model.Courts)
Your trying to bind you dropdownlist to property Courts which is IEnumerable<SelectListItem>. A <select> posts back a value type (the value of the selected item) which cannot be bound to a collection. You need an additional property to bind to (or you could bind to Court.CourtId, but the CourtName property of Court wont be bound on postback.
View model
public class ParentVM
{
public int ParentID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[Required]
public int? SelectedCourt { get; set; } // bind the dropdown to this
public SelectList CourtList { get; set; }
public IList<ChildVM> Children { get; set; }
}
Controller
public ActionResult Create()
{
ParentVM model = new ParentVM()
{
Children = new List<ChildVM>() .....,
CourtList = new SelectList(db.Courts, "CourtId", "CourtName"),
SelectCourt = // set a value here if you want a specific option to be selected
});
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ParentVM model)
{
if (ModelState.IsValid)
{
Court court = db.Courts.Find(model.SelectedCourt) // get the Court based on `SelectedCourt`
var parent = new Parent()
{
FirstName = model.FirstName,
LastName = model.LastName,
Court = court
};
db.Parents.Add(parent);
foreach (ChildVM item in viewModel.Children)
{
....
db.Childs.Add(child);
}
db.SaveChanges();
return RedirectToAction("Index");
}
model.CourtList = new SelectList(db.Courts, "CourtId", "CourtName"); // reassign select list
return View(model);
}
View
#Html.DropDownListFor(m => m.SelectedCourt, Model.CourtList, "--Please select--")
If the value of SelectedCourt matches the value of one of the options, it will be selected when the page is rendered, otherwise the first (label) option will be selected. When you post back, the value of SelectedCourt will be the value of the selected option
I am new to ASP.NET MVC and was/am not sure exactly how to word my problem. I have to create a page where the user can add a list of multiple collateral items to a loan application. Each "row" for each collateral items needs several Dropdownlist to select the type of collateral, its class etc. The page is based on a ViewModel:
public class CollateralViewModel
{
public Guid LoanApplicationId { get; set; }
public IEnumerable<CollateralRowViewModel> Collateral { get; set; }
}
The IEnumerable Collateral gets the following:
public class CollateralRowViewModel
{
public Guid Id { get; set; }
public Guid LoanApplicationId { get; set; }
public IEnumerable<SelectListItem> CollateralClass { get; set; }
public IEnumerable<SelectListItem> CollateralType { get; set; }
public Guid SelectedCollateralType { get; set; }
public Guid SelectedCollateralClass { get; set; }
[DataType(DataType.MultilineText)]
public string Description { get; set; }
public decimal? MarketValue { get; set; }
public decimal? PriorLiens { get; set; }
public decimal? AdvanceRate { get; set; }
public string GrantorFirstName { get; set; }
public string GrantorMiddleName { get; set; }
public string GrantorLastName { get; set; }
}
My Controller looks like this:
public async Task<ActionResult> Create(CollateralViewModel collateralViewModel)
{
var collateralServiceProxy = base.ServiceProvider.CollateralServiceProxy;
var collateralTypes = await GetCollateralTypesByClass(Guid.NewGuid());
var selectedCollateral = collateralViewModel.Collateral.Select(collateral => new Collateral()
{
Id = collateral.Id,
LoanApplicationId = collateral.LoanApplicationId,
CollateralTypeId = collateral.SelectedCollateralType,
Description = collateral.Description,
GrantorFirstName = collateral.GrantorFirstName,
GrantorMiddleName = collateral.GrantorMiddleName,
GrantorLastName = collateral.GrantorLastName,
PriorLiens = collateral.PriorLiens,
MarketValue = collateral.MarketValue
});
foreach (var collateral in selectedCollateral)
{
await collateralServiceProxy.PutCollateralAsync(collateral);
}
return View(collateralViewModel);
}
private async Task<IEnumerable<SelectListItem>> GetCollateralClasses()
{
var collateralServiceProxy = base.ServiceProvider.CollateralServiceProxy;
var collateralClasses = await collateralServiceProxy.GetAllCollateralClassesAsync();
if (collateralClasses == null)
{
return new List<SelectListItem>();
}
return collateralClasses.ToSelectList();
}
private async Task<IEnumerable<SelectListItem>> GetCollateralTypesByClass(Guid collateralClassId)
{
var allCollateralTypes = await GetAllCollateralTypes();
var selectedCollateralTypes = allCollateralTypes.Where(collateralType => Guid.Parse(collateralType.Value).Equals(collateralClassId));
return selectedCollateralTypes;
}
When I try to use #Html.DropDownListFor(model=>model.Collateral.CollateralClasses) I cannot because CollateralClasses is unavailable. I type "(model.Collateral." and the properties aren't there. What am I doing wrong here?
Any help is greatly appreciated!!
Please check you dropdownlistfor syntex. I think that may be the issue (because you have not specified the error).Please check the syntex
#Html.DropDownListFor(m => m.ContribType,
new SelectList(Model.ContribTypeOptions,
"ContribId", "Value",
Model.ContribTypeOptions.First().ContribId))
so you may try it like this. In your first place "valueItRepresent", it should be the property for which the dropdown is for
#Html.DropDownListFor(model => model.valueItRepresent, model.Collateral.FirstOrDefault().CollateralClasses‌ as SelectList, "Select")
The issue is your dropdownlist not populated when rendering the UI. You have to properly populate dropdownlist before render data.This can be done in several ways, but I would recommend reading below article.
This article provide solution for your question
http://odetocode.com/blogs/scott/archive/2013/03/11/dropdownlistfor-with-asp-net-mvc.aspx
Hope this helps.
I'm using an enum to populate my DropDownList that works fine with a List and Create views but my Edit view loads duplicate values in the DropDownList. The duplicate values are only the selected value for the property meaning, if Rented was the value saved in the DB the DropDownList would show Rented selected, Available, and another Rented in the list. What I need to know is how to load a DropDownList that selects the value previously stored in the DB for the PropertyStatus enum without any duplicates?
Controler:
public ActionResult Edit(int id)
{
Property property = db.Properties.Find(id);
ViewBag.PropertyStatus = SetViewBagPropertyStatus();
return View(property);
}
private IEnumerable<SelectListItem> SetViewBagPropertyStatus()
{
IEnumerable<ePropStatus> values =
Enum.GetValues(typeof(ePropStatus)).Cast<ePropStatus>();
IEnumerable<SelectListItem> items =
from value in values
select new SelectListItem
{
Text = value.ToString(),
Value = value.ToString()
};
return items;
}
Model:
public enum ePropStatus
{
Available ,
Rented
}
public partial class Property
{
public int PropertyId { get; set; }
public string PropName { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public int SqFeet { get; set; }
public int Bedrooms { get; set; }
public int Bathrooms { get; set; }
public int Garage { get; set; }
public string Notes { get; set; }
public ePropStatus PropertyStatus { get; set; }
}
Edit View:
#Html.DropDownList("PropertyStatus", Model.PropertyStatus.ToString())
Try this instead :
#Html.DropDownListFor(model => model.PropertyStatus, ViewBag.PropertyStatus)
Edit ::: Alternately try this
Controler:
public ActionResult Edit(int id)
{
Property property = db.Properties.Find(id);
ViewBag.PropertyStatusList = SetViewBagPropertyStatus(property.PropertyStatus);
return View(property);
}
private IEnumerable<SelectListItem> SetViewBagPropertyStatus(string selectedValue = "")
{
IEnumerable<ePropStatus> values =
Enum.GetValues(typeof(ePropStatus)).Cast<ePropStatus>();
IEnumerable<SelectListItem> items =
from value in values
select new SelectListItem
{
Text = value.ToString(),
Value = value.ToString(),
Selected = (selectedValue == value.ToString())
};
return items;
}
View:
#Html.DropDownList("PropertyStatus", ViewBag.PropertyStatusList)