How to edit List of objects in a model - c#

CustomCssFields is null when going back to controller. I already set a constructor but it is still the same. I found some similar question MVC Model with a list of objects as property but it almost has the same code as mine.
MODEL
public class CompanyModelView
{
public CompanyModelView()
{
CustomCssFields = new List<CompanyCssReferenceModelView>();
}
[BsonId]
public string _id { get; set; }
[BsonElement("CompanyName")]
[DisplayName("Company Name")]
public string CompanyName { get; set; }
[BsonElement("CompanyCode")]
[DisplayName("Company Code")]
public string CompanyCode { get; set; }
[BsonElement("CompanyConnectionString")]
[DisplayName("Company Connection String")]
public string CompanyConnectionString { get; set; }
[BsonElement("CargowiseVersion")]
[DisplayName("Cargowise Version")]
public string CargoWiseVersion { get; set; }
[BsonElement("CustomCssFields")]
[UIHint("CustomCssFields")]
public IList<CompanyCssReferenceModelView> CustomCssFields { get; set; }
}
public class CompanyCssReferenceModelView
{
[BsonElement("FieldName")]
public CssOptionEnum FieldName;
[BsonElement("FieldValue")]
public string FieldValue;
}
VIEW
here is the view.
#model WebTrackerModels.CompanyModels.CompanyModelView
<form asp-action="SaveCompany" enctype="multipart/form-data">
<div class="form-group">
<table class="table">
<thead>
<tr>
<th>
Field Name
</th>
<th>
Field Value
</th>
</tr>
</thead>
<tbody>
#{
for (int i = 0; i < Model.CustomCssFields.Count; i++)
{
<tr>
<td>
#Html.DisplayFor(model => model.CustomCssFields[i].FieldName)
</td>
<td>
#Html.TextBoxFor(model => model.CustomCssFields[i].FieldValue, new { #class = "form-control", type = "color", value = Model.CustomCssFields[i].FieldValue })
</td>
</tr>
}
}
</tbody>
</table>
</div>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-success" />
</div>
</form>

Related

How to solve "Name field is required" in ASP.NET MVC?

Iam getting the following error when posting the form with ProductVM fields:
This is the model being passed:
[BindProperties]
public class ProductVM
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public decimal Price { get; set; }
public int Quantity { get; set; } = 0;
public List<SelectListItem> Categories { get; set; }
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public List<SelectListItem> Suppliers { get; set; }
public int SupplierId { get; set; }
public string SupplierName { get; set; }
}
This is the form:
#model IEnumerable<ProductVM>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Price)
</td>
<td>
#Html.DisplayFor(modelItem => item.CategoryName)
</td>
<form asp-action="AddToCart">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="#item.Id">
<input type="hidden" asp-for="#item.Name">
<input type="hidden" asp-for="#item.Price">
<td>
<input asp-for="#item.Quantity" value="1" class="form-control" style="inline-size:100px">
<span asp-validation-for="#item.Quantity" class="text-danger"></span>
</td>
<td>
<input type="submit" id="addtocart" value="Add To Cart" class="btn btn-primary"/>
</td>
</form>
</tr>
}
Any ideas why the name field is throwing error even with the "input type="hidden" asp-for="#item.Name"" ?
foreach loop is not submiting data back, you have to use for loop
#foreach (var i=0, i< Model.Count; i++) {
.....
<input type="hidden" asp-for="#Model[i].Id">
<input type="hidden" asp-for="#Model[i].Name">
...
}

Pass ID from view of type IEnumerable using HTML Actionlink in Razor

