ASP.NET MVC empty KeyValuePair into Controller - asp.net

I have an Model like KeyValuePair<Book, List<Author>>, after saving changes to controller comes empty model. To Edit(int id) comes Id of Book.
To this method need to get KeyValuePair filled, but it comes empty. Help please.
[HttpPost]
public ActionResult Edit(KeyValuePair<Book, List<Author>> data)
Controller
public class HomeController : Controller
{
static ViewModelAuthorsBooks data = new ViewModelAuthorsBooks();
static Dictionary<Book, List<Author>> tempDict = new Dictionary<Book, List<Author>>();
public ActionResult Index()
{
data = new ViewModelAuthorsBooks();
data.dictionary = new Dictionary<Book, List<Author>>();
List<Author> temp = new List<Author>();
Book book1 = new Book
{
Id = 0,
Name = "Book1",
Genre = "Genre1",
Description = "DescriptionDescription",
Price = 22.42M
};
Author author = new Author
{
Id = 0,
Name = "Name1",
Surname = "Surname1",
SecondName = "Secondname1"
};
temp.Add(author);
Author author2 = new Author
{
Id = 1,
Name = "Name2",
Surname = "Surname2",
SecondName = "Secondname2"
};
temp.Add(author2);
data.dictionary.Add(book1, temp);
temp = new List<Author>();
Book book2 = new Book
{
Id = 1,
Name = "Book2",
Genre = "Genre2",
Description = "DescriptionDescription2",
Price = 44.44M
};
Author author3 = new Author
{
Id = 2,
Name = "Name3",
Surname = "Surname3",
SecondName = "Secondname3"
};
temp.Add(author3);
data.dictionary.Add(book2, temp);
tempDict = data.dictionary;
return View(data.dictionary);
}
public ActionResult Edit(int id)
{
var model = tempDict.FirstOrDefault(x => x.Key.Id == id);
return View(model);
}
[HttpPost]
public ActionResult Edit(KeyValuePair<Book, List<Author>> data)
{
if (ModelState.IsValid)
{
return RedirectToAction("Index");
}
else
{
return View(data);
}
}
}
Classes
public class Book
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Description { get; set; }
public string Genre { get; set; }
}
public class Author
{
public int Id { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string SecondName { get; set; }
}
public class ViewModelAuthorsBooks
{
public Dictionary<Book,List<Author>> dictionary { get; set; }
}
Views/Index
#using KeyValuePairTest.Models
#model IEnumerable<KeyValuePair<Book,List<Author>>>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<div class="panel panel-default">
<div class="panel-heading">
Books List
</div>
<div class="panel-body">
<table class="table table-striped table-condensed table-bordered">
<tr>
<th class="text-center">
#Html.DisplayNameFor(x => x.Key.Id)
</th>
<th class="text-center">
#Html.DisplayNameFor(x => x.Key.Name)
</th>
<th class="text-center">
#Html.DisplayNameFor(x => x.Key.Genre)
</th>
<th class="text-right">
#Html.DisplayNameFor(x => x.Key.Price)
</th>
<th class="text-center">
Action
</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td class="text-right">
#item.Key.Id
</td>
<td>
#Html.ActionLink(item.Key.Name, "Edit", new { item.Key.Id })
</td>
<td>
#Html.DisplayFor(modelItem => item.Key.Genre)
</td>
<td class="text-right">
#item.Key.Price.ToString("# USD")
</td>
<td class="text-center">
#using (Html.BeginForm("Delete", "Admin"))
{
#Html.Hidden("id", item.Key.Id)
<input type="submit" class="btn btn-default btn-xs" value="Remove" />
}
</td>
</tr>
}
</table>
</div>
<div class="panel-footer">
#Html.ActionLink("Add", "Create", null, new { #class = "btn btn-default" })
</div>
</div>
Views/Edit
#using KeyValuePairTest.Models
#model KeyValuePair<Book, List<Author>>
#{
ViewBag.Title = "Edit";
}
<div class="panel">
<div class="panel-heading">
<h5>Edit Book: #Model.Key.Name</h5>
</div>
#using (Html.BeginForm("Edit", "Home", FormMethod.Post, new { app = #Model }))
{
<div class="panel-body">
#Html.HiddenFor(b => b.Key.Id)
<div class="form-group">
<label>Name:</label>
#Html.TextBoxFor(x => x.Key.Name, new { #class = "form-control" })
<input type="text" name="m" />
<label>Genre:</label>
#Html.TextBoxFor(x => x.Key.Genre, new { #class = "form-control" })
<label>Authors:</label>
#foreach (var author in Model.Value)
{
<label>Name</label>
#Html.TextBoxFor(x => author.Name);
<label>Surname</label>
#Html.TextBoxFor(x => author.Surname);
<label>Second name</label>
#Html.TextBoxFor(x => author.SecondName);
<p></p>
}
<label>Description:</label>
#Html.TextAreaFor(x => x.Key.Description, new { #class = "form-control", rows = 5 })
<label>Price:</label>
#Html.TextBoxFor(x => x.Key.Price, new { #class = "form-control" })
</div>
</div>
<div class="panel-footer">
<input type="submit" value="Save" class="btn btn-primary" />
#Html.ActionLink("Cancel", "Index", null, new { #class = "btn btn-default" })
</div>
}
</div>
Dictionary contains keys and values
In edit we see, that dictionary has values, they shown
Change value of Book name
Null

