MVC 3 DropDownList displays multiple values on Edit page - c#

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)

Related

Add objects one by one when click button MVC C#

I have added items to the list.But the problem is in here i have added items one by one to the list after button click items.Every time only 1 object shows in the list.
List<Items> _objList = new List<Items>();
public ActionResult AddNewItems(int ItemId)
{
Items items = itemBusiness.GetItemByItemId(ItemId);
_objList.Add(new Items { ItemId =items.ItemId,ItemName =items.ItemName,
ItemPrice = items.ItemPrice });
Session["ItemSession"] = _objList;
return RedirectToAction("Index","Home");
}
Items DTO
public class Items
{
public int ItemId { get; set; }
public string ItemCode { get; set; }
public string ItemName { get; set; }
public string ImageUrl { get; set; }
public int? ItemBadge { get; set; }
public DateTime? AddedDate { get; set; }
public int? AddedBy { get; set; }
public DateTime? UpdatedDate { get; set; }
public int? UpdatedBy { get; set; }
public bool? IsActive { get; set; }
public decimal ItemPrice { get; set; }
}
You need to store the list, then retrieve it to add a new item to it. That create could be done a couple ways including calling a method that creates if it does not exist and returns that session list as in the
var _objList = (List<Items>)Session["ItemSession"];
Just make sure you DO have one so it does not throw an InvalidCastException
This code assumes you DO have a list stored in some "create" method prior to adding another one.
public ActionResult AddNewItems(int ItemId)
{
var _objList = (List<Items>)Session["ItemSession"];
Items items = itemBusiness.GetItemByItemId(ItemId);
_objList.Add(new Items { ItemId = items.ItemId,
ItemName = items.ItemName,
ItemPrice = items.ItemPrice });
Session["ItemSession"] = _objList;
return RedirectToAction("Index","Home");
}
Example alternate, set a property on your class and use that avoiding the cast exception by checking for null and creating if not there yet (and store at end as you have):
ItemsHolder.Add(new Items { ItemId = items.ItemId,
ItemName = items.ItemName,
ItemPrice = items.ItemPrice });
Add to your class
// the property
public List<Items> ItemsHolder
{
get
{
object ItemsSession = Session["ItemSession"] as List<Items>;
if (ItemsSession == null)
{
ItemsSession = new List<Items>();
Session["ItemSession"] = ItemsSession;
}
return (List<Items>)ItemsSession;
}
}
Side note, just make sure your items are serializable. You might just want to store a list of ItemId and get the name and price as needed to avoid some issues. https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/serialization/index

C# Editing ViewModel

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.

Using the selected item from DropDownList in MVC

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 )

How to access list of a ViewModel

I have the following model;
public class Object
{
public int Id { get; set; }
public string Name { get; set; }
public Nullable<double> Price { get; set; }
public string Description { get; set; }
public string Image { get; set; }
public Nullable<int> Type { get; set; }
}
and i create a view model;
public class PlanBaseTypedObjects
{
public int? Id { get; set; }
public IEnumerable<Object> ObjectDetails { get; set; }
}
in my controller i did grouping as follows;
var model = model1.GroupBy(t => t.Type).Select(g => new PlanBaseTypedObjects
{
Id = g.Key,
ObjectDetails = g
});
How can i get the number of records that belong to a particular "Type"??
for an example for type 1 how many records under ObjectDetails??
and can i access the "objectDetails" directly??
for an example if i want to know the "Name" of Id=3 of Type 2.how can i get it??
You need to iterate on the grouping result to find the count for each one.
foreach(var group in model)
{
int groupCount = group.ObjectDetails.Count();
}
If you want to access the items in ObjectDetails you need another foreach:
foreach(var group in model
{
int groupCount = group.ObjectDetails.Count();
foreach(var item in group.ObjectDetails))
{
//do something with item
}
}

MVC Dropdown using ViewModels without Magic String

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

Categories

Resources