I have two models "Computer" and "Computer Detail." From the Computer's Index page the user can click "View Details" for a given record which redirects to the Index of the Computer Detail and fetches all the records associated with that given "Computer ID" using the query string - That works fine
My problem is I want to have a "Create" link that carries this "Computer ID" (shown in view) and populates the Computer ID field on the Create form.
I used Model.First().ComputerID that worked to run the code with some test records but of course it doesn't work if records for the ComputerID is null.
View
#modelIEnumerable<MyApp.Models.ComputerDetail>
#{
ViewBag.Title = "Index";
}
<h2 class ="page-header">Computer Details</h2>
<div class ="col-lg-12">
<p>
#Html.ActionLink("Create New", "Create", "ComputerDetail", new {id = Model.First().ComputerID}, new { #class = "btn btn-default"})
</p>
<div class="panel panel-default">
<div class ="panel-body">
<table class ="table table-striped" id="dtaTable">
<thead class ="dataTableHead">
<tr>
<th>
#Html.DisplayNameFor(model => model.ComputerID)
</th>
<th>
#Html.DisplayNameFor(model => model.EmployeeID)
</th>
<th>
#Html.DisplayNameFor(model => model.StartDate)
</th>
<th>
#Html.DisplayNameFor(model => model.EndDate)
</th>
<th>
#Html.DisplayNameFor(model => model.Comments)
</th>
<th>Actions</th>
</tr>
</thead>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.ComputerID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Employee.FullName)
</td>
<td>
#Html.DisplayFor(modelItem => item.StartDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.EndDate)
</td>
<td>
#Html.DisplayFor(modelItem => item.Comments)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
#Html.ActionLink("Details", "Details", new { id=item.ID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
</table>
</div>
</div>
</div>
Controller
public ActionResult Index(int id)
{
var _FindComputerID = GetComputerDetails(id);
return View(_FindComputerID);
}
private List<ComputerDetail>GetComputerDetails(int id)
{
var FindComputerID = db.ComputerDetails.Where(cd => cd.ComputerID == id).Include
(cd => cd.Employee).OrderByDescending(cd => cd.ID);
return FindComputerID.ToList();
}
[HttpGet]
public ActionResult Create(int id)
{
ComputerDetail computerdetail = new ComputerDetail ();
computerdetail.ComputerID = id;
return View(computerdetail);
}
Model
public class ComputerDetail
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Required(ErrorMessage = "Please enter service tag")]
[Display(Name = "Service Tag")]
public int ComputerID { get; set; }
[Required(ErrorMessage = "Please select employee name")]
[Display(Name = "Employee Name")]
public int EmployeeID { get; set; }
[Required(ErrorMessage = "Please enter date")]
[Display(Name = "Date Bought")]
[DataType(DataType.Date)]
public DateTime StartDate { get; set; }
[Display(Name = "Date Bought")]
[DataType(DataType.Date)]
public DateTime? EndDate { get; set; }
public string Comments { get; set; }
//references
public virtual Assets.Computer Computer { get; set; }
public virtual Employee Employee { get; set; }
}
Two thing are happening here:
In the first place, if your view needs to get the ComputerID you may want to reflect this field in the ViewModel and not magically get it from the first item in the list.
public class ComputerDetailsViewModel
{
public int ComputerID {get; set;} // populate in the action directly
public IEnumerable<MyApp.Models.ComputerDetail> Items {get; set;}
}
You really want to go that route, you should use the nullable operator for better error handling figure it out what happens when the ComputerID is null.
#Html.ActionLink("Create New", "Create", "ComputerDetail", new {id = Model.FirstOrDefault()?.ComputerID ?? 0 /*Null case*/}, new { #class = "btn btn-default"})
Hope this help!

C# , MVC , Instead table html

