MVC UpdateModel ComplexType - asp.net-mvc

If you have the following type.
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public List<TheParameters> Parameters { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string Street { get; set; }
public string City { get; set; }
public string State { get; set; }
}
public class TheParameters
{
public string Parameter { get; set; }
}
You make your page stronglytyped to Person.
"System.Web.Mvc.ViewPage<Person>"
<form action="/Home/Save" method="post">
<b>Your Name</b>
<label for="FirstName">
<span>First Name</span>
<%=Html.TextBox("Person.FirstName", ViewData.Model.FirstName) %>
</label>
<label for="LastName">
<span>Last Name</span>
<%=Html.TextBox("Person.LastName", ViewData.Model.LastName)%>
</label>
<b>Your Address</b>
<label for="Street">
<span>Street</span>
<%=Html.TextBox("Person.Address.Street", ViewData.Model.Address.Street)%>
</label>
<label for="City">
<span>City</span>
<%=Html.TextBox("Person.Address.City", ViewData.Model.Address.City)%>
</label>
<label for="State">
<span>State</span>
<%=Html.TextBox("Person.Address.State", ViewData.Model.Address.State)%>
</label>
<label for="Parameters">
<span>Parameters</span>
<%
int index = 0;
foreach (TheParameters parameter in ViewData.Model.Parameters)
{
Response.Write(Html.TextBox("Person.Parameters.Parameter[" + index + "]", parameter.Parameter));
index++;
}
%>
</label>
<input id="submit" type="submit" value="submit" />
</form>
In the controller the following:
public ActionResult Index()
{
Person p = new Person();
p.FirstName = "Name";
p.LastName = "Last";
p.Address = new Address();
p.Address.City = "city";
p.Address.State = "state";
p.Address.Street = "street";
p.Parameters = new List<TheParameters>();
p.Parameters.Add(new TheParameters(){ Parameter = "P1" });
p.Parameters.Add(new TheParameters(){ Parameter = "p2" });
ViewData.Model = p;
return View();
}
public ActionResult Save(FormCollection form)
{
Person p = new Person();
UpdateModel(p, "Person", form.ToValueProvider());
return RedirectToAction("Index");
}
I call the UpdateModel. All properties are filled in properly except for the Person.Parameters. This is always null after the updateModel.
Is there a solution for this or a workaround?
regards,
Steve

In your view:
"Person.Parameters.Parameter[" + index + "]"
should be
"Person.Parameters[" + index + "].Parameter"

Related

Binding in Razor returns null (OnPostAsync)

