This is Task model
namespace TaskManager.Models
{
public class Task
{
private const int DefaultTaskPriority = 1;
//some other properties
[DefaultValue(DefaultTaskPriority)]
public TaskPriority Priority { get; set; }
}
public enum TaskPriority
{
[Display(Name = "Low")]
Low = 0,
[Display(Name = "Default")]
Normal = 1,
[Display(Name = "High")]
High = 2,
[Display(Name = "Extreme")]
Extreme = 3
}
}
and this is part of my view
<div class="form-group">
#Html.LabelFor(u => u.Priority)
<div class="radio">
<label>#Html.RadioButtonFor(model => model.Priority, 0) Low</label>
</div>
<div class="radio">
<label>#Html.RadioButtonFor(model => model.Priority, 1, new { Checked = "checked" }) Default</label>
</div>
<div class="radio">
<label>#Html.RadioButtonFor(model => model.Priority, 2) High</label>
</div>
<div class="radio">
<label>#Html.RadioButtonFor(model => model.Priority, 3) Extreme</label>
</div>
#Html.ValidationMessageFor(u => u.Description, null, new {#class = "error"})
</div>
but I'm not sure, is it the right way to create radio buttons? Maybe I should get label for every radio button from model (from enum TaskPriority)? I'm new in MVC so I don't know which way is better?
UPD View using values from enum TaskPriority
<div class="form-group">
#Html.LabelFor(u => u.Priority)
<div class="radio">
<label>#Html.RadioButtonFor(model => model.Priority, TaskPriority.Low) Low</label>
</div>
<div class="radio">
<label>#Html.RadioButtonFor(model => model.Priority, TaskPriority.Normal) Normal</label>
</div>
<div class="radio">
<label>#Html.RadioButtonFor(model => model.Priority, TaskPriority.High) High</label>
</div>
<div class="radio">
<label>#Html.RadioButtonFor(model => model.Priority, TaskPriority.Extreme) Extreme</label>
</div>
#Html.ValidationMessageFor(u => u.Description, null, new {#class = "error"})
</div>
Related
I have a ViewModel defined as:
public class Fixtures
{
public int Id { get; set; }
public string HomeTeam { get; set; }
public string AwayTeam { get; set; }
public string HomeTeamCode { get; set; }
public string AwayTeamCode { get; set; }
public string League { get; set; }
public bool Home { get; set; }
public bool Draw { get; set; }
public bool Away { get; set; }
public string FixturePrediction { get; set; }
}
My view displays a list of these fixtures and for each fixture, I have a radio button grouping. I need some way of passing the selected radio button for each fixture to my Post method. My View and controller are as below:
View:
<div class="container">
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
for (int i = 0; i < Model.Count(); i++)
{
#Html.HiddenFor(model => model[i].Id)
<div class="col-sm-6">
<div class="panel panel-primary panel-fixture">
<div class="panel-heading text-center fixturetitle">
#Html.DisplayFor(model => model[i].HomeTeam) v #Html.DisplayFor(model => model[i].AwayTeam)
#Html.HiddenFor(model => model[i].HomeTeam)
#Html.HiddenFor(model => model[i].AwayTeam)
</div>
<div class="panel-body">
<div class="container-fluid">
<div class="row">
<div class="col-xs-4 text-center">
<img src="~/Content/Images/#string.Concat(Model[i].HomeTeamCode, ".png")" class="fixturecrest" />
<div class="text-center">
#Html.DisplayFor(model => model[i].HomeTeamCode)
#Html.HiddenFor(model => model[i].HomeTeamCode)
</div>
</div>
<div class="col-xs-4 text-center">
<label class="text-center">
V <br />
</label>
</div>
<div class="col-xs-4 text-center">
<img src="~/Content/Images/#string.Concat(Model[i].AwayTeamCode, ".png")" class="fixturecrest" />
<div class="text-center">
#Html.DisplayFor(model => model[i].AwayTeamCode)
#Html.HiddenFor(model => model[i].AwayTeamCode)
</div>
</div>
</div>
<hr />
<div class="row">
<div class="text-center" role="group" aria-label="Fixture Prediction">
<div class="col-xs-4 text-center">
<button type="button" class="btn btn-xs btn-default">
HOME
#Html.RadioButtonFor(model => model[i].FixturePrediction, Model[i].Home, new { #Name = Model[i].Id })
#Html.HiddenFor(model => model[i].FixturePrediction)
<span class="glyphicon glyphicon-check"></span>
</button>
</div>
<div class="col-xs-4 text-center">
<button type="button" class="btn btn-xs btn-default">
DRAW
#Html.RadioButtonFor(model => model[i].FixturePrediction, Model[i].Draw, new { #Name = Model[i].Id })
#Html.HiddenFor(model => model[i].FixturePrediction)
<span class="glyphicon glyphicon-check"></span>
</button>
</div>
<div class="col-xs-4 text-center">
<button type="button" class="btn btn-xs btn-default">
AWAY
#Html.RadioButtonFor(model => model[i].FixturePrediction, Model[i].Away, new { #Name = Model[i].Id })
#Html.HiddenFor(model => model[i].FixturePrediction)
<span class="glyphicon glyphicon-check"></span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
}
<input type="submit" value="Confirm Predictions" class="btn btn-success" />
}
</div>
Post Method in Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Test(IEnumerable<Fixtures> test)
{
if (ModelState.IsValid)
{
}
return RedirectToAction("Test");
}
My field FixturePrediction is always null and I have attempted several variations of the 'radiobuttonfor' shown above.
All I need is to assign a value to FixturePrediction based on which radiobutton is selected. What am I missing?
Thanks in advance.
I think what you are trying to do is this, I am not sure why you are doing it the way you are doing it, but this is how you would implement Html.RadioButtonFor, it takes the model prop, and the value, you can add as many buttons as you want, and the selected radio value will be passed as the value for your model prop
#Html.RadioButtonFor(model => model[i].FixturePrediction, "Home")
#Html.RadioButtonFor(model => model[i].FixturePrediction, "Draw")
#Html.RadioButtonFor(model => model[i].FixturePrediction, "Away")
Another example
I have a simple MVC program where earlier I was using one model and the code was working fine. here is the code.
View
#model Microsoft.Azure.ActiveDirectory.GraphClient.User
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Create User</title>
</head>
<body>
<h2>Create User</h2><br />
#using (Html.BeginForm("Create",
"CreateUsers",
new { id = Model != null ? Model.ObjectId : "" },
FormMethod.Post,
new { enctype = "multipart/form-data" })
)
{
<fieldset>
<legend>User</legend>
<div class="editor-label">
#Html.LabelFor(model => model.UserPrincipalName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.UserPrincipalName)
#Html.ValidationMessageFor(model => model.UserPrincipalName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.AccountEnabled)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.AccountEnabled)
#Html.ValidationMessageFor(model => model.AccountEnabled)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PasswordProfile.Password)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PasswordProfile.Password)
#Html.ValidationMessageFor(model => model.PasswordProfile.Password)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.MailNickname)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.MailNickname)
#Html.ValidationMessageFor(model => model.MailNickname)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DisplayName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.DisplayName)
#Html.ValidationMessageFor(model => model.DisplayName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.GivenName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.GivenName)
#Html.ValidationMessageFor(model => model.GivenName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Surname)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Surname)
#Html.ValidationMessageFor(model => model.Surname)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.JobTitle)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.JobTitle)
#Html.ValidationMessageFor(model => model.JobTitle)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Department)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Department)
#Html.ValidationMessageFor(model => model.Department)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
</body>
</html>
#if (ViewBag.ErrorMessage == "AuthorizationRequired")
{
<p>You have to sign-in. Click #Html.ActionLink("here", "Create", "Users", new { reauth = true }, null) to sign-in.</p>
}
Controller
public async Task<ActionResult> Create(string blobDetails)
{
#region POPULATE USER DETAIL IN CREATEUSER FIELDS
List<string> userDetails = blobDetails.Split(',').ToList();
User user = new User();
user.UserPrincipalName = userDetails[2] + "#xxx.com";
user.GivenName = userDetails[0];
user.Surname = userDetails[1];
user.DisplayName = userDetails[0] + " " + userDetails[1];
return View(Tuple.Create(user);
#endregion
}
[HttpPost]
public async Task<ActionResult> Create([Bind(Include ="UserPrincipalName,AccountEnabled,PasswordProfile,MailNickname,DisplayName,GivenName,Surname,JobTitle,Department")] User user)
{
ActiveDirectoryClient client = null;
client = AuthenticationHelper.GetActiveDirectoryClient();
string name = user.GivenName;
string username = user.UserPrincipalName;
return RedirectToAction("Index");
}
And this works perfectly fine , I get the values of user.GivenName and user.UserPrincipalName from view and I store it into string. Now what I am doing is that I am including one more model into this and trying to get its value from view so I did something like this:
Model
public class CreateUsers
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string PIDetails { get; set; }
public string BlobDetails { get; set; }
public string UserEmail { get; set; }
}
View
#using WebAppGraphAPI.Models
#model Tuple<Microsoft.Azure.ActiveDirectory.GraphClient.User, CreateUsers>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Create User</title>
</head>
<body>
<h2>Create User</h2><br />
#using (Html.BeginForm("Create",
"CreateUsers",
new { id = Model != null ? Model.Item1.ObjectId : ""
},
FormMethod.Post,
new { enctype = "multipart/form-data" })
)
{
#Html.ValidationSummary(true)
<fieldset>
<legend>User</legend>
<div class="editor-label">
#Html.LabelFor(tuple => tuple.Item1.UserPrincipalName)
</div>
<div class="editor-field">
#Html.EditorFor(tuple => tuple.Item1.UserPrincipalName)
#Html.ValidationMessageFor(tuple => tuple.Item1.UserPrincipalName)
</div>
<div class="editor-label">
#Html.LabelFor(tuple => tuple.Item1.AccountEnabled)
</div>
<div class="editor-field">
#Html.EditorFor(tuple => tuple.Item1.AccountEnabled)
#Html.ValidationMessageFor(tuple => tuple.Item1.AccountEnabled)
</div>
<div class="editor-label">
#Html.LabelFor(tuple => tuple.Item1.PasswordProfile.Password)
</div>
<div class="editor-field">
#Html.EditorFor(tuple => tuple.Item1.PasswordProfile.Password)
#Html.ValidationMessageFor(tuple => tuple.Item1.PasswordProfile.Password)
</div>
<div class="editor-label">
#Html.LabelFor(tuple => tuple.Item1.MailNickname)
</div>
<div class="editor-field">
#Html.EditorFor(tuple => tuple.Item1.MailNickname)
#Html.ValidationMessageFor(tuple => tuple.Item1.MailNickname)
</div>
<div class="editor-label">
#Html.LabelFor(tuple => tuple.Item1.DisplayName)
</div>
<div class="editor-field">
#Html.EditorFor(tuple => tuple.Item1.DisplayName)
#Html.ValidationMessageFor(tuple => tuple.Item1.DisplayName)
</div>
<div class="editor-label">
#Html.LabelFor(tuple => tuple.Item1.GivenName)
</div>
<div class="editor-field">
#Html.EditorFor(tuple => tuple.Item1.GivenName)
#Html.ValidationMessageFor(tuple => tuple.Item1.GivenName)
</div>
<div class="editor-label">
#Html.LabelFor(tuple => tuple.Item1.Surname)
</div>
<div class="editor-field">
#Html.EditorFor(tuple => tuple.Item1.Surname)
#Html.ValidationMessageFor(tuple => tuple.Item1.Surname)
</div>
<div class="editor-label">
#Html.LabelFor(tuple => tuple.Item1.JobTitle)
</div>
<div class="editor-field">
#Html.EditorFor(tuple => tuple.Item1.JobTitle)
#Html.ValidationMessageFor(tuple => tuple.Item1.JobTitle)
</div>
<div class="editor-label">
#Html.LabelFor(tuple => tuple.Item1.Department)
</div>
<div class="editor-field">
#Html.EditorFor(tuple => tuple.Item1.Department)
#Html.ValidationMessageFor(tuple => tuple.Item1.Department)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
<div class="editor-label">
#*#Html.LabelFor(tuple => tuple.Item2.UserEmail)*#
#Html.EditorFor(tuple => tuple.Item2.UserEmail)
</div>
</body>
</html>
#if (ViewBag.ErrorMessage == "AuthorizationRequired")
{
<p>You have to sign-in. Click #Html.ActionLink("here", "Create", "Users", new { reauth = true }, null) to sign-in.</p>
}
Controller
public async Task<ActionResult> Create(string blobDetails)
{
#region POPULATE USER DETAIL IN CREATEUSER FIELDS
List<string> userDetails = blobDetails.Split(',').ToList();
User user = new User();
user.UserPrincipalName = userDetails[2] + "#gwuadmeaoutlook.onmicrosoft.com";
user.GivenName = userDetails[0];
user.Surname = userDetails[1];
user.DisplayName = userDetails[0] + " " + userDetails[1];
CreateUsers userInfo = new CreateUsers();
userInfo.UserEmail = userDetails[4];
return View(Tuple.Create(user,userInfo));
}
[HttpPost]
public async Task<ActionResult> Create([Bind(Include ="UserPrincipalName,AccountEnabled,PasswordProfile,MailNickname,DisplayName,GivenName,Surname,JobTitle,Department")] User user,[Bind(Include ="UserEmail")] CreateUsers userInfo)
{
ActiveDirectoryClient client = null;
client = AuthenticationHelper.GetActiveDirectoryClient();
string name = user.GivenName;
string username = user.UserPrincipalName;
string Email = userInfo.UserEmail
return RedirectToAction("Index");
}
When I do this I do not get values from View in my controller strings , it shows null. Can you suggest me how can I achieve this.
You could use an object which contains all of the properties you're trying to send to the client. We generally create DTOs for this specific usage. In you're case you'd have:
CreateDto
public class CreateDto
{
public Microsoft.Azure.ActiveDirectory.GraphClient.User User { get; set; }
public CreateUsers UserInfo { get; set; }
}
Then you're controller will be updated as:
public async Task<ActionResult> Create(string blobDetails)
{
#region POPULATE USER DETAIL IN CREATEUSER FIELDS
List<string> userDetails = blobDetails.Split(',').ToList();
User user = new User();
user.UserPrincipalName = userDetails[2] + "#gwuadmeaoutlook.onmicrosoft.com";
user.GivenName = userDetails[0];
user.Surname = userDetails[1];
user.DisplayName = userDetails[0] + " " + userDetails[1];
CreateUsers userInfo = new CreateUsers();
userInfo.UserEmail = userDetails[4];
var dto = new CreateDto() {
User = user,
UserInfo = userInfo
}
return View(dto);
}
[HttpPost]
public async Task<ActionResult> Create([Bind(Include ="UserPrincipalName,AccountEnabled,PasswordProfile,MailNickname,DisplayName,GivenName,Surname,JobTitle,Department")] User user,[Bind(Include ="UserEmail")] CreateUsers userInfo)
{
ActiveDirectoryClient client = null;
client = AuthenticationHelper.GetActiveDirectoryClient();
string name = user.GivenName;
string username = user.UserPrincipalName;
string Email = userInfo.UserEmail
return RedirectToAction("Index");
}
And your view will have:
#using WebAppGraphAPI.Models
#model CreateDto
Later you can reference the information with Model.user and Model.userInfo.
I know this doesn't explain why the Tuple doesn't work. I believe that is best explain by #darin-dimitrov in ado.net mvc3 tuple using in model and single views
In this Form used validation summary for errors.
View:-
<div class="col-md-12 table-bordered" style="padding: 20px; margin:10px;">
<div class="col-md-12">#Html.ValidationSummary(false,"Please Correct Following details :", new { #class = "text-danger" })</div>
<div class="col-md-12" style="padding:10px;">
<div class="col-md-6">
<div style="width:95%;">
#Html.LabelFor(Model => Model.ItemName, new { style = "font-weight:bold;", #maxlength = "100" })
#Html.TextBoxFor(Model => Model.ItemName)
<span class="text-danger"> #Html.ValidationMessageFor(Model => Model.ItemName) </span>
</div>
</div>
<div class="col-md-6">
<div style="width:75%;">
#Html.LabelFor(Model => Model.ActiveProductGroup, new { style = "font-weight:bold;" })
#Html.DropDownListFor(Model => Model.ProductGroupID, new SelectList(ViewBag.ActiveProductGroup, "Value", "Text"), "--Select Value--", new { style = "Width:95%" })
<span class="text-danger"> #Html.ValidationMessageFor(Model => Model.ActiveProductGroup) </span>
</div>
</div>
</div>
<div class="col-md-12" style="padding:10px;">
<div class="col-md-3">
<div style="width:70%;">
#Html.LabelFor(Model => Model.SequenceNumber, new { style = "font-weight:bold;" })
#Html.TextBoxFor(Model => Model.SequenceNumber, new { style = "text-align:right", #maxlength = "3" })
<span class="text-danger"> #Html.ValidationMessageFor(Model => Model.SequenceNumber) </span>
</div>
</div>
<div class="col-md-3">
<div style="width:50%;">
#Html.LabelFor(Model => Model.UnitPrice, new { style = "font-weight:bold;" })
#Html.TextBoxFor(Model => Model.UnitPrice, new { style = "text-align:right", #maxlength = "5" })
<span class="text-danger"> #Html.ValidationMessageFor(Model => Model.UnitPrice) </span>
</div>
</div>
<div class="col-md-3">
<div style="width:50%;">
#Html.LabelFor(Model => Model.Quantity, new { style = "font-weight:bold;" })
#Html.TextBoxFor(Model => Model.Quantity, new { style = "text-align:right", #maxlength = "5" })
<span class="text-danger"> #Html.ValidationMessageFor(Model => Model.Quantity) </span>
</div>
</div>
<div class="col-md-3">
<div style="width:80%;">
#Html.LabelFor(Model => Model.EstimatedDeliveryDays, new { style = "font-weight:bold;" })
#Html.TextBoxFor(Model => Model.EstimatedDeliveryDays, new { style = "text-align:right", #maxlength = "2" })
<span class="text-danger"> #Html.ValidationMessageFor(Model => Model.EstimatedDeliveryDays) </span>
</div>
</div>
</div>
</div>
In this used html.validation summary
In this Form it should show asterisk (*) sign below textbox and error in validation summary
how to achieve it?
Can't you use the Required attribute in your model?
Example:
public class ClassName{
[Required(ErrorMessage = "* Please enter Item Name")]
public string ItemName {get;set;}
}
I've put some Regex expression on the properties of my model that only accept numbers.
public class MaterialsViewModel
{
[Display(Name = "Material")]
public string MaterialName { get; set; }
[Range(typeof(int), "0", "999")]
[RegularExpression(#"^\d+$", ErrorMessage = "Please enter proper value")]
public int? Quantity { get; set; }
[RegularExpression(#"^\d+$", ErrorMessage = "Please enter proper value")]
public double? Cost { get; set; }
public IEnumerable<SelectListItem> CategoryList { get; set; }
public int SelectedCategory { get; set; }
public string SelectedCategoryName { get; set; }
}
I have my View in which I can add controls dynamically
Dynamically add ScopeOfWork and Materials<br />
<div id="scopes">
<h3>Scopes</h3>
Add Scope of Work
#for (int i = 0; i < Model.ScopeOfWork.Count; i++)
{
<div class="scope">
<div class="form-group">
#Html.LabelFor(m => m.ScopeOfWork[i].ScopeOfWorkName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.ScopeOfWork[i].ScopeOfWorkName, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.ScopeOfWork[i].ScopeOfWorkName)
</div>
</div>
<input type="hidden" class="scopeindex" name="ScopeOfWork.Index" value="#i" />
<div class="indent materials">
<h4>Material</h4>
Add Material
#for (int j = 0; j < Model.ScopeOfWork[i].Materials.Count; j++)
{
<div class="material">
<div class="form-group">
#Html.LabelFor(m => m.ScopeOfWork[i].Materials[j].MaterialName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-2">
#Html.TextBoxFor(m => m.ScopeOfWork[i].Materials[j].MaterialName, new { #class = "form-control" })
</div>
<div class="col-md-10 col-md-offset-2">
#Html.ValidationMessageFor(m => m.ScopeOfWork[i].Materials[j].MaterialName)
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.ScopeOfWork[i].Materials[j].Quantity, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-1">
#Html.TextBoxFor(m => m.ScopeOfWork[i].Materials[j].Quantity, new { #class = "form-control" })
</div>
<div class="col-md-10 col-md-offset-2">
#Html.ValidationMessageFor(m => m.ScopeOfWork[i].Materials[j].Quantity)
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.ScopeOfWork[i].Materials[j].Cost, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-1">
#Html.TextBoxFor(m => m.ScopeOfWork[i].Materials[j].Cost, new { #class = "form-control" })
</div>
<div class="col-md-10 col-md-offset-2">
#Html.ValidationMessageFor(m => m.ScopeOfWork[i].Materials[j].Cost)
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">Category</label>
<div class="col-xs-2">
#Html.DropDownListFor(m => m.ScopeOfWork[i].Materials[j].SelectedCategory, Model.ScopeOfWork[i].Materials[j].CategoryList, "Please select", htmlAttributes: new { #class = "form-control" })
</div>
</div>
<input type="hidden" class="materialindex" name="ScopeOfWork[#i].Materials.Index" value="#j" />
</div>
}
</div>
</div>
}
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-success" />
</div>
</div>
</div>
}
<div id="newScope" style="display:none">
<div class="scope">
<div class="form-group">
<label for="_#__ScopeOfWorkName" class="control-label col-md-2">Scope Of Work</label>
<div class="col-md-10">
<input class="form-control" type="text" id="_#__ScopeOfWorkName" name="ScopeOfWork[#].ScopeOfWorkName" value="">
<span class="field-validation-valid text-danger" data-valmsg-for="ScopeOfWork[#].ScopeOfWorkName" data-valmsg-replace="true"></span>
</div>
</div>
<input type="hidden" class="scopeindex" name="ScopeOfWork.Index" value="#" />
<div class="materials">
<h4>Material</h4>
Add Material
</div>
<hr />
</div>
</div>
<div id="newMaterial" style="display:none">
<div class="form-group">
<label for="_#__Materials_%__MaterialName" class="control-label col-md-2">Material</label>
<div class="col-md-2">
<input class="form-control" type="text" id="_#__Materials_%__MaterialName" name="ScopeOfWork[#].Materials[%].MaterialName" value="">
<span class="field-validation-valid text-danger" data-valmsg-for="ScopeOfWork[#].Materials[%].MaterialName" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label for="_#__Materials_%__Quantity" class="control-label col-md-2">Quantity</label>
<div class="col-md-1">
<input class="form-control" type="text" id="_#__Materials_%__Quantity" name="ScopeOfWork[#].Materials[%].Quantity" value="">
<span class="field-validation-valid text-danger" data-valmsg-for="ScopeOfWork[#].Materials[%].Quantity" data-valmsg-replace="true"></span>
</div>
</div>
<div class="form-group">
<label for="_#__Materials_%__Cost" class="control-label col-md-2">Cost</label>
<div class="col-md-1">
<input class="form-control" type="text" id="_#__Materials_%__Cost" name="ScopeOfWork[#].Materials[%].Cost" value="">
<span class="field-validation-valid text-danger" data-valmsg-for="ScopeOfWork[#].Materials[%].Cost" data-valmsg-replace="true"></span>
</div>
</div>
#*Drop down*#
<div class="form-group">
<label for="_#__Materials_%__SelectedCategory" class="control-label col-md-2">Category</label>
<div class="col-xs-2">
<select class="form-control category" id="_#__Materials_%__SelectedCategory" name="ScopeOfWork[#].Materials[%].SelectedCategory">
<option value="">--Select--</option>
</select>
</div>
</div>
<input type="hidden" class="materialindex" name="ScopeOfWork[#].Materials.Index" value="%" />
</div>
<script>
var form = $('form');
var scope = $('#newScope');
var material = $('#newMaterial');
var categories = #Html.Raw(Json.Encode(Model.CategoryList));
form.on('click', '.addmaterial', function () {
var clone = material.clone();
var scopeIndex = $(this).closest('.scope').find('.scopeindex').val();
clone.html($(clone).html().replace(/#/g, scopeIndex));
var materialIndex = new Date().getTime();
clone.html($(clone).html().replace(/%/g, materialIndex));
// drop down list
var select = clone.find('.category');
$.each(categories, function(index, item) {
select.append($('<option></option>').val(item.Value).text(item.Text));
});
$(this).closest('.materials').append(clone.html());
form.data('validator', null);
$.validator.unobtrusive.parse(form);
});
$('#addScope').click(function () {
var clone = scope.clone();
var scopeIndex = new Date().getTime();
clone.html($(clone).html().replace(/#/g, scopeIndex));
$('#scopes').append(clone.html());
form.data('validator', null);
$.validator.unobtrusive.parse(form);
});
</script>
Controller:
[HttpPost]
public ActionResult _CreateProject(ProjectViewModel project)
{
tblProject projectModel = new tblProject();
tblScopeOfWork scopeModel = new tblScopeOfWork();
tblMaterial materialModel = new tblMaterial();
if (ModelState.IsValid)
{
projectModel.ProjectName = project.ProjectName;
projectModel.ProjectLocation = project.ProjectLocation;
projectModel.ProjectDescription = project.ProjectDescription;
projectModel.WorkArea = project.WorkArea;
projectModel.ModeOfPayment = project.ModeOfPayment;
projectModel.Duration = project.Duration;
projectModel.StartDate = project.StartDate;
projectModel.EndDate = project.EndDate;
projectModel.ProfitSupervision = project.ProfitSupervision;
projectModel.ProjectStatus = project.ProjectStatus;
projectModel.ForemanId = project.ForemanId;
projectModel.ClientId = project.ClientId;
db.tblProjects.Add(projectModel);
db.SaveChanges();
//Get the recently created ProjectId
var recentProjectId = db.tblProjects.OrderByDescending(x => x.ProjectId).FirstOrDefault().ProjectId;
//Get all values from List of ScopeOfWork
//Add each ScopeOfWork to the database
for (int scopeIndex = 0; scopeIndex < project.ScopeOfWork.Count; scopeIndex++)
{
scopeModel = new tblScopeOfWork();
scopeModel.ScopeOfWork = project.ScopeOfWork[scopeIndex].ScopeOfWorkName;
scopeModel.ProjectId = recentProjectId;
db.tblScopeOfWorks.Add(scopeModel);
db.SaveChanges();
//Get the recently created ScopeOfWorkId
var recentScopeOfWorkId = db.tblScopeOfWorks.OrderByDescending(x => x.ScopeOfWorkId).FirstOrDefault().ScopeOfWorkId;
//Get all materials from its corresponding ScopeOfWork and save to database
for (int materialIndex = 0; materialIndex < project.ScopeOfWork[scopeIndex].Materials.Count; materialIndex++)
{
materialModel = new tblMaterial();
materialModel.Description = project.ScopeOfWork[scopeIndex].Materials[materialIndex].MaterialName;
materialModel.Quantity = project.ScopeOfWork[scopeIndex].Materials[materialIndex].Quantity;
materialModel.Cost = project.ScopeOfWork[scopeIndex].Materials[materialIndex].Cost;
materialModel.ScopeOfWorkId = recentScopeOfWorkId;
materialModel.CategoryId = project.ScopeOfWork[scopeIndex].Materials[materialIndex].SelectedCategory;
db.tblMaterials.Add(materialModel);
}
}
db.SaveChanges();
}
project.ScopeOfWork = new List<ScopeOfWorkViewModel>
{
new ScopeOfWorkViewModel()
{
Materials = new List<MaterialsViewModel>
{
new MaterialsViewModel()
{
CategoryList = new SelectList(db.tblCategories, "CategoryId", "CategoryName")
}
}
}
};
return View(project);
}
}
The problem is I tried to put some string ('ss') on the textbox of quantity and cost to see if the validation will work and this appears The value 'ss' is not valid for Quantity and The value 'ss is not valid for Cost.but it should be Please enter proper value. And also whenever the validation occurs, the Add Material link cannot add another newMaterial.
I have tried and check these answer and also DotNetFiddle but still it has some errors.
You do not need your regex (its an int so it can only accept a number anyway). And ditto for the cost property (but why have you made it decimal if you don't allow fractions?).
The validation for the type will be performed first, and because its invalid, no further validation is performed.
Change the attribute to to a [Required]
[Range(typeof(int), "0", "999")]
[Required(ErrorMessage = "Please enter proper value")]
public int? Quantity { get; set; }
Refer also this question/answer for changing the default error message for an invalid value for a type.
As a side note, your dynamically added items will not give client side validation because you have not added the necessary data-val-* attributes. You need to inspect the html generated for the elements in the for loops and copy the html exactly, except replacing the collection indexers.
You also have an issue with your POST method because you set the ScopeOfWork property to a new collection, and wipe out all the data the user has entered before you return the view. The basic structure of your POST method should be
[HttpPost]
public ActionResult _CreateProject(ProjectViewModel project)
{
if (!ModelState.IsValid)
{
ConfigureViewModel(project);
return View(project);
}
// code to initialize your data models, save and redirect
}
private void ConfigureViewModel(ProjectViewModel model)
{
var categories = db.tblCategories;
model.CategoryList = new SelectList(categories , "CategoryId", "CategoryName");
foreach (var scope in model.ScopeOfWork)
{
foreach (var material in scope.Materials)
{
material.CategoryList = new SelectList(categories , "CategoryId", "CategoryName");
}
}
}
Note the ConfigureviewModel() method is also called from your GET method to populate the SelectLists
Model is list here while clicking on submit button Radio button and checkbox values get null
#foreach (var item in Model)
{
#Html.HiddenFor(m => m[Countid].ActivityType)
<div class=" ">
<div class="clear">
</div>
#Html.Label("Group Name", "Group Name", new { #class = "control-label col-md-2", #style = "font-weight:700" })
<label class="control-label col-md-2"> : #item.PfpActivityGroup.ActivityGroupName</label>
</div>
<div class="">
#Html.Label("Activity Type", "Activity Type", new { #class = "control-label col-md-2", #style = "font-weight:700" })
<label class="control-label col-md-2"> : #item.ActivityType</label>
<div class="clear">
</div>
</div>
if (item.PfpQsnCreationMasters != null)
{
<div class=" ">
<label for="ActivityType" class="field-label">
Question Description
</label>
<label class="control-label col-md-2"> : #item.PfpQsnCreationMasters.SurveyDesc</label>
<div class="clear">
</div>
#Html.HiddenFor(m => m[Countid].PfpQsnCreationMasters.SurveyDesc)
#Html.DropDownList("NoOfOptions", ViewData["NoOfOptions"] as SelectList, new { #class = "hide" })
#Html.DropDownListFor(m => #item.PfpQsnCreationMasters.QuestionType, ViewData["QuestionType"] as SelectList, new { #class = "hide" })
#if (item.Type == "TextBox")
{
<div id="divTextBox">
#Html.TextBoxFor(x => item.txtQsnDesc);
#Html.HiddenFor(x => item.txtQsnDesc)
<div class="clear">
</div>
</div>
}
#if (item.Type == "RedioButton")
{
<div >
#if (item.option1 != null)
{
#Html.RadioButtonFor(x => item.RadioOptionSelected, #item.option1)
<label class="control-label col-md-2"> #item.option1</label>
<div class="clear">
</div>
}
#if (item.option2 != null)
{
#Html.RadioButtonFor(x => item.RadioOptionSelected, #item.option2)
<label class="control-label col-md-2"> #item.option2</label>
<div class="clear">
</div>
}
#if (item.option3 != null)
{
#Html.RadioButtonFor(x => item.RadioOptionSelected, #item.option3)
<label class="control-label col-md-2"> #item.option3</label>
<div class="clear">
</div>
}
#if (item.option4 != null)
{
#Html.RadioButtonFor(x => item.RadioOptionSelected, #item.option4)
<label class="control-label col-md-2"> #item.option4</label>
<div class="clear">
</div>
}
#Html.HiddenFor(x => item.RadioOptionSelected)
</div>
}
#if (item.Type == "CheckBox")
{
<div id="divCheckBox">
#if (item.ListTextBox1 != null)
{
#Html.CheckBoxFor(x => item.IsOption1Selected) <label class="control-label col-md-2"> #item.ListTextBox1</label>
#Html.HiddenFor(x => item.IsOption1Selected)
<div class="clear">
</div>
}
#if (item.ListTextBox2 != null)
{
#Html.CheckBoxFor(x => item.IsOption2Selected) <label class="control-label col-md-2"> #item.ListTextBox2</label>
#Html.HiddenFor(x => item.IsOption2Selected)
<div class="clear">
</div>
}
#if (item.ListTextBox3 != null)
{
#Html.CheckBoxFor(x => item.IsOption3Selected) <label class="control-label col-md-2"> #item.ListTextBox3</label>
#Html.HiddenFor(x => item.IsOption3Selected)
<div class="clear">
</div>
}
#if (item.ListTextBox4 != null)
{
#Html.CheckBoxFor(x => item.IsOption4Selected) <label class="control-label col-md-2"> #item.ListTextBox4</label>
#Html.HiddenFor(x => item.IsOption4Selected)
<div class="clear">
</div>
}
</div>
}
</div>
}
<div class="clear">
</div>
<br />
Countid = Countid + 1;
}
I would ordinarily add this as a comment but I lack the +50 rep
Try putting this on the Model value of the checkbox:
public class mymodel {
[DisplayFormat(ConvertEmptyStringToNull = false)]
public bool mycheckboxvalue { get; set; }
}