I have this model :
public class CoursesTeacher
{
public int Id { get; set; }
public string FullName { get; set; }
public IEnumerable<string> CourseName { get; set; }
public IEnumerable<int> CourseId { get; set; }
}
I would like to create an Instead table html by razor.
The teacher has a multiple courses.
like that
that
I wrote this code :
<table class="table table-bordered">
<tr>
<th>
#Html.ActionLink("Teacher Name", "RequestsTeachers")
</th>
<th>
#Html.ActionLink("Corese Name", "RequestsTeachers")
</th>
<th>
Edit
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td rowspan="#item.CourseName.Count()">
#Html.DisplayFor(modelItem => item.FullName)
</td>
#foreach (var courseName in item.CourseName)
{
<td>
#Html.DisplayFor(modelItem => courseName)
</td>
}
#foreach (var courseId in item.CourseId)
{
<td>
<div class="pull-right">
#Html.NoEncodeActionLink("<span class='glyphicon glyphicon-pencil'></span>", "Edit", "EditFinancial", "Control", routeValues: new { courseId = courseId }, htmlAttributes: new { data_modal = "", #class = "btn btn-default" })
</div>
</td>
}
</tr>
}
but created not correct :
correct
how to create correct ?
I'd go and create a viewmodel to represent the info for a course:
public class CourseInfoModel
{
public string CourseName { get; set; }
public int CourseId { get; set; }
public bool IsFirstCourse { get; set; }
}
Then in the model class, create a readonly property to get the data in a more suitable way:
public class CoursesTeacher
{
public int Id { get; set; }
public string FullName { get; set; }
public IEnumerable<string> CourseName { get; set; }
public IEnumerable<int> CourseId { get; set; }
public IList<CourseInfoModel> Courses
{
get
{
if (CourseName == null || CourseId == null || CourseId.Count() != CourseName.Count())
throw new Exception("Invalid data"); //courses and ids must have the same number of elements
var list = new List<CourseInfoModel>();
for (int i = 0; i < CourseName.Count(); i++)
{
list.Add(new CourseInfoModel
{
IsFirstCourse = i == 0,
CourseId = CourseId.ElementAt(i),
CourseName = CourseName.ElementAt(i),
});
}
return list;
}
}
}
Now in the view is easy to render the table the way you want:
#model IEnumerable<MvcTable.Models.CoursesTeacher>
<table class="table table-bordered">
<tr>
<th>
#Html.ActionLink("Teacher Name", "RequestsTeachers")
</th>
<th>
#Html.ActionLink("Course Name", "RequestsTeachers")
</th>
<th>
Edit
</th>
</tr>
#foreach (var item in Model)
{
foreach (var courseItem in item.Courses)
{
<tr>
#if (courseItem.IsFirstCourse)
{
<td rowspan="#item.Courses.Count">
#Html.DisplayFor(modelItem => item.FullName)
</td>
}
<td>
#Html.DisplayFor(modelItem => courseItem.CourseName)
</td>
<td>
<div class="pull-right">
<span class='glyphicon glyphicon-pencil'></span>
</div>
</td>
</tr>
}
}
</table>
Instead of keeping the CourseName and CourseIds to seperate lists. Why not create a class to represent a course and use that ?
public class CourseVm
{
public int Id { set; get;}
public string Name { set; get;}
}
public class CoursesTeacher
{
public int Id { set;get;}
public string FullName { set;get;}
public List<CourseVm> Courses { set;get;}
}
and in the view which is strongly typed to a collection CoursesTeacher
#model IEnumerable<CoursesTeacher>`
<table>
#foreach(var t in Model)
{
<tr>
<td>#t.FullName</td>
<td>
<table>
#foreach(var c in t.Courses)
{
<tr><td>#c.Name</td>
<td><button>Some button</button></td>
</tr>
}
</table>
</td>
</tr>
}
</table>

C# Entity Overview Table of one to many checkbox

I can't seem to find how to build a proper solution for a one to many checkbox.
So what do i have :
I have an article and an admin user can set user rights to that article.
So in my article right page you have an overview with all the users.
My article:
public partial class Artikel
{
public Artikel()
{
this.ArtikelLinks = new HashSet<ArtikelLink>();
this.ArtikelRights = new HashSet<ArtikelRight>();
}
public int id { get; set; }
public string code { get; set; }
public string naam { get; set; }
public virtual ICollection<ArtikelLink> ArtikelLinks { get; set; }
public virtual ICollection<ArtikelRight> ArtikelRights { get; set; }
}
My rights class
public partial class ArtikelRight
{
public int id { get; set; }
public System.Guid userId { get; set; }
public int artikelId { get; set; }
public bool hasRight { get; set; }
public virtual Artikel Artikel { get; set; }
}
How do i build my view? i tried several ways but i can't seem to save my data.
this is my rights view at the moment:
#using (Html.BeginForm()) {
<table width="90%" align="center" class="table table-striped">
<thead>
<tr>
<th align="left">Gebruiker</th>
<th align="left">Heeft toegang</th>
</tr>
</thead>
#Html.EditorFor(x => Model.ArtikelRights, "ArtikelRight")
</table>
<br />
<div class="pull-right">
<input type="submit" value="Opslaan" class="btn btn-sm beige" />
</div>
}
And this is my partial Artikel right view:
#model IEnumerable<GtiProducts.Models.ArtikelRight>
#foreach (var item in Model) {
<tr>
<td>
#Membership.GetUser(item.userId).UserName
</td>
<td>
#Html.EditorFor(x => item.hasRight)
</td>
</tr>
}
My save action is:
public ActionResult Rights(Artikel art)
{
repo.SaveChanges();
return View(art);
}
When i debug my art.ArtikelRights is null.
How can i fix this and what's the best solution to do this with the entity framework?
Rename the partial to make it an EditorTemplate- /Views/Shared/EditorTemplates/ArtikelRight.cshtml, then make the following modifications
#model GtiProducts.Models.ArtikelRight // not IEnumerable
<tr>
<td>
#Html.CheckBoxFor(m => m.hasRight)</td>
#Html.LabelFor(m => m.hasRight, "....") // the users name?
#Html.HiddenFor(m > m.id) // or what ever property you need to identify the ArtikelRight.cshtml
</td>
</tr>
Then in the main view
<tbody>
#Html.EditorFor(x => Model.ArtikelRights)
</tbody>
This will correctly name you controls with indexers so they can be bound to your model on post back, for example
<input type="checkbox" name="ArtikelRights[0].hasRight" ...>
<input type="checkbox" name="ArtikelRights[1].hasRight" ...>
Side note: You should not be using #Membership.GetUser(item.userId).UserName in the view. Instead create a view model with only those properties you need in the view (which appears to be id and hasright, and include a property for the users display name (and populate it in the controller).