In the code below, we all values in QuestionViewModel are null. Any ideas what I am doing wrong about binding?
cs file:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using VerityLearn.DataAccess;
using VerityLearn.Domain;
using VerityLearn.DataAccess.UOW;
using VerityLearn.WebUI.ViewModels;
namespace VerityLearn.WebUI.Pages.Questions
{
[Authorize]
public class StudentQuestionsModel : PageModel
{
private readonly SignInManager<VerityUser> _signInManager;
private readonly UserManager<VerityUser> _userManager;
private readonly IStudentQuesionsUOW _studentQuesionsUOW;
private readonly VerityLearn.DataAccess.VerityContext _context;
public StudentQuestionsModel(
VerityContext context,
SignInManager<VerityUser> signInManager,
UserManager<VerityUser> userMrg,
IStudentQuesionsUOW studentQuesionsUOW
)
{
_context = context;
_signInManager = signInManager;
_userManager = userMrg;
_studentQuesionsUOW = studentQuesionsUOW;
} // end public StudentQuestionsModel(VerityContext context, SignInManager<VerityUser> signInManager, UserManager<VerityUser> userMrg)
#region User Properties
public VerityUser VerityUser { get; set; }
//[TempData]
//public string UserId { get; set; }
public Student Student { get; set; }
public Prospect Prospect { get; set; }
public Parent Parent { get; set; }
public ExamUserViewModel ExamUserViewModel { get; set; }
#endregion // User Properties
public DateTime DateStarted { get; set; }
public Exam Exam { get; set; }
[TempData]
public int ExamId { get; set; }
ExamQuestion ExamQuestion { get; set; }
public List<ExamQuestion> ExamQuestions { get; set; }
[TempData]
public int NbrOfExamQuestions { get; set; }
public ExamViewModel ExamViewModel { get; set; }
[TempData]
public int QuestionNdx { get; set; }
[BindProperty]
public QuestionViewModel QuestionViewModel { get; set; }
[ViewData]
public string Message { get; set; }
[BindProperty]
public Question Question { get; set; }
public async Task OnGetAsync(int? examId, int? questionNdx)
{
Message = string.Empty;
if (_signInManager.IsSignedIn(HttpContext.User))
{
string email = HttpContext.User.Identity.Name;
VerityUser = await _studentQuesionsUOW.GetVerityUser(email);
//UserId = VerityUser.Id.ToString();
// TODO: Setup priorities of setting Student, Prospect and Parent properties, might involve Enrollments 4/30/2020
//Student = await _context.Students.Where(s => s.UserId == VerityUser.Id).FirstOrDefaultAsync<Student>();
//Prospect = await _context.Prospects.Where(p => p.UserId == VerityUser.Id).FirstOrDefaultAsync<Prospect>();
//Parent = await _context.Parents.Where(p => p.UserId == VerityUser.Id).FirstOrDefaultAsync<Parent>();
DateStarted = DateTime.Now;
if ((examId != null) && (examId.Value > 0))
{
ExamId = examId.Value;
Exam = await _context.Exams.Where(e => e.ExamId == examId)
.Include(e => e.Course).ThenInclude(c => c.Subject).FirstOrDefaultAsync<Exam>();
if (Exam != null)
{
ExamUserViewModel = new ExamUserViewModel
{
ExamUserId = 0,
ExamId = Exam.ExamId,
TimeStarted = DateTime.Now,
Status = ExamUserStatus.InProgress,
StudentId = VerityUser.StudentId,
ProspectId = VerityUser.ProspectId,
ParentId = VerityUser.ParentId
};
// TODO: If this is a new ExamUser, we must insert it to VerityLearnDB2.ExamUsers
if (NbrOfExamQuestions == 0)
{
ExamQuestions = await _context.ExamQuestions
.Where(eq => eq.ExamId == examId)
.ToListAsync<ExamQuestion>();
NbrOfExamQuestions = ExamQuestions.Count;
TempData.Keep("NbrOfExamQuestions");
} // endif (NbrOfExamQuestions == 0)
if ((questionNdx == null) || (questionNdx.Value == 0))
{
questionNdx = 1;
} // endif ((questionNdx == null) || (questionNdx.Value == 0))
QuestionNdx = questionNdx.Value;
TempData.Keep("QuestionNdx");
ExamQuestion = await _context.ExamQuestions
.Include(eq => eq.Question)
.ThenInclude(q => q.Options)
.Where(eq => eq.ExamQuestionOrder == questionNdx)
.FirstOrDefaultAsync<ExamQuestion>();
QuestionViewModel = new QuestionViewModel
{
QuestionId = ExamQuestion.QuestionId,
ExamQuestionOrder = ExamQuestion.ExamQuestionOrder,
QuestionText = ExamQuestion.Question.QuestionText,
IsSingleSelection = ExamQuestion.Question.IsSingleSelection,
Options = new List<OptionViewModel>()
};
ExamViewModel = new ExamViewModel
{
ExamId = Exam.ExamId,
ExamName = Exam.ExamName,
Questions = new List<QuestionViewModel>()
};
ExamViewModel.Questions.Add(QuestionViewModel);
ExamViewModel.ExamUserViewModel = ExamUserViewModel;
List<AnswerOption> answerOptions = _context.AnswerOptions
.Where(ao => ao.QuestionId == ExamQuestion.QuestionId)
.ToList<AnswerOption>();
foreach (AnswerOption ao in answerOptions)
{
OptionViewModel ovm = new OptionViewModel
{
OptionId = ao.OptionId,
OptionText = ao.OptionText,
IsCorrect = ao.IsCorrect
};
ovm.UserExamOptionViewModel = new UserExamOptionViewModel
{
UserExamOptionId = ExamUserViewModel.ExamUserId,
UserExamId = 0,
OptionId = ao.OptionId,
IsSelected = false
};
QuestionViewModel.Options.Add(ovm);
}
}
else
{
Message = String.Format("Error: Exam with Identifier, {0}, was not found.", examId);
}
}
else
{
Message = String.Format("Error: Exam with Identifier, {0}, was not found.", examId);
}
}
else
{
Message = "Error: Login is required.";
}
}
public async Task<IActionResult> OnPostAsync(QuestionViewModel QuestionViewModel)
{
var t = QuestionViewModel;
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(Question).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
}
return RedirectToPage("./Index");
}
}
}
cshtml file:
#page "{examId:int?}"
#model VerityLearn.WebUI.Pages.Questions.StudentQuestionsModel
#{
ViewData["Title"] = "StudentQuestions";
}
#if (String.IsNullOrEmpty(#Model.Message))
{
<div class="row" style="background-color: #5D2685; color: #FFFF80;">
<div class="col-md-6">
<h4>Exam: #Html.DisplayFor(model => model.Exam.ExamName)</h4>
</div>
<div class="col-md-6">
<h4>Course: #Html.DisplayFor(model => model.Exam.Course.CourseName)</h4>
</div>
</div>
<br />
<br />
<div>
<h4>Question</h4>
<hr />
<form method="post">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<input type="hidden" asp-for="Question.QuestionId" />
<div class="form-group">
<label asp-for="Question.QuestionText" class="control-label"></label>
<input asp-for="Question.QuestionText" class="form-control" />
<span asp-validation-for="Question.QuestionText" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Question.KeyToAnswer" class="control-label"></label>
<input asp-for="Question.KeyToAnswer" class="form-control" />
<span asp-validation-for="Question.KeyToAnswer" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Question.IsSingleSelection" class="control-label"></label>
<input asp-for="Question.IsSingleSelection" class="form-control" />
<span asp-validation-for="Question.IsSingleSelection" class="text-danger"></span>
</div>
<label asp-for="QuestionViewModel.QuestionText" class="control-label"></label>
#if (Model.QuestionViewModel.IsSingleSelection.Value)
{
<p>Select the correct option.</p>
#foreach (OptionViewModel opt in Model.QuestionViewModel.Options)
{
<input type="radio" name="option" value="#opt.UserExamOptionViewModel.IsSelected"><label for=" #opt.OptionText"> #opt.OptionText </label><br />
}
}
else
{
<p>Select the correct options (More than one).</p>
#foreach (OptionViewModel opt in Model.QuestionViewModel.Options)
{
<input type="checkbox" name="option" value="#opt.UserExamOptionViewModel.IsSelected"><label for=" #opt.OptionText"> #opt.OptionText </label><br />
}
}
#{
var prevDisabled = (Model.QuestionNdx <= 1) ? "disabled" : "";
var nextDisabled = (Model.QuestionNdx >= Model.NbrOfExamQuestions) ? "disabled" : "";
}
<button type="submit" asp-route-questionIndex="#(Model.QuestionNdx - 1)" class="btn btn-primary #prevDisabled">Previous</button>
<button type="submit" asp-route-questionIndex="#(Model.QuestionNdx + 1)" class="btn btn-primary #nextDisabled">Next</button>
<div class="form-group">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</form>
</div>
}
else
{
<div class="row" style="background-color: #5D2685; color: #FFFF80;">
<div class="col-md-6">
<h4>#Model.Message</h4>
</div>
</div>
}
UPDATE (5/11/2020):
I have simplified the view like this:
#foreach(OptionViewModel opt in Model.QuestionViewModel.Options)
{
optionIndex++;
#Html.RadioButtonFor(model => model.QuestionViewModel.Options[optionIndex].OptionText, #opt.OptionText);
#opt.OptionText<br />
}
I see 4 options but all of them are selected. I would expect only one radio button to be selected at a time. I click Next anyway
I now see the option texts are bound. Question: How to figure out which one is selected?
The problem is you are using a complex model, but your HTML does not indicate that the model is complex. I have created a demo to highlight the issue:
Here Student contains Address and List<Subject> (it is complex model)
public class Subject
{
public string SubjectName { get; set; }
}
public class Address
{
public string StreetAddress { get; set; }
}
public class Student
{
public string Name { get; set; }
public Address HomeAddress { get; set; }
public List<Subject> Subjects { get; set; }
}
When displaying a complex model in a form, you need to use the entire model in the html input tag, this way ASP.NET MVC ModelBinder knows how to bind your HTML inputs to your server-side model.
The above demo has 3 inputs, I am using HTML.TextBoxFor which is the older equivalent of asp-for Tag Helper.
Input 1:
#Html.TextBoxFor(model => model.Name)
Generates the following HTML:
<input id="Name" name="Name" type="text" value="John Smith">
Model binder uses name and binds the above input to Student.Name
Input 2
#Html.TextBoxFor(model => model.HomeAddress.StreetAddress)
Generates the following HTML:
<input id="HomeAddress_StreetAddress" name="HomeAddress.StreetAddress" type="text" value="some address">
Here Model binder knows that this input should be bound to Student.HomeAddress.StreetAddress because that's what the input name indicates
Input 3
#Html.TextBoxFor(model => model.Subjects[0].SubjectName)
Generates the following HTML:
<input id="Subjects_0__SubjectName" name="Subjects[0].SubjectName" type="text" value="Math">
Model binder will bind the above input to Student.Subjects[0].SubjectName
See this article for more info.
In your example, Model Binder has no way to know that option belongs to QuestionViewModel.Options because you are not indicating it in the input name:
<input type="checkbox" name="option" value="#opt.UserExamOptionViewModel.IsSelected">
Make sure you're using [BindProperty] attribute.

