Previously, I was using this in my model
public List<SelectListItem> StatusList { get; set; }
public string Status { get; set; }
and this in my view to bind to the Dropdownlist
#Html.DropDownListFor(model => model.Status, Model.StatusList, "")
but if I want to use
public List<ICode> StatusList { get; set; }
where ICode is as below
public interface ICode
{
int Id { get; set; }
ICodeGroup CodeGroup { get; set; }
string ShortDescription { get; set; }
string LongDescription { get; set; }
}
What should I do in my view and model?
Cybernate's solution works. You could also do:
#Html.DropDownListFor(model => model.Status,
new SelectList(Model.StatusList, "Id", "ShortDescription"))
Cybernate's version will do stronger type checking, but SelectList is more encapsulated.
Try this:
#Html.DropDownListFor(model => model.Status,
Model.StatusList.Select(a=>
new SelectListItem(){
Text=a.ShortDescription, Value=a.Id.ToString()
}),
"")
Related
i created a dropdown list in MVC page,i want when changed id,new data pass to Action with below code:
#if (ViewBag.IdType==1)
{
#Html.DropDownListFor(m => m.Citycode, new SelectList(ViewBag.ResultList as System.Collections.IEnumerable, "Citycode", "CityName","1"))
#Html.ValidationMessageFor(model => model.Citycode)
}
else
{
#Html.DropDownListFor(m => m.IDReshteh, new SelectList(ViewBag.ResultList as System.Collections.IEnumerable, "IDReshteh", "ReshteName",Model.IDReshteh),"Fselect")
#Html.ValidationMessageFor(model => model.IDReshteh)
}
<input type="hidden" id="SelValue" value="1"/>
<input type="submit" value="Submit" />
</p>
/*<input type="hidden" name="HDcity" id="HDcity" />*/
<div id="LoadData">
#Html.Action("selVahedListAjax", new { IdReshte = ViewBag.ChooseItem, IdCity = Model.IDReshteh })
</div>
Model:
public class TInfo
{
[Key]
public int Id { get; set; }
[Required]
public string Scode { get; set; }
[Required]
public string SName { get; set; }
[Required]
public string TName { get; set; }
public string ModirName { get; set; }
public string FZamineh { get; set; }
public string TAddress { get; set; }
public string PcodeSh { get; set; }
public string TelcodeSh { get; set; }
public string FaxcodeSh { get; set; }
public string DAddress { get; set; }
public string PcodeDa { get; set; }
public string TelcodeDa { get; set; }
public string FaxcodeDa { get; set; }
public string WebsiteAddress { get; set; }
public string EmailAdd { get; set; }
public string TablighatPic { get; set; }
[Required]
public int Citycode { get; set; }
[ForeignKey ("Citycode")]
public Lcity City { get; set; }
[Required]
public int IDReshteh { get; set; }
[ForeignKey("IDReshteh")]
public RFaaliat Reshteh { get; set; }
}
My controller:
//If IdType=1 then user clicked on Reshteh But if IdType=2 then user clicked on city
public ActionResult selVahedList(int IdType, int IdChoose)
{
ViewBag.ChooseItem = IdChoose;
ViewBag.IdType = IdType;
if (IdType == 1)
ViewBag.ResultList = Dbcon.Lcitys.ToList();
else
ViewBag.ResultList = Dbcon.RFaaliats.ToList();
return View();
}
public ActionResult selVahedListAjax(int IdReshte,int IdCity )
{
ViewBag.Reshteh = IdReshte;
var res = Dbcon.TaavoniInfos.Where(m => m.IDReshteh == IdReshte && m.Citycode ==?);//Idont know what should put here
return PartialView(res);
}
my problem is i cant get and pass selected item in drop down and update data in page. please help me.
thanks a lot
I want to set the default selected value in DropDownListFor when the element is created
Data model:
public class CascadingDropDownModel
{
public int? PreviousFirstListId { get; set; }
public int? SelectedFirstListId { get; set; }
public int? SelectedSecondListId { get; set; }
public string FirstTextHint { get; set; }
public string SecondTextHint { get; set; }
public IList<DropDownElement> FirstDropDownData { get; set; }
public IList<DropDownElement> SecondDropDownData { get; set; }
public CascadingDropDownModel()
{
FirstDropDownData = new List<DropDownElement>();
SecondDropDownData = new List<DropDownElement>();
}
}
Partial view (doesn't work):
#Html.DropDownListFor(
m => m.SelectedFirstListId,
new SelectList(Model.FirstDropDownData, "Id", "Name", Model.SelectedFirstListId),
Model.FirstTextHint)
Partial view (work):
#Html.DropDownListFor(
m => m.SelectedFirstListId,
new SelectList(Model.FirstDropDownData, "Id", "Name", 5),
Model.FirstTextHint)
Please, tell me what the problem is?
I am using code-first with EF. Validation seems to be failing on a dropdown list with the error System.NullReferenceException: Object reference not set to an instance of an object. This happens when I save a record and I intentionally leave controls empty to test the validation. It happens even if the dropdown list itself has a selection.
here is part of my view:
<div class="editor">
#Html.LabelFor(model => model.EmployeeID)
#Html.DropDownListFor(model => model.EmployeeID, new SelectList(Model.Employees, "Value", "Text"))
#Html.ValidationMessageFor(model => model.EmployeeID)
</div>
If I use a textbox validation works:
<div class="editor">
#Html.LabelFor(model => model.EmployeeID)
#Html.TextBoxFor(model => model.EmployeeID, new { style = "width: 250px;" })
#Html.ValidationMessageFor(model => model.EmployeeID)
</div>
here are my Create controller actions:
public ActionResult Create()
{
var e = iEmployeeRepository.GetAll();
var visitorLogViewModel = new VisitorLogViewModel
{
Employees = e.Select(x => new SelectListItem
{
Value = x.EmployeeID,
Text = x.EmployeeName
})
};
return View(visitorLogViewModel);
}
//
// POST: /VisitorLogs/Create
[HttpPost]
public ActionResult Create(VisitorLog visitorlog)
{
if (ModelState.IsValid) {
iVisitorlogRepository.Add(visitorlog);
iVisitorlogRepository.Save();
return RedirectToAction("Search");
} else {
return View();
}
}
And my viewmodel:
public class VisitorLogViewModel
{
public int Id { get; set; }
[Display(Name = "Visitor Name")]
public string VisitorName { get; set; }
[Display(Name = "Company Name")]
public string CompanyName { get; set; }
[Required(ErrorMessage = "Employee ID is required.")]
[Display(Name = "GB Employee")]
public string EmployeeID { get; set; }
[Display(Name = "Visit Reason")]
public string VisitReason { get; set; }
[Display(Name = "Time In")]
public DateTime TimeIn { get; set; }
[Display(Name = "Time Out")]
public DateTime TimeOut { get; set; }
[Display(Name = "GB Employee")]
public string EmployeeName { get; set; }
public IEnumerable Employees { get; set; }
public VisitorLog VisitorLog { get; set; }
}
And my partial model for validation:
[MetadataType(typeof(VisitorLogMetaData))]
public partial class VisitorLog
{
}
public class VisitorLogMetaData
{
[Required(ErrorMessage = "Visitor name is required.")]
[MaxLength(128)]
public string VisitorName { get; set; }
[Required(ErrorMessage = "Company name is required.")]
[MaxLength(128)]
public string CompanyName { get; set; }
[Required(ErrorMessage = "GB Employee is required.")]
[MaxLength(128)]
public string EmployeeID { get; set; }
[Required(ErrorMessage = "Visit reason is required.")]
[MaxLength(254)]
public string VisitReason { get; set; }
[Required(ErrorMessage = "Time in is required.")]
public DateTime TimeIn { get; set; }
[Required(ErrorMessage = "Time out reason is required.")]
public DateTime TimeOut { get; set; }
}
And finally my model:
public partial class VisitorLog
{
public int Id { get; set; }
public string VisitorName { get; set; }
public DateTime TimeIn { get; set; }
public DateTime TimeOut { get; set; }
public string CompanyName { get; set; }
public string EmployeeID { get; set; }
public string VisitReason { get; set; }
// Navigation properties
[ForeignKey("EmployeeID")]
public virtual Employee Employee { get; set; }
}
I read there was a bug in MVC razor regarding the DropDownListFor but I don't know if that applies in my situation. I have tried some of the solutions and they didn't work for me. I am using 4.5 framework.
Thanks.
Edit:
One thing I noticed, when I submit the page and the error stops on the dropdown element:
#Html.DropDownListFor(model => model.EmployeeID, new SelectList(Model.Employees, "Value", "Text"))
the Model in Model.Employees is null, like it is loosing its binding when the page is submited.
Ok, I did some fundemental changes to my classes. First, I changed the post method in my controller. Previously I was passing the model to the post, now I am passing the view model and mapping it to the model before saving via my repository:
//
// POST: /VisitorLogs/Create
[HttpPost]
public ActionResult Create(VisitorLogViewModel visitorLogViewModel)
{
var e = iEmployeeRepository.GetAll();
VisitorLog visitorLog = new VisitorLog();
visitorLog.Id = visitorLogViewModel.Id;
visitorLog.VisitorName = visitorLogViewModel.VisitorName;
visitorLog.CompanyName = visitorLogViewModel.CompanyName;
visitorLog.EmployeeID = visitorLogViewModel.EmployeeID;
visitorLog.TimeIn = visitorLogViewModel.TimeIn;
visitorLog.TimeOut = visitorLogViewModel.TimeOut;
visitorLog.VisitReason = visitorLogViewModel.VisitReason;
visitorLogViewModel.Employees = new SelectList(e, "EmployeeID", "EmployeeName");
if (ModelState.IsValid)
{
iVisitorlogRepository.Add(visitorLog);
iVisitorlogRepository.Save();
return RedirectToAction("Search");
} else {
return View(visitorLogViewModel);
}
}
Next, I had to add the "required" attribute (validation) to the viewmodel:
public class VisitorLogViewModel
{
public int Id { get; set; }
[Required(ErrorMessage = "Visitor name is required.")]
[MaxLength(128)]
[Display(Name = "Visitor Name")]
public string VisitorName { get; set; }
[Required(ErrorMessage = "Company name is required.")]
[MaxLength(128)]
[Display(Name = "Company Name")]
public string CompanyName { get; set; }
[Required(ErrorMessage = "GB Employee is required.")]
[MaxLength(16)]
[Display(Name = "GB Employee")]
public string EmployeeID { get; set; }
[Required(ErrorMessage = "Visit Reason is required.")]
[MaxLength(254)]
[Display(Name = "Visit Reason")]
public string VisitReason { get; set; }
[Display(Name = "Time In")]
public DateTime TimeIn { get; set; }
[Display(Name = "Time Out")]
public DateTime TimeOut { get; set; }
[Display(Name = "GB Employee")]
public string EmployeeName { get; set; }
public SelectList Employees { get; set; }
}
Not sure if that is the most effcient method but everything works now. If someone sees something wrong with this method let me know.
I am having trouble with Model.IsValid on a property that's not required.
Here's the code.
BeginForm in the Edit.cshtml file
#using (Html.BeginForm("Edit", "Member", FormMethod.Post, new { enctype = "multipart/formdata" }))
{
#Html.Partial("_MemberForm", Model.Member)
}
MemberEditViewModel: (used for the Edit.cshtml file)
public class MemberEditViewModel
{
public MemberFormModel Member { get; set; }
}
MemberFormModel:
public class MemberFormModel : ICreateMemberCommand, IValidatableObject
{
public int Id { get; set; }
[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }
[Required]
public string SocialSecurityNumber { get; set; }
[Required]
public int PinCode { get; set; }
[Required]
public char Gender { get; set; }
public string Email { get; set; }
[Required]
public string Address { get; set; }
[Required]
public string ZipCode { get; set; }
[Required]
public string ZipAddress { get; set; }
public string Phone { get; set; }
public string Phone2 { get; set; }
[Required]
public string City { get; set; }
[Required]
public int CountryId { get; set; }
//not required (but still displaying error it's required)
public Membership Membership { get; set; }
// not required (displaying error it's required)
public PunchCard PunchCard { get; set; }
public bool IsActive { get; set; }
block of _MemberForm.cshtml (partial)
<fieldset>
<dl>
<dt>#Html.LabelFor(m => m.Id)</dt>
<dd>#Html.TextBoxFor(m => m.Id, new { disabled = "disabled", #readonly = "readonly" })</dd>
<dt>#Html.LabelFor(m => m.PinCode)</dt>
<dd>#Html.EditorFor(m => m.PinCode)</dd>
<!-- problem with membership, maybe with the .FromData/ToDate ? -->
<dt>#Html.LabelFor(m => m.Membership)</dt>
<dd>#Html.EditorFor(m => m.Membership.FromDate, new { #name = "Membership" }) -
#Html.EditorFor(m => m.Membership.ToDate, new { #name="Membership"})</dd>
<!-- problem with punch card, maybe with the .Times ? -->
<dt>#Html.LabelFor(m => m.PunchCard)</dt>
<dd>#Html.EditorFor(m => m.PunchCard.Times, new { #name = "PunchCard" })</dd>
</dl>
</fieldset>
The MemberController Edit Action
// POST: /Members/10002/Edit
[HttpPost]
public ActionResult Edit(FormCollection formValues, MemberFormModel memberForm)
{
var errors = ModelState.Values.SelectMany(v => v.Errors);
if(IsSaveOperation(formValues)){
if(TryUpdateMember(memberForm)){
return RedirectToAction("Details", "Member", new {id = memberForm.Id});
}
}
var mm = new MemberEditViewModel{ Member = memberForm };
return View(mm);
}
Membership.cs
public class Membership
{
public Membership(){ /* empty constructor */}
public Membership(int id, int memberId, DateTime fromDate, DateTime toDate)
{
Id = id;
MemberId = memberId;
FromDate = fromDate;
ToDate = toDate;
}
public int Id { get; set; }
public int MemberId { get; set; }
[DataType(DataType.Date)]
public DateTime FromDate { get; set; }
[DataType(DataType.Date)]
public DateTime ToDate { get; set; }
}
PunchCard.cs
public class PunchCard
{
public PunchCard() { /* empty constructor */ }
public PunchCard(int memberId, int times, DateTime createdDate, DateTime modifiedDate)
{
this.MemberId = memberId;
this.Times = times;
this.CreatedDate = createdDate;
this.ModifiedDate = modifiedDate;
}
public int Id { get; set; }
public int MemberId { get; set; }
public int Times { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime ModifiedDate { get; set; }
}
You see I dont have any [Required] attribute, neither in the MemberFormModel. So how come those two are Required ? Its a mystery.
You should not be using both the disabled and readonly attribute on your textbox:
#Html.TextBoxFor(m => m.Id, new { disabled = "disabled", #readonly = "readonly" })
I guess the disabled attribute takes precedence and the value of the Id is never sent to the server when you submit the form. That's why you get a modelstate error. Because your id property is required. Now you will be probably tell me that it is not decorated with the [Required] attribute but this doesn't matter. Since you have declared it as a non-nullable integer it is implicitly required and the framework automatically makes it required. If you don't want this to happen you should declare it as a nullable integer.
So back to your view, if you want to only display id, without allowing the user to modify it, use readonly:
#Html.TextBoxFor(m => m.Id, new { #readonly = "readonly" })
Obviously don't think that if you made a textbox readonly, the user cannot modify it. The normal user will not. But a hacker could always put whatever value he wants in this textbox and forge a request. So absolutely do not rely on this as some sort of security or something.
I found many articles on this but still I don´t know how exactly to do this. I am trying to create my own blog engine, I have View for create article (I am using EF and Code first) and now I must fill number of category in which article should be add but I want to change it to dropdownlist with names of categories. My model looks this:
public class Article
{
public int ArticleID { get; set; }
[Required]
public string Title { get; set; }
[Required]
public int CategoryID { get; set; }
public DateTime Date { get; set; }
[Required()]
[DataType(DataType.MultilineText)]
[AllowHtml]
public string Text { get; set; }
public virtual Category Category { get; set; }
public IEnumerable<SelectListItem> Categories { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
public class Category
{
public int CategoryID { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
I know I must use Enum (or I think) but I am not exactly sure how. I don´t know which tutorial from that I found is best for me.
Edit:
Thanks for your answers but I found something else. I am trying this:
This is my model:
public class Article
{
[Key]
public int ArticleID { get; set; }
[Display(Name = "Title")]
[StringLength(30, MinimumLength = 5)]
[Required]
public string Title { get; set; }
public DateTime Date { get; set; }
public int CategoryID { get; set; }
[Required()]
[DataType(DataType.MultilineText)]
[AllowHtml]
public string Text { get; set; }
public Category Category { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public IEnumerable<Category> Categories { get; set; }
}
public class Category
{
[Key]
public int CategoryId { get; set; }
[Required]
public string CategoryName { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
This is my controller to create article:
public ActionResult Vytvorit()
{
IEnumerable<Category> categories = GetCaregories();
var view = View(new Article() { Categories = categories });
view.TempData.Add("Action", "Create");
return view;
}
private static IEnumerable<Category> GetCaregories()
{
IEnumerable<Category> categories;
using (BlogDBContext context = new BlogDBContext())
{
categories = (from one in context.Categories
orderby one.CategoryName
select one).ToList();
}
return categories;
}
private Category GetCategory(int categoryID)
{
return db.Categories.Find(categoryID);
}
//
// POST: /Clanky/Vytvorit
[HttpPost]
public ActionResult Vytvorit(Article newArticle)
{
try
{
if (newArticle.CategoryID > 0)
{
newArticle.Category = GetCategory(newArticle.CategoryID);
}
if (TryValidateModel(newArticle))
{
db.Articles.Add(newArticle);
db.SaveChanges();
return RedirectToAction("Index");
}
else
{
newArticle.Categories = GetCaregories();
var view = View(newArticle);
view.TempData.Add("Action", "Create");
return view;
}
}
catch
{
return View();
}
}
And this is part of my view:
#Html.DropDownListFor(model => model.CategoryID, new SelectList(Model.Categories,"CategoryID","CategoryName"))
#Html.ValidationMessageFor(model => model.CategoryID)
I have problem with NullReferenceExeption but I don´t know why. Can I do it this way? It looks very easy for me.
Your model seems quite strange. It contains properties such as CategoryID and Category which seem redundant. It also contains a SelectListItem collection property called Categories. So, is this a model or a view model? It looks quite messed up. Let's assume it's a model. In this case it would more likely look something like this:
public class Article
{
public int ArticleID { get; set; }
[Required]
public string Title { get; set; }
public DateTime Date { get; set; }
[Required()]
[DataType(DataType.MultilineText)]
[AllowHtml]
public string Text { get; set; }
public virtual Category Category { get; set; }
public IEnumerable<Category> Categories { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
public class Category
{
public int CategoryID { get; set; }
[Required]
public string Name { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
Now that the model is clear we could define a view model which will be passed to the view. A view model is a class which is specifically designed for the view. So depending on what you intend to put in this view you define it in this view model. So far you have talked only about a drop down, so let's do it:
public class ArticleViewModel
{
public int SelectedCategoryId { get; set; }
public IEnumerable<SelectListItem> Categories { get; set; }
}
and then we have a controller:
public class ArticlesController: Controller
{
private readonly IArticlesRepository _repository;
public ArticlesController(IArticlesRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
Article article = _repository.GetArticle();
ArticleViewModel viewModel = Mapper.Map<Article, ArticleViewModel>(article);
return View(viewModel);
}
}
So the controller uses a repository to fetch the model, maps it to a view model (in this example I use AutoMapper) and passes the view model to the view which will take care of showing it:
#model AppName.Models.ArticleViewModel
#using (Html.BeginForm())
{
#Html.DropDownListFor(
x => x.SelectedCategoryId,
new SelectList(Model.Categories, "Value", "Text"),
"-- Select category --"
)
<input type="submit" value="OK" />
}
I have gone through this as well and I have to agree that at first it seems odd (In my explanation I'm assuming you want to select one category only, but the process is very similar for a multi select).
Basically you need to perform 3 steps:
1:
You need two properties on your viewmodel
One will hold the selected category id (required for postback) and the other will a SelectList with all possible categories:
public class Article
{
public int ArticleID { get; set; }
public int CategoryID { get; set; }
public SelectList Categories { get; set; }
}
2:
Also before passing the viewmodel on to the view you need to initialize the SelectList (Best practivce is to prepare as much as possible before passing a model into the view):
new SelectList(allCategories, "CategoryID", "Name", selectedCategoryID)
3:
In the view you need to add a ListBox for the CategoryID property, but using the Categories property too fill the ListBox with values:
#Html.ListBoxFor(model => model.CategoryID , Model.Categories)
Thats it! In the post back action of the controller you will have the CategoryID set. You can do whatever you need to from there to persist things in your db.