Validation not worked on kendoUI multiselect

I am creating a form by using MVC4.
Here i used kendo multiselect and try to validate through model annotation.
My Code is :
#model WEBAPP._2012.Models.DeviceInventory.DeviceTechnologyModel
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
#using (Ajax.BeginForm("Create", "Device_TechnologyInventory", new AjaxOptions { HttpMethod = "POST", OnSuccess = "onSuccessAddTechnology" })) { #Html.ValidationSummary(true)
<table width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td>
<#Html.LabelFor(model=>model.Name)</td>
<td class="editor-field" width="160px;">
#Html.EditorFor(model => model.Name) #Html.ValidationMessageFor(model => model.Name)
</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.Alias)</td>
<td class="editor-field">
#Html.EditorFor(model => model.Alias) #Html.ValidationMessageFor(model => model.Alias)
</td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.Vendors)/td>
<td class="editor-field">
#(Html.Kendo().MultiSelectFor(model=>model.Vendors) .Name("Vendors").Placeholder("Select") .BindTo(new SelectList(ViewBag.VendorList, "Value", "Text")) ) #Html.ValidationMessageFor(model => model.Vendors)
</td>
</tr>
</table>
<div class="CreateWrp">
<input type="submit" value="Create " class="btn-success"/>
<input type="reset" value="Reset " class="btn-primary" />
</div>
My model is :
public class DeviceTechnologyModel
{
public int Id { get; set; }
[Required(ErrorMessage = "*")]
[Display(Name = "Device Technology")]
public string Name { get; set; }
[Required(ErrorMessage = "*")]
[Display(Name = "Alias")]
public string Alias { get; set; }
[Required(ErrorMessage = "*")]
[Display(Name = "Device vendors")]
public List<string> Vendors { get; set; }
}
When i clicked on Submit button validation error message are appear on both "Name" and "Alias" field but not on field "Vendors".
I do not want to use javascript validation.
You need to validate the Value not a list object.
You may need to make below changes in your model:
public class DeviceTechnologyModel
{
public int Id { get; set; }
[Required(ErrorMessage = "*")]
[Display(Name = "Device Technology")]
public string Name { get; set; }
[Required(ErrorMessage = "*")]
[Display(Name = "Alias")]
public string Alias { get; set; }
[Required]
[Required(ErrorMessage = "*")]
[Display(Name = "Device vendors")]
public int VendorId { get; set; }
public List<string> Vendors { get; set; }
}
In your View:
<tr>
<td>#Html.LabelFor(model => model.Vendors)/td>
<td class="editor-field">
#(Html.Kendo().MultiSelectFor(model=> model.VendorId)
.Name("Vendors").Placeholder("Select")
.BindTo(new SelectList(ViewBag.VendorList, "Value", "Text")))
#Html.ValidationMessageFor(model => model.VendorId)
</td>
</tr>
Make sure when you submit the Form the VendorId property holds any value or not.
If it has nothing the validation should work.
Hope it helps.

Categories

Resources