how to pass parameter to controller from viewpage in mvc

please help me.
i can not bind the input parameter from textbox in to actionmethod
Controller code:
public ActionResult CheckUser(string empCode) // ActionMethod with parameter
{
try
{
string res = "";
DataSet dataSet = new DataSet();
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
using (SqlCommand command = new SqlCommand("spUserCheck"))
{
command.Parameters.AddWithValue("#UserCode", empCode);
command.CommandType = CommandType.StoredProcedure;
connection.Open();
command.Connection = connection;
SqlDataAdapter dataAdapter = new SqlDataAdapter();
dataAdapter.SelectCommand = command;
dataAdapter.Fill(dataSet);
connection.Close();
}
}
if (dataSet.Tables.Count > 0)
{
res = "Alredy Avilable";
}
else
{
res = "Not Avilable. Please create user";
}
return View(res) ;
}
catch (Exception ex)
{
throw new Exception("Error ", ex);
}
}
ViewCode:-
<div class="form-group">
<label class="control-label col-sm-2">Employee Code <span class="mandatory"></span>:</label>
<div class="col-sm-3">
<input type="text" class="form-control input-md" id="empCode" placeholder="Enter employee code" />
</div>
<div class="col-sm-2">
<input type="button" class="btn btn-info" onclick="location.href='#Url.Action("CheckUser", "User")'" id="btnAvaiaable" value="Check Availability ?" />
</div>
</div>
ModelCode
public class UserParameter
{
public string empCode { get; set; }
public string Role { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailID { get; set; }
public int MobileNo { get; set; }
public string Zone { get; set; }
public string State { get; set; }
public string Branch { get; set; }
public string CompanyType { get; set; }
}
First issue is you need a textbox with attribute name="empCode".
Second, you need to wrap the textbox in a form element.
Third, you need to post to the controller. Just changing the location in a button click (as you are doing) will do a get with no form data attached.
There are plenty of samples online which show this.

Error in my upload page after i changed my model [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
I added the code to show many checkboxes from my table (HairTags) and in my form CreationUpload.cshtml i got the following error :
An exception of type 'System.NullReferenceException' occurred in
App_Web eba142hb.dll but was not handled in user code Additional
information: Object reference not set to an instance of an object.
Object reference not set to an instance of an object.
<div class="col-md-12">
#for (int i = 0; i < Model.CreationHairTags.Count; i++)
{
#Html.CheckBoxFor(m => Model.CreationHairTags[i].IsChecked)
#Model.CreationHairTags[i].Text
#Html.HiddenFor(m => Model.CreationHairTags[i].Value)
#Html.HiddenFor(m => Model.CreationHairTags[i].Text)<br />
}
</div>
this is my model Creation.cs (in bold the added code)
namespace HairCollection3.Models
{
public class Creation
{
public string UserId { get; set; }
[Key]
public int CreationId { get; set; }
[Required(ErrorMessageResourceName = "Required", ErrorMessageResourceType = typeof(ViewRes.ValidationStrings))]
[Display(Name = "Sex", ResourceType = typeof(ViewRes.Names))]
public string CreationSex { get; set; }
[Required(ErrorMessageResourceName = "Required", ErrorMessageResourceType = typeof(ViewRes.ValidationStrings))]
[Display(Name = "CreationTitle", ResourceType = typeof(ViewRes.NamesCreation))]
[StringLength(2000)]
[AllowHtml]
public string CreationTitle { get; set; }
public string CreationPhotoBis { get; set; }
public string Creationtag { get; set; }
public virtual ICollection<CreationLike> CreationLikes { get; set; }
}
public class CreationLike
{
public int CreationId { get; set; }
public string UserId { get; set; }
public virtual ApplicationUser User { get; set; }
[Key]
public int CreationLikeId { get; set; }
public virtual Creation ParentCreation { get; set; }
}
public class HairTag
{
[Key]
public int HairTagId { get; set; }
[Required]
public string HairTagTitle { get; set; }
[Required]
public string HairTagType { get; set; }
[Required]
public int HairTagOrder { get; set; }
}
***//CHECKBOXES
public class HairTagModel
{
[Key]
public int Value { get; set; }
public string Text { get; set; }
public bool IsChecked { get; set; }
}
public class HairTagList
{
private ApplicationDbContext creationdb = new ApplicationDbContext();
public HairTagList()
{
var HairTagList = creationdb.HairTags.ToList();
List<HairTagModel> obj = new List<HairTagModel>();
foreach (var tags in HairTagList)
{
obj.Add(new HairTagModel
{
Text = tags.HairTagTitle,
Value = tags.HairTagId,
IsChecked = false
});
}
this.CreationHairTags = obj;
}
public List<HairTagModel> CreationHairTags { get; set; }
//public List<HairTagModel> ListHairTags { get; set; }
}
public class CreationHairTagsModel
{
public Creation Creation { get; set; }
public List<HairTagModel> CreationHairTags { get; set; }
}
}***
My controller CreationController.cs
// GET: /Creation/CreationUpload
[Authorize]
public ActionResult CreationUpload()
{
CreationHairTagsModel creation = new CreationHairTagsModel();
return View(creation);
//return View();
}
// POST: /Creation/CreationUpload
// Afin de déjouer les attaques par sur-validation, activez les propriétés spécifiques que vous voulez lier. Pour
// plus de détails, voir http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public ActionResult CreationUpload([Bind(Include = "CreationId,CreationSex,CreationTitle,CreationPhotoBis,CreationHairTags")] CreationHairTagsModel creation, IEnumerable<HttpPostedFileBase> files)
{
if (ModelState.IsValid)
{
// update each field manually
foreach (var file in files)
{
if (file != null)
{
if (file.ContentLength > 0)
{
....CODE UPLOAD HIDDEN....
//Avoid Script
var CreationTitletocheck = Regex.Replace(creation.Creation.CreationTitle, #"<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>", string.Empty);
CreationTitletocheck = Regex.Replace(CreationTitletocheck, #"(?></?\w+)(?>(?:[^>'""]+|'[^']*'|""[^""]*"")*)>", string.Empty);
creation.Creation.CreationTitle = CreationTitletocheck;
//Tags
StringBuilder sb = new StringBuilder();
foreach (var item in creation.CreationHairTags)
{
if (item.IsChecked)
{
sb.Append(item.Text + ",");
}
}
creation.Creation.Creationtag = sb.ToString();
creation.Creation.UserId = User.Identity.GetUserId();
db.Creations.Add(creation.Creation);
db.SaveChanges();
}
}
}
}
//UserId
return RedirectToAction("CreationList", "Creation", new { UserId = User.Identity.GetUserId() });
}
return View(creation);
}
My page of upload CreationUpload.cshtml
#model HairCollection3.Models.CreationHairTagsModel
#using Microsoft.AspNet.Identity
#{
ViewBag.Title = ViewRes.NamesCreation.CreationUploadTitle;
}
<div class="col-sm-12 col-md-12 chpagetop">
<h1>#ViewRes.Shared.PublishAPhoto</h1>
<hr />
#using (Html.BeginForm("CreationUpload", "Creation", FormMethod.Post, new { id = "CreationUpload", enctype = "multipart/form-data", onsubmit = "$('#creationloading').show(); $('#creationform').hide();" }))
{
#Html.AntiForgeryToken()
<div class="col-md-12" id="creationloading" style="display:none">
<div id="progress">
<p>#ViewRes.Shared.UploadPhotoProgress<strong>0%</strong></p>
<progress value="5" min="0" max="100"><span></span></progress>
</div>
</div>
<div class="col-md-12" id="creationform">
<div class="col-md-12">
#Html.ValidationMessageFor(m => m.Creation.CreationSex)
#Html.RadioButtonFor(m => m.Creation.CreationSex, "F", new { #checked = true }) #ViewRes.Shared.WomanHairstyle #Html.RadioButtonFor(m => m.Creation.CreationSex, "M") #ViewRes.Shared.ManHairstyle
</div>
<div class="col-md-12">
#Html.ValidationMessageFor(m => m.Creation.CreationTitle)
#Html.TextBoxFor(m => m.Creation.CreationTitle, new { #class = "inputplaceholderviolet wid100x100", placeholder = HttpUtility.HtmlDecode(Html.DisplayNameFor(m => m.Creation.CreationTitle).ToHtmlString()), onfocus = "this.placeholder = ''", onblur = "this.placeholder = '" + HttpUtility.HtmlDecode(Html.DisplayNameFor(m => m.Creation.CreationTitle).ToHtmlString()) + "'" })
</div>
<div class="col-md-12">
#for (int i = 0; i < Model.CreationHairTags.Count; i++)
{
#Html.CheckBoxFor(m => Model.CreationHairTags[i].IsChecked)
#Model.CreationHairTags[i].Text
#Html.HiddenFor(m => Model.CreationHairTags[i].Value)
#Html.HiddenFor(m => Model.CreationHairTags[i].Text)<br />
}
</div>
<div class="col-md-12" style="text-align: center">
<p style="display: inline-block">
<input type="file" accept="image/*" onchange="loadFile(event)" name="files" id="file1" translate="yes" data-val="true" data-val-required="A File is required." class="wid100x100" /><label for="file1"></label>
<img id="output" style="max-width:200px;"/>
</p>
</div>
<div class="col-sm-12 col-md-12 chpagetopdiv">
<button type="submit" title="#ViewRes.Shared.Publish"><span class="glyphicon glyphicon-share-alt"></span> #ViewRes.Shared.Publish</button>
</div>
</div>
}
</div>
What is wrong in my code please help and explain ?
Important: In C#, every collection must be initialized before being accessed
The error occurs when you are trying to access from the View to the collection CreationHairTags, which is not initialized. Replace your model to initialize collection in the class constructor:
public class CreationHairTagsModel
{
public Creation Creation { get; set; }
public List<HairTagModel> CreationHairTags { get; set; }
public CreationHairTagsModel()
{
CreationHairTags = new List<HairTagModel>();
}
}

MVC Controllers get value of 'Checkboxlist'

I'm probably a idiot here but I'm having problems getting the value of whether or not a checkbox is checked/selected or not. Here's what I've got so far:
In my Model:
public IEnumerable<SelectListItem> Insurers
{
get
{
var list = new List<SelectListItem>();
string zInsurersList = "Age UK,Be Wiser,Call Connection,Churchill,Sainsbury's,Direct Line,Hastings Direct,LV=,Nationwide,RIAS,Swinton";
string[] zInsurers = zInsurersList.Split(',');
foreach (string aInsurer in zInsurers)
{
list.Add(new SelectListItem() { Text = aInsurer, Value = aInsurer, Selected=false});
}
return list;
}
}
}
And my view:
#foreach (var insurer in #Model.Insurers)
{
var zInsurer = insurer.Text;
var zValue = insurer.Value;
<tr>
<td style="width: 120px; height: 35px;"><span id="#zInsurer">#zInsurer</span></td>
<td style="width: 40px; height: 35px;"><input id="#zInsurer" type="checkbox" name="#zInsurer"></td>
</tr>
}
So in my controller I'm trying to loop the list and get the value of whether or not the user has selected the option:
foreach (var item in model.Insurers)
{
//if (item.GetType() == typeof(CheckBox))
//string controlVal = ((SelectListItem)item).Selected.ToString();
zInsurers = zInsurers + item.Text + " " + ((SelectListItem)item).Selected.ToString() + "<br/>";
}
But the value always returns false.
Could someone spare a few mins to highlight my stupidity please?
Thanks,
Craig
There are a lot of ways to do it. I normally add String Array in model to collect selected values.
public string[] SelectedInsurers { get; set; }
<input type="checkbox" name="SelectedInsurers" value="#insurer.Value" />
Here is the sample code -
MyModel
public class MyModel
{
public string[] SelectedInsurers { get; set; }
public IEnumerable<SelectListItem> Insurers
{
get
{
var list = new List<SelectListItem>();
string zInsurersList = "Age UK,Be Wiser,Call Connection,Churchill,Sainsbury's,Direct Line,Hastings Direct,LV=,Nationwide,RIAS,Swinton";
string[] zInsurers = zInsurersList.Split(',');
foreach (string aInsurer in zInsurers)
{
list.Add(new SelectListItem { Text = aInsurer, Value = aInsurer, Selected = false });
}
return list;
}
}
}
Action Methods
public ActionResult Index()
{
return View(new MyModel());
}
[HttpPost]
public ActionResult Index(MyModel model)
{
return View();
}
View
#using (Html.BeginForm())
{
foreach (var insurer in #Model.Insurers)
{
<input type="checkbox" name="SelectedInsurers" value="#insurer.Value" /> #insurer.Text<br/>
}
<input type="submit" value="Post Back" />
}
Result
Firstly, your property Insurers should not be IEnumerable<SelectListItem> (tha'ts for binding a collection to a dropdownlist), and in any case, that kind of logic does not belong in a getter (and whats the point of creating a comma delimited string and then splitting it? - just create an array of strings in the first place!). Its not really clear exactly what you trying to do, but you should be creating a view model and doing it the MVC way and making use of its model binding features
View model
public class InsurerVM
{
public string Name { get; set; }
public bool IsSelected { get; set; }
}
Controller
public ActionResult Edit()
{
// This should be loaded from some data source
string[] insurers = new string[] { "Age UK", "Be Wiser", "Call Connection" };
List<InsurerVM> model = insurers.Select(i => new InsurerVM() { Name = i }).ToList();
return View(model);
}
View
#model List<InsurerVM>
#using(Html.BeginForm())
{
for (int i = 0; i < Model.Count; i++)
{
#Html.HiddenFor(m => m[i].Name)
#Html.CheckBoxFor(m => m[i].IsSelected)
#Html.LabelFor(m => m.[i].IsSelected, Model[i].Name)
}
<input type="submit" value="Save" />
}
Post method
[HttpPost]
public ActionResult Edit(IEnumerable<InsurerVM> model)
{
// loop each item to get the insurer name and the value indicating if it has been selected
foreach(InsurerVM insurer in model)
{
....
}
}
In reality, Insurers would be an object with an ID and other properties so it can be identified and have a relationship with other entities.
As to why you code is not working. Your property does not have a setter so nothing that posted back could be bound anyway. All the method is doing is initializing your model then calling the getter which creates a new IEnumerable<SelectListItem> (identical to the one you sent to the view in the first place). Not that it would have mattered anyway, your checkboxes have name attributes name="Age_UK", name=Be_Wiser" etc which have absolutely no relationship to your model so cant be bound
That is because the modelbinding can't process your values.
You should look into model binding.
Try something like this:
#for (var countInsurer = 0; Model.Insurers.Count > countInsurer++)
{
var zInsurer = insurer.Text;
var zValue = insurer.Value;
<tr>
<td style="width: 120px; height: 35px;"><span id="#zInsurer">#zInsurer</span></td>
<td style="width: 40px; height: 35px;">#Html.CheckBoxFor(m=> Model.Insurers[countInsurer], new {name = zInsurer})</td>
</tr>
}
#for(int i = 0; i < Model.List.Count; i++)
{
#Html.CheckBoxFor(m => Model.List[i].IsChecked, htmlAttributes: new { #class = "control-label col-md-2" })
#Model.List[i].Name
#Html.HiddenFor(m => Model.List[i].ID)
#Html.HiddenFor(m => Model.List[i].Name)
<br />
}
in controller
StringBuilder sb = new StringBuilder();
foreach (var item in objDetail.List)
{
if (item.IsChecked)
{
sb.Append(item.Value + ",");
}
}
ViewBag.Loc = "Your preferred work locations are " + sb.ToString();
I Get Module And Right from Module and Rights Table How to Send All Data To RoleRight Table All Checkbox value
public class RoleRightModel
{
public ModuleModel _ModuleModel { get; set; }
public RightsModel _RightsModel { get; set; }
public RolesModel _RolesModel { get; set; }
public List<ModuleModel> _ModuleModelList { get; set; }
public List<RightsModel> _RightsModelList { get; set; }
public List<RolesModel> _RolesModelList { get; set; }
public List<RoleRightModel> _RoleRightModelList { get; set; }
public int RoleRightID { get; set; }
public int RoleID { get; set; }
public int ModuleID { get; set; }
public int FormMode { get; set; }
public int RightCode { get; set; }
public bool? RowInternal { get; set; }
public byte? IsAuthorised { get; set; }
public int? CreationID { get; set; }
public DateTime? CreationDate { get; set; }
public int? LastModificationID { get; set; }
public DateTime? LastModificationDate { get; set; }
public byte? RowStatus { get; set; }
public string RoleName { get; set; }
}
Razor
#foreach(var item in Model._ModuleModelList.Where(x => x.Level == 1))
{
<ul style="display: block;">
<li><i class="fa fa-plus"></i>
<label>
#if (item.Level == 1)
{
<input id="node-0-1" data-id="custom-1" type="checkbox" name="Module" value="#item.ModuleID"#(Model._ModuleModel.ModuleID)? "checked":"">
#item.ModuleName
}
</label>
#foreach (var lavel1 in Model._ModuleModelList.Where(x => x.ParentModuleID == item.ModuleID))
{
<ul>
<li><i class="fa fa-plus"></i>
<label>
<input id="node-0-1-1" data-id="custom-1-1" type="checkbox" name="Module" value="#lavel1.ModuleID"#(Model._ModuleModel.ModuleID)? "checked":"">
#lavel1.ModuleName
</label>
#foreach (var lavel2 in Model._ModuleModelList.Where(x => x.ParentModuleID == lavel1.ModuleID))
{
<ul>
<li><i class="fa fa-plus"></i>
<label>
<input id="node-0-1-1-1" data-id="custom-1-1-1" type="checkbox" name="Module" value="#lavel2.ModuleID"#(Model._ModuleModel.ModuleID)? "checked":"">
#lavel2.ModuleName
</label>
#foreach (var lavel3 in Model._RightsModelList.Where(x => x.ModuleId == lavel2.ModuleID))
{
<ul>
<li>
<label>
<input id="node-0-1-1-1-1" data-id="custom-1-1-1-1" type="checkbox" name="Right" value="#lavel3.RightID"#(Model._RightsModel.RightID)? "checked":"">
#lavel3.RightName
</label>
</li>
</ul>
}
</li>
</ul>
}
</li>
</ul>
}
</li>
</ul>
}

How to bind value from database to Dropdown List in MVC 3

I am trying to bind a dropdown list from database in mvc3.
I have two tables.
tblEmp:
EmpID (pk),
EName,
Age,
Address,
EmailID,
DeptID (fk).
tblDept
DeptID (pk),
DeptName,
DeptHead.
I am trying to bind create an Employee application with the basic details of an employee
Name, Age, Address, EmailID, and Dept Name. I am trying to bind the Dept Name dropdownlist from the other table.
This is my Model:
namespace MvcEmployeeApplication.Models
{
public class UandPcompare
{
public int EmpID { get; set; }
public string EName { get; set; }
public int Age { get; set; }
public string Address { get; set; }
public string EmailID { get; set; }
public int DeptID { get; set; }
public string DeptName { get; set; }
public string DeptHead { get; set; }
public IList<SelectListItem> Drp_DeptNames { get; set; }
}
}
This is Controller:
[HttpGet]
public ActionResult Create()
{
FillDeptName();
return View();
}
[HttpPost]
public ActionResult Create(tblEmployee tblEmp)
{
test.Entry(tblEmp).State = System.Data.EntityState.Added;
test.SaveChanges();
return RedirectToAction("Index");
}
public ActionResult FillDeptName()
{
UandPcompare filldeptNme = new UandPcompare();
filldeptNme.Drp_DeptNames = (from DptName in test.tblDepts
select new SelectListItem()
{
Text = DptName.DeptName,
Value = SqlFunctions.StringConvert((double)DptName.DeptID)
}).ToList<SelectListItem>();
return View("Create");
}
This is MyView:
#model MvcEmployeeApplication.Models.UandPcompare
#{
ViewBag.title = "Edit";
}
<h2> Create </h2>
#using (Html.BeginForm())
{
<fieldset>
<legend> Create </legend>
<div>
Employee ID: #Html.DisplayFor(model => model.EmpID)
</div>
<div>
Employee Name: #Html.EditorFor(model => model.EName)
</div>
<div>
Email-ID: #Html.EditorFor(model => model.EmailID)
</div>
<div>
Address: #Html.EditorFor(model => model.Address)
</div>
<div>
Dept Name: #Html.DropDownList("DeptName", Model.Drp_DeptNames, "Select")
</div>
<p>
<input type="submit" value="Create" />
</p>
<div>
#Html.ActionLink("Back to Index", "Index");
</div>
Not able to get what error are you getting.
You are not passing any model to your view.
public ActionResult FillDeptName()
{
UandPcompare filldeptNme = new UandPcompare();
filldeptNme.Drp_DeptNames = (from DptName in test.tblDepts
select new SelectListItem()
{
Text = DptName.DeptName,
Value = SqlFunctions.StringConvert((double)DptName.DeptID)
}).ToList<SelectListItem>();
return View("Create",filldeptNme);//pass model to view here
}

Resources