Thank's all for help, I find a solution
public class ViewModelUpdated
{
public Book book { set; get; }
public List<Author> lstAuthors { set; get; }
}
Just don't do a dictionary that's all :3

Related

Dropdown Data Binding Problem in ASP.NET Core 6 MVC

I am using SelectListItem in the controller for binding my dropdown data. All the dropdown options are showing perfectly in the dropdown list, but when I try to save, the problem occurs. It's not adding the dropdown options data rather than its adding dropdown data's id.
All the related models, controller and views are shown here:
BuyerSelectList model class:
public class BuyerSelectList
{
[Key]
public int Id { get; set; }
[DisplayName("BUYER")]
public string Buyer { get; set; }
}
ItemSelectList model class:
public class ItemSelectList
{
[Key]
public int Id { get; set; }
[DisplayName("ITEM")]
public string Item { get; set; }
}
BTBNewLien2 model class:
public class BTBNewLien2
{
public int Id { get; set; }
[Required]
[DisplayName("Buyer")]
public int BuyerSelectListId { get; set; }
[ForeignKey("BuyerSelectListId")]
[ValidateNever]
public BuyerSelectList BuyerSelectList { get; set; }
[Required]
[DisplayName("Item")]
public int ItemSelectListId { get; set; }
[ForeignKey("ItemSelectListId")]
[ValidateNever]
public ItemSelectList ItemSelectList { get; set; }
}
BTBNewLien2 controller (here I added all the data binding functionalities for my dropdown):
namespace CommercialCalculatorWeb.Areas.Admin.Controllers
{
public class BTBNewLien2Controller : Controller
{
private readonly IUnitOfWork _unitOfWork;
public BTBNewLien2Controller(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public IActionResult Index()
{
IEnumerable<BTBNewLien2> objBTBNewLienList = _unitOfWork.BTBNewLien2.GetAll();
return View(objBTBNewLienList);
}
public IActionResult Create()
{
BTBNewLien2 btbNewLien2 = new();
IEnumerable<SelectListItem> BuyerSelectList = _unitOfWork.Buyer.GetAll().Select(
c => new SelectListItem
{
Text = c.Buyer,
Value = c.Id.ToString()
});
IEnumerable<SelectListItem> ItemSelectList = _unitOfWork.Item.GetAll().Select(
c => new SelectListItem
{
Text = c.Item,
Value = c.Id.ToString()
});
ViewBag.BuyerSelectList = BuyerSelectList;
ViewBag.ItemSelectList = ItemSelectList;
return View(btbNewLien2);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(BTBNewLien2 obj)
{
if (ModelState.IsValid)
{
_unitOfWork.BTBNewLien2.Add(obj);
_unitOfWork.Save();
TempData["success"] = "Row Created Successfully!";
return RedirectToAction("Index");
}
return View(obj);
}
}
}
BTBNewLien2 create view:
#model CommercialCalculator.Models.BTBNewLien2
#{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>BTBNewLien2</h4>
<hr />
<div class="row ml-6">
<div class="col-md-4">
<form asp-action="Create">
<div class="form-group">
<label asp-for="BuyerSelectListId" class="control-label">Buyer</label>
<select asp-for="BuyerSelectListId" asp-items="ViewBag.BuyerSelectList" class="form-control">
<option disabled selected>--Select Buyer--</option>
</select>
</div>
<div class="form-group">
<label asp-for="ItemSelectListId" class="control-label">Item</label>
<select asp-for="ItemSelectListId" asp-items="ViewBag.ItemSelectList" class="form-control">
<option disabled selected>--Select Item--</option>
</select>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
BTBNewLien2 index view:
#model IEnumerable<CommercialCalculator.Models.BTBNewLien2>
#{
ViewData["Title"] = "Index";
}
<table class="table table-bordered table-hover table-sm align-middle m-0" id="header">
<tr class="m-0" style="text-align:center;background-color: #17A2B8">
<th width="20%">
#Html.DisplayNameFor(model => model.BuyerSelectList)
</th>
<th>
#Html.DisplayNameFor(model => model.ItemSelectList)
</th>
</tr>
#foreach (var BTBNewLien2 in Model)
{
<tr class="m-0">
<td>
#Html.DisplayFor(modelItem => BTBNewLien2.BuyerSelectList)
</td>
<td>
#Html.DisplayFor(modelItem => BTBNewLien2.ItemSelectList)
</td>
</tr>
}
</table>
Try this way:
#Html.DropDownList("ItemSelectListId", new SelectList(ViewBag.ItemSelectListId, "Text", "Text"), "-- Select Item --", new { required = true, #class = "form-control" })
In my code, it works fine:
Controller:
[HttpGet]
public IActionResult Create()
{
List<SelectListItem> test = new()
{
new SelectListItem { Value = "1", Text = "test1" },
new SelectListItem { Value = "2", Text = "test2" },
new SelectListItem { Value = "3", Text = "test3" },
new SelectListItem { Value = "4", Text = "test4" }
};
ViewBag.ItemSelectListId = test;
return View();
}
[HttpPost]
public IActionResult Create(Test test)
{
return View();
}
View:
<div class="row ml-6">
<div class="col-md-4">
<form asp-action="Create">
<div class="form-group">
<label asp-for="ItemSelectListId" class="control-label">Buyer</label>
#Html.DropDownList("ItemSelectListId", new SelectList(ViewBag.ItemSelectListId, "Text", "Text"), "-- Select Item --", new { required = true, #class = "form-control" })
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
Test Result:

How to Bind ViewModal to Dropdownlist in asp.net mvc

Suppose that we have a doctor with its weekday schedule. I want to display this weekday schedule and update it in the view. My WeekDay class looks like this:
public class WeekDay
{
public int Id { get; set; }
public string DayName { get; set; }
public string EightTen { get; set; }
public string TenTwelve { get; set; }
public string TwelveFourteen { get; set; }
public string FourteenSixteen { get; set; }
public int DoctorId { get; set; }
public Doctor Doctor { get; set; }
}
And Here is the ViewModel I've created to pass it to the view:
public class DoctorWeekDaysViewModel
{
public DoctorWeekDaysViewModel()
{
WeekDays = new List<WeekDay>();
}
public DoctorWeekDaysViewModel(IEnumerable<WeekDay> weekDay = null)
{
WeekDays = weekDay ?? new List<WeekDay>();
}
public IEnumerable<WeekDay> WeekDays { get; set; }
}
In the controller, the corresponding action will return 6 objects of WeekDay Class. In this situation, I've converted it into list and created a ViewModel and returned the ViewModel to the view:
public ActionResult EditTimeTable()
{
string username = Session["Username"].ToString();
var doctor = _context.Doctors.FirstOrDefault(a => a.Username.Equals(username));
var weekdays = _context.WeekDays.Include(a => a.Doctor).Where(a => a.DoctorId.Equals(doctor.Id)).ToList();
DoctorWeekDaysViewModel viewModel = new DoctorWeekDaysViewModel(weekdays);
return View(viewModel);
}
Then In the view I've took it and showed it this way:
#model ClinicWebApp.Models.ViewModel.DoctorWeekDaysViewModel
#using (Html.BeginForm(FormMethod.Post))
{
#Html.AntiForgeryToken()
<div class="calendar-main mb-30">
<div class="row">
#{
var listItems = new List<ListItem> {
new ListItem { Text = "استراحت", Value = "استراحت" },
new ListItem { Text = "ویزیت", Value = "ویزیت" },
new ListItem { Text = "نهار", Value = "نهار" },
new ListItem { Text = "صبحانه", Value = "صبحانه" },
new ListItem { Text = "خالی", Value = "خالی" },
};
}
<table class="mb-0 table table-hover table-dark">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">8 تا 10</th>
<th scope="col">10 تا 12</th>
<th scope="col">12 تا 14</th>
<th scope="col">14 تا 16</th>
</tr>
</thead>
<tbody>
#foreach (var weekday in Model.WeekDays)
{
<tr>
<th scope="row">#weekday.DayName</th>
<td>
#Html.DropDownListFor(model => weekday.EightTen, new SelectList(listItems), weekday.EightTen, new {#class = "custom-select my-1 mr-sm-2"})
</td>
<td>
#Html.DropDownListFor(model => weekday.TenTwelve, new SelectList(listItems), weekday.TenTwelve, new {#class = "custom-select my-1 mr-sm-2"})
</td>
<td>
#Html.DropDownListFor(model => weekday.TwelveFourteen, new SelectList(listItems), weekday.TwelveFourteen, new {#class = "custom-select my-1 mr-sm-2"})
</td>
<td>
#Html.DropDownListFor(model => weekday.FourteenSixteen, new SelectList(listItems), weekday.FourteenSixteen, new {#class = "custom-select my-1 mr-sm-2"})
</td>
</tr>
}
</tbody>
</table>
</div>
</div>
<footer class="bg-white p-4">
<div class="row">
<div class="col-md-12">
<div class="pull-left">
<button type="submit" class="btn btn-primary">save</button>
</div>
</div>
</div>
</footer>
}
The Output of This View is fine and everything is shown correctly:
Actual Html Output
But when I change the dropdownlist values and submit it to the corresponding action, The ViewModel will be null. here is my ActionResult:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult EditTimeTable(DoctorWeekDaysViewModel viewModel)
{
...
}
I think the problem is my viewModel or dropdownlist that configured incorrectly. please help me to solve this problem.
You should custome Name of dropdown to make it correctly.
#Html.DropDownListFor(model => weekday.EightTen, new SelectList(listItems), weekday.EightTen, new {#class = "custom-select my-1 mr-sm-2", Name = "WeekDays[0].EightTen"})
Note: Name = WeekDays[0].EightTen
0: Index, increase for each loop.
EightTen: Name of each property follow up your dropdown accordingly.
Instead of using foreach, use for loop to iterate the weekday list.
#for (var weekday=0; weekday < Model.WeekDays.Count; weekday++)
{
<tr>
<th scope="row">#weekday.DayName</th>
<td>
#Html.DropDownListFor(m => m.WeekDays.ElementAt(weekday).EightTen, new SelectList(listItems), Model.WeekDays.ElementAt(weekday).EightTen, new {#class = "custom-select my-1 mr-sm-2"})
</td>
<td>
#Html.DropDownListFor(m => m.WeekDays.ElementAt(weekday).TenTwelve, new SelectList(listItems), Model.WeekDays.ElementAt(weekday).TenTwelve, new {#class = "custom-select my-1 mr-sm-2"})
</td>
<td>
#Html.DropDownListFor(m => m.WeekDays.ElementAt(weekday).TwelveFourteen, new SelectList(listItems), Model.WeekDays.ElementAt(weekday).TwelveFourteen, new {#class = "custom-select my-1 mr-sm-2"})
</td>
<td>
#Html.DropDownListFor(m => m.WeekDays.ElementAt(weekday).FourteenSixteen, new SelectList(listItems), Model.WeekDays.ElementAt(weekday).FourteenSixteen, new {#class = "custom-select my-1 mr-sm-2"})
</td>
</tr>
}

MVC4 - Partial View List Model binding during Submit to Main view

I have view model which has a list of child models to render the partial view (below).
public class PRDocument
{
[Key]
[Column(Order = 0)]
public int Id { get; set; }
[DisplayName("Vendor Name")]
[Column(Order = 2)]
public int VendorId { get; set; }
public virtual ICollection<PRDocumentQuotation> PRDocumentQuotations { get; set; }
[NotMapped]
public List<PRDocumentQuotation> Quotations { get; set; }
public PRDocument()
{
Quotations = new List<PRDocumentQuotation>();
}
}
public class PRDocumentQuotation
{
[Key]
[Column(Order = 0)]
public int Id { get; set; }
[Required]
[Column(Order = 1)]
public int PRDocumentId { get; set; }
[Display(Name = "Uploaded File")]
[Column(Order = 2)]
public string FileName { get; set; }
}
And in the Partial View rendered like this.
#Html.Partial("_PRDocs", Model.Quotations)
Here is my partial view.
#model IEnumerable<JKLLPOApprovalApp.Models.PRDocumentQuotation>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.FileName)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
#Html.HiddenFor(modelItem => item.PRDocumentId)
<td>
#Html.DisplayFor(modelItem => item.FileName)
</td>
<td>
#Html.ActionLink("Delete", "Delete", new { id=item.Id })
</td>
</tr>
}
</table>
And the controller actions
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(PRDocument pRDocument)
{
if (ModelState.IsValid)
{
pRDocument.PRDocumentQuotations = pRDocument.Quotations;
db.tbl_PRDocuments.Add(pRDocument);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(pRDocument);
}
View Data Main View
#model JKLLPOApprovalApp.Models.PRDocument
#{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>PRDocument</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.VendorId, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.VendorId, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.VendorId, "", new { #class = "text-danger" })
</div>
</div>
#Html.Partial("_PRDocs", Model.Quotations)
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
What i want is to get the partial view data list (PRDocumentQuotation) into the Create action, bound with main model (PRDocument). How can i do this?
Interesting Question :)
The issue was that Model binding to list should have unique names. So the Generated HTML Should look like below:
<input id="Quotations_0__PRDocumentId" name="Quotations[0].PRDocumentId" type="hidden" value="0">
<input id="Quotations_1__PRDocumentId" name="Quotations[1].PRDocumentId" type="hidden" value="0">
The recommended solution is to use Editor Templates, Check this and this.
But I am giving alternate solution below using for loop to create unique names with index, taken from this post which faced same issue.
In Main View:
Pass The Main Model Instead
#Html.Partial("_PRDocs", Model)
Partial View:
#model JKLLPOApprovalApp.Models.PRDocument
<table class="table">
#if (Model.Quotations != null)
{
for (var i = 0; i < Model.Quotations.Count(); i++)
{
<tr>
<th>
#Html.DisplayNameFor(model => Model.Quotations[i].FileName)
</th>
<th></th>
</tr>
<tr>
#Html.HiddenFor(modelItem => Model.Quotations[i].PRDocumentId)
<td>
#Html.DisplayFor(modelItem => Model.Quotations[i].FileName)
</td>
<td>
#Html.ActionLink("Delete", "Delete", new { id = Model.Quotations[i].Id })
</td>
</tr>
}
}
</table>
Hope helps.

how to insert multiple rows database in asp.net core 2.1

I have one table which contains static data with 5 columns and 4 rows. I have another table which would accept input based on static table. I am trying to build a view with table where all field from static Db table is displayed and few text box so that user could fill in the data. But when I click on submit button no data is saved in second table. Can anyone help me with this. How could I submit multiple rows to database based on static database table.
Following are the codes:
View Model:
public class DBM2BillingViewModel
{
public List<DatabaseM2> databaseM2List { get; set; }
[Display(Name = "Items")]
public string Name { get; set; }
[Display(Name = "PO Item No.")]
public int POItemNo { get; set; }
[Display(Name = "Date of Effect")]
public DateTime DateOfEffect { get; set; }
[Display(Name = "Baseline Volume")]
public float baselineVolume { get; set; }
[Display(Name = "Billing Month")]
public string BillingMonth { get; set; }
[Display(Name = "Monthly Device Count")]
public float DeviceCount { get; set; }
}
**Controller**
//Get Method
public IActionResult Create()
{
DBM2BillingViewModel dbm2billingVM = new DBM2BillingViewModel();
dbm2billingVM.databaseM2List = _context.databaseM2s.ToList();
return View(dbm2billingVM);
}
//Post Method
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(DBM2BillingViewModel model)
{
foreach(var dbm2 in model.databaseM2List)
{
DeviceBilling addModel = new DeviceBilling();
addModel.Name = dbm2.Name;
addModel.TrackName = "Database M2";
addModel.POItemNo = dbm2.POItemNo;
addModel.DateOfEffect = dbm2.DateOfEffect;
addModel.baselineVolume = dbm2.BaselineVolume;
addModel.BillingMonth = model.BillingMonth;
addModel.DeviceCount = model.DeviceCount;
_context.deviceBillings.Add(addModel);
}
_context.SaveChanges();
return RedirectToAction(nameof(Index));
}
enter code here
View
#model FinancantPro.Models.DeviceCountModel.DBM2BillingViewModel
#{
ViewData["Title"] = "Create";
}
<div class="container">
<table class="table table-striped border">
<thead>
<tr class="table-info">
<th>#Html.DisplayName("Item Name")</th>
<th>#Html.DisplayName("PO Item No#")</th>
<th>#Html.DisplayName("Date Of Effect")</th>
<th>#Html.DisplayName("Baseline Volume")</th>
<th>#Html.DisplayName("Billing Month")</th>
<th>#Html.DisplayName("Device Count")</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.databaseM2List.Count; i++)
{
<tr>
<td>
#Html.HiddenFor(d => d.databaseM2List[i].Id)
#Html.DisplayFor(d => d.databaseM2List[i].Name)
</td>
<td>
#Html.DisplayFor(d => d.databaseM2List[i].POItemNo)
</td>
<td>
#Html.DisplayFor(d => d.databaseM2List[i].DateOfEffect)
</td>
<td>
#Html.DisplayFor(d => d.databaseM2List[i].BaselineVolume)
</td>
<td>
#Html.TextBoxFor(d => d.BillingMonth, new { #class = "form-control" })
</td>
<td>
#Html.TextBoxFor(d => d.DeviceCount, new { #class = "form-control" })
</td>
</tr>
}
</tbody>
</table>
<div class="form-group">
<input type="submit" class="btn btn-primary" value="Create" />
</div>
</div>
**************************
If I add list in View I am not able to resolve the Model

Making checkboxlist custom validation in asp.net mvc 5

I am developing an ASP.Net MVC 5 Web application and I am having some difficulties with making custom validation on Checkbox list. Validation I need that at least one checkbox must be checked
My ViewModel
public class EditUtilisateurViewModel
{
public long Id { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = " Required ")]
[Display(Name = "Login")]
public string UserName { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Required")]
[Display(Name = "Email")]
[EmailAddress (ErrorMessage = "Invalid Email")]
public string Email { get; set; }
[CheckOneSelected(ErrorMessage = "Please select role")]
public IEnumerable<System.Web.Mvc.SelectListItem> RolesList { get; set; }
}
My Controller
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Include = "Id,UserName,Email")] EditUtilisateurViewModel editUser, params string[] selectedRole)
{
if (ModelState.IsValid)
{
// ToDo ...
return RedirectToAction("Index");
}
}
My View
#model MyProject.Areas.Admin.Models.EditUtilisateurViewModel
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.HiddenFor(m => m.Id)
<table
<tbody>
< >
<th>
#Html.LabelFor(m => m.UserName)
</th>
<td>
#Html.TextBoxFor(m => m.UserName)
#Html.ValidationMessageFor(m => m.UserName)
</td>
</tr>
<tr>
<th>
#Html.LabelFor(m => m.Email)
</th>
<td>
#Html.TextBoxFor(m => m.Email, new { #class = "form-control", #disabled = "disabled" })
#*#Html.ValidationMessageFor(m => m.Email)*#
</td>
</tr>
<tr>
<th>#Html.Label("Roles")</th>
<td>
<span>
#foreach (var item in Model.RolesList)
{
#*<input type="checkbox" id="#item.Value" name="SelectedRole" value="#item.Value" checked="#item.Selected" class="checkbox-inline" />*#
#Html.CheckBoxFor(m => item.Selected, new { id = item.Value, #Value = item.Value, #Name = "selectedRole[]", #class = "checkbox-inline", data_val = "true", data_val_verifListe = " Select field " })
#Html.Label(item.Value, new { #class = "checkbox-inline-label" })
}
</span>
#Html.ValidationMessageFor(m => m.RolesList)
</td>
</tr>
</tbody>
</table>
<p>
<input type="submit" value="Update" />
</p>
}
I tried Validation like below but and have essues
namespace ...
{
public class CheckOneSelectedAttribute : ValidationAttribute, IClientValidatable
{
public string[] SelectedRole { get; private set; }
public CheckOneSelectedAttribute(string SelectedValue) : base("Select field")
{
if (SelectedValue != null && SelectedValue.Length > 0)
SelectedRole = SelectedValue;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value != null)
{
if (selectedRole != null)
{
if (selectedRole.Length == 0)
{
return new ValidationResult("Select field ");
}
}
}
else
{
return new ValidationResult("Null parameter");
}
return ValidationResult.Success;
}
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule()
{
ErrorMessage = ErrorMessageString,
ValidationType = "CheckOneSelected"
};
}
}
}
Can some one please help me?
Thanks.
In the controller part which is post and takes []list , You should check the length of the list by that u can make a validation for that .

Resources