How to data list to model and model's data send with one post process from view to controller? - model-view-controller

My model(dto);
public class DTOExample
{
#region Properties
[Required(ErrorMessage = "Required")]
[DataType(DataType.Text)]
[Display(Name = "Name")]
public string Name{ get; set; }
[Required(ErrorMessage = "Required")]
[StringLength(12, ErrorMessage = "{0} alanı en az {1}, en çok {2} karakter olabilir.", MinimumLength = 12)]
[DataType(DataType.Text)]
[Display(Name = "Last Name")]
public string LastName{ get; set; }
[Display(Name = "Send Information")]
public List<DTOSendInformations> ListSend { get; set; }
}
public class DTOSendInformations
{
[Display(Name = "AdressOne")]
[Required(ErrorMessage = "Zorunlu alan")]
[StringLength(50, ErrorMessage = "{0} min {2}, max {1}", MinimumLength = 1)]
[DataType(DataType.Text)]
public string AdressOne{ get; set; }
[Display(Name = "AdressTwo")]
[StringLength(11, ErrorMessage = "{0} min {2}, max {1} karakter olabilir.", MinimumLength = 10)]
[DataType(DataType.Text)]
public string AdressTwo{ get; set; }
}
My View (I have written the necessary parts)
<div class="row">
<div class="col-md-6">
<div class="row">
<div class="col-md-4">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label" })
</div>
<div class="col-md-8">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="col-md-6">
<div class="row">
<div class="col-md-4">
#Html.LabelFor(model => model.LastName, htmlAttributes: new { #class = "control-label" })
</div>
<div class="col-md-8">
#Html.EditorFor(model => model.LastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.ParcaliAlisIzinGostergesi, "", new { #class = "text-danger" })
</div>
</div>
</div>
</div><br />
//I have a table,for AdressOne and AdressTwo,I can enter data dynamically int he view
<table id="tableSendInformation" class="table" cellpadding="0" cellspacing="0">
<thead>
<tr>Send Information Detail</tr>
<tr>
<th style="width:150px">AdressOne</th>
<th style="width:250px">AdressTwo</th>
<th></th>
</tr>
</thead>
<tbody></tbody>
<tfoot>
#{
for (int i = 0; i < Model.ListSend.Count; i++)
{
<tr>
<td>
#Html.EditorFor(l => l.ListSend [i].AdressOne)
</td>
<td>
#Html.EditorFor(l => l.ListSend [i].AdressTwo)
</td>
</tr>
}
}
</tfoot>
</table>
//my buttons;
<div class="float-right"> // my button(for AdressOne and AdressTwo)
<div class="col-md-offset-8">
<input type="button" value="Add" class="btn btn-primary" name="Add" id="Add"/>
</div>
</div>
<div class="col-md-offset-8"> //my submit button
<input type="submit" value="Save" id="buttonSave" class="btn btn-primary" name="buttonSave" />
</div>
I want Name,LastName, AdressOne,AdressTwo(multiple records) data, when you click the button(submit buton=>buttonSave) all of this information send from view to controller(I want to submit at the same time).
I want to send both my data and list in the model with a single post.
How can I do that?

Related

How to get DropDownList SelectedValue to update Database

I finally was able to get cascading drowdownlist working but I can not get the values to update the database table.
Controller
public IActionResult Create()
{
var strRowWid = "RowWid";
var strDt = "Dt";
var dateNow = DateOnly.FromDateTime(DateTime.Now);
//Date Dropdown
ViewBag.DateWid = new SelectList(_context.TblDays.OrderByDescending(x => x.Dt).Where(n => n.Dt <= dateNow), strRowWid, strDt);
//Ammo Type dropdown
ViewBag.ammo = _context.VwAmmos.OrderBy(n => n.Caliber)
.Select(n => new SelectListItem
{
Value = n.RowWid.ToString(),
Text = n.WeaponType.ToString() + " " + n.Caliber.ToString() + " " + n.Brand.ToString() + " " + n.Style.ToString(),
}).ToList();
return View();
}
HTML
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
#Html.LabelFor(model => model.TblUsed.DateWid, htmlAttributes: new { #class = "control-label"})
<div>
#Html.DropDownList("DateWid", ViewBag.DateWid as SelectList, "--select date--", new { #class = "form-control form-select-sm form-select" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TblUsed.AmmoWid, htmlAttributes: new { #class = "control-label"})
<div>
#Html.DropDownList("AmmoWid",ViewBag.ammo, "--select Ammo--", new { #class = "form-control form-select-sm form-select" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TblUsed.StoreWid, htmlAttributes: new { #class = "control-label"})
<div>
#Html.DropDownList("StoreWid",new SelectList(string.Empty,"StoreWid","StoreName"), new { #class = "form-control form-select-sm form-select" })
</div>
</div>
<div class="form-group">
<label asp-for="#Model.TblUsed.QtyUsed" class="control-label"></label>
<input asp-for="#Model.TblUsed.QtyUsed" class="form-control" />
<span asp-validation-for="#Model.TblUsed.QtyUsed" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
Javascript for the cascade
<script>
$('#AmmoWid').change(function () {
$('#StoreWid').empty();
$.ajax({
url: "#Url.Action("GetStore")",
type: "Get",
data: { id: $('#AmmoWid option:selected').val() },
dataType:"json",
success: function (result) {
$.each(result, function (i,Store) {
$('#StoreWid').append('<option value="' + Store.value + '">' + Store.text+'</option>')
})
}
})
})
</script>
When I select the values from the dropdownlist and submit they do not update the database table. It appears that they are not binded correctly.
I don't know what to try at this point.
When doing them like this I can get them to update but then I can't do the cascading.
<div class="form-group col-2">
<select asp-for="#Model.TblPurchase.AmmoWid" class="form-control form-select-sm form-select" asp-items="#Model.Ammo">
<option value="">Select Ammo</option>
</select>
<span asp-validation-for="#Model.TblPurchase.AmmoWid" class="text-danger"></span>
</div>
Create Post
// POST: Useds/Create
// To protect from overposting attacks, enable the specific properties you want to bind to.
// For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("RowWid,DateWid,AmmoWid,QtyUsed,StoreWid")] TblUsed tblUsed)
{
if (ModelState.IsValid)
{
_context.Add(tblUsed);
await _context.SaveChangesAsync();
return RedirectToAction(nameof(Index));
}
return View(tblUsed);
}
TblUsed Model
namespace Ammo.Models;
public partial class TblUsed
{
[Key]
public int RowWid { get; set; }
[ForeignKey("TblDay")]
[DisplayName("Date")]
public int DateWid { get; set; }
[ForeignKey("TblAmmunition")]
[DisplayName("Ammo")]
public int AmmoWid { get; set; }
public int QtyUsed { get; set; }
[ForeignKey("TblStore")]
[DisplayName("Store")]
public int StoreWid { get; set; }
}
VwAmmo Model
namespace Ammo.Models;
public partial class VwAmmo
{
public int RowWid { get; set; }
public string? WeaponType { get; set; }
public string? Caliber { get; set; }
public string Brand { get; set; } = null!;
public string Style { get; set; } = null!;
public int? Grain { get; set; }
public int? FtS { get; set; }
public decimal? ShellSize { get; set; }
public string? ShotType { get; set; }
public string? Shot { get; set; }
public decimal? GrainLoad { get; set; }
}
The reason why you couldn't get the tblUsed value is you used the wrong name for your attribute.
I suggest you could try to modify as below and then test. Besides, there is no need to put the bind attribute again.
View codes:
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
#Html.LabelFor(model => model.TblUsed.DateWid, htmlAttributes: new { #class = "control-label"})
<div>
#Html.DropDownList("TblUsed.DateWid", ViewBag.DateWid , "--select date--", new { #class = "form-control form-select-sm form-select" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TblUsed.AmmoWid, htmlAttributes: new { #class = "control-label"})
<div>
#Html.DropDownList("TblUsed.AmmoWid",ViewBag.ammo, "--select Ammo--", new { #class = "form-control form-select-sm form-select" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TblUsed.StoreWid, htmlAttributes: new { #class = "control-label"})
<div>
#Html.DropDownList("TblUsed.StoreWid",new SelectList(string.Empty,"StoreWid","StoreName"), new { #class = "form-control form-select-sm form-select" })
</div>
</div>
<div class="form-group">
<label asp-for="#Model.TblUsed.QtyUsed" class="control-label"></label>
<input asp-for="#Model.TblUsed.QtyUsed" class="form-control" />
<span asp-validation-for="#Model.TblUsed.QtyUsed" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
#section Scripts{
<script>
$('#TblUsed_AmmoWid').change(function () {
$('#TblUsed_StoreWid').empty();
$.ajax({
url: "#Url.Action("GetStore")",
type: "Get",
data: { id: $('#TblUsed_AmmoWid option:selected').val() },
dataType:"json",
success: function (result) {
$.each(result, function (i,Store) {
$('#TblUsed_StoreWid').append('<option value="' + Store.value + '">' + Store.text+'</option>')
})
}
})
})
</script>
}

Validation error working wit ASP.NET MVC .NET FRAMEWORK

your text
I added validation to my ASP.NET MVC .NET FRAMEOWRK project and get this error:
your text
Unable to cast object of type 'System.Int32' to type 'System.String'.
My project connect to data base with one table.
my code:
Customer.cs:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ConnectToDB
{
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
public partial class Customers : IValidatableObject
{
[StringLength(1000, ErrorMessage = "Queue number must be no more than 1000 digits")]
[Required(ErrorMessage = "Queue number is required")]
[DataType(DataType.Text)]
[DisplayName("Queue number")]
public int queueNumber { get; set; }
[StringLength(30, ErrorMessage = "First name must be no more tha 1000 letters")]
[RegularExpression("^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$")] // RegEx: Used to validate a person name
[Required(ErrorMessage = "First name is required")]
[DisplayName("First name")]
[DataType(DataType.Text)]
public string firstName { get; set; }
[StringLength(30, ErrorMessage = "Last name must be no more tha 1000 letters")]
[RegularExpression("^[a-zA-Z]+(([',. -][a-zA-Z ])?[a-zA-Z]*)*$")] // RegEx: Used to validate a person name
[Required(ErrorMessage = "Last name is required")]
[DisplayName("Last name")]
[DataType(DataType.Text)]
public string lastName { get; set; }
[Required(ErrorMessage = "Time customer enter is required")]
[DisplayName("Time customer enter")]
[DataType(DataType.Time)]
public Nullable<System.TimeSpan> timeCusEnter { get; set; }
// Validation for queue number using IValidatableObject interface:
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
List<ValidationResult> errors = new List<ValidationResult>();
if (queueNumber < 0)
{
errors.Add(new ValidationResult("Queue number can not be negative.", new List<string> { "queueNumber" }));
}
return errors;
}
}
}
addCustomer.cshtml:
#model ConnectToDB.Customers
#{
ViewBag.Title = "addCustomer";
}
<link rel="stylesheet" href="~/CSS/addCusDesign.css" />
<link rel="stylesheet" href="~/CSS/Local.css" />
<body>
#*Menu:*#
<div class="navBar">
<span class="navItem">
#Html.ActionLink("Dequeue to the queue", "addCustomer")
</span>
<span class="navItem">
#Html.ActionLink("Customers list", "customersList")
</span>
</div>
<h2>Enqueue</h2>
<span id="secondTitle">Fill in the following details, then press the button and enter the queue.<br>Have a good day :)</span>
<br />
<br />
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Customers</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.queueNumber, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.queueNumber, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.queueNumber)
</div>
</div>
<br />
<div class="form-group">
#Html.LabelFor(model => model.firstName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.firstName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.firstName)
</div>
</div>
<br />
<div class="form-group">
#Html.LabelFor(model => model.lastName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.lastName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.lastName)
</div>
</div>
<br />
<div class="form-group">
#Html.LabelFor(model => model.timeCusEnter, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.timeCusEnter, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.timeCusEnter)
</div>
</div>
<br />
<br />
#Html.ValidationSummary(true, "Add customer was unsuccessful. Please coorect the following errors: ")
#*Dequeue customer to the queue input: *#
<div class="form-group">
<div class="GetInTheQueue">
<input type="submit" value="GET IN THE QUEUE" class="btn btn-default" />
</div>
</div>
</div>
}
<br />
<br />
#*Carusel in boostrap: *#
<!-- #region Carusel -->
<div id="carouselExampleFade" class="carousel slide carousel-fade" data-bs-ride="carousel">
<div class="carousel-inner">
<div class="carousel-item active">
<img src="~/Images/image1.jpeg" class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="~/Images/image2.png" class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="~/Images/Image3.jpeg" class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="~/Images/Image4.jpeg" class="d-block w-100" alt="...">
</div>
<div class="carousel-item">
<img src="~/Images/Image5.jpeg" class="d-block w-100" alt="...">
</div>
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleFade" data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#carouselExampleFade" data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
<!-- #endregion -->
<br />
<br />
#*Images: *#
<!-- #region Images -->
<div class="images">
<img width="200" height="200" src="~/Images/image1.jpeg" alt="Queue image1" />
<img width="200" height="200" src="~/Images/image2.png" alt="Queue image2" />
<img width="200" height="200" src="~/Images/Image3.jpeg" alt="Queue image3" />
<img width="200" height="200" src="~/Images/Image4.jpeg" alt="Queue image4" />
<img width="200" height="200" src="~/Images/Image5.jpeg" alt="Queue image5" />
</div>
<!-- #endregion -->
</body>
Would appreciate help
The validation work for me yesterday, but today not working.

Error with expressive annotations requiredif validator

This is my view
<div id="Domain">
<ul class="formlist">
<li class="width100">
<div class="form-check form-check-inline">
<label class="form-check-label">
#Html.RadioButtonFor(model => model.domain_flag, 1, new { #class = "form-check-input" }) <span>Yes</span>
</label>
</div>
<div class="form-check form-check-inline">
<label class="form-check-label">
#Html.RadioButtonFor(model => model.domain_flag, 0, new { #class = "form-check-input", #checked = "checked" }) <span>No</span>
</label>
</div>
</li>
</ul>
<ul class="formlist">
<li>
<div class="frm-marg-b">
<label class="label"><b>#Html.LabelFor(model => model.domain_renew_date)</b></label>
<div class="textbx">
<div class="input-group">
#Html.TextBoxFor(model => model.domain_renew_date, new { #type = "datetime", #class = "form-control" })
#Html.ValidationMessageFor(model => model.domain_renew_date, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="frm-marg-b">
<label class="label"><b>#Html.LabelFor(model => model.domain_vendor_id)</b></label>
<div class="textbx">
#Html.DropDownListFor(model => model.domain_vendor_id, Model.domain_Vendor, "Please Select")
#Html.ValidationMessageFor(model => model.domain_vendor_id, "", new { #class = "text-danger" })
</div>
</div>
</li>
<li>
<div class="frm-marg-b">
<label class="label"><b>#Html.LabelFor(model => model.domain_exp_date)</b></label>
<div class="textbx">
<div class="input-group">
#Html.TextBoxFor(model => model.domain_exp_date, new { #type = "datetime", #class = "form-control" })
#Html.ValidationMessageFor(model => model.domain_exp_date, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="frm-marg-b">
<label class="label"><b>#Html.LabelFor(model => model.domain_amt)</b></label>
<div class="textbx">
#Html.EditorFor(model => model.domain_amt, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.domain_amt, "", new { #class = "text-danger" })
</div>
</div>
</li>
<li class="width100">
<div class="frm-marg-b">
<label class="label"><b>#Html.LabelFor(model => model.domain_remarks)</b></label>
<div class="textbx3">
#Html.TextAreaFor(model => model.domain_remarks, new { htmlAttributes = new { #class = "form-control", #rows = 2 } })
#Html.ValidationMessageFor(model => model.domain_remarks, "", new { #class = "text-danger" })
</div>
</div>
</li>
</ul>
</div>
My model
public int? domain_flag { get; set; }
[Display(Name = "Date of Renewal")]
[DataType(DataType.Date)]
[RequiredIf("domain_flag==1",ErrorMessage ="Enter Renew Date")]
public DateTime? domain_renew_date { get; set; }
[Display(Name = "Date of Expiry")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:mm/dd/yy}", ApplyFormatInEditMode = true)]
[RequiredIf("domain_flag==1", ErrorMessage = "Enter Expiry Date")]
public DateTime? domain_exp_date { get; set; }
[Display(Name = "Vendor")]
[RequiredIf("domain_flag==1", ErrorMessage = "Please Select Vendor")]
public int? domain_vendor_id { get; set; }
[Display(Name = "Amount(Rs.)")]
[RequiredIf("domain_flag==1", ErrorMessage = "Enter Amount")]
[RegularExpression("^[0-9]+$", ErrorMessage = "Enter Numeric Values")]
public decimal? domain_amt { get; set; }
[Display(Name = "Comments")]
public string domain_remarks { get; set; }
Global.asax
DataAnnotationsModelValidatorProvider.RegisterAdapter(
typeof(RequiredIfAttribute), typeof(RequiredIfValidator));
DataAnnotationsModelValidatorProvider.RegisterAdapter(
typeof(AssertThatAttribute), typeof(AssertThatValidator));
In this as soon as I select the radio button the required if error messages are displayed before entering the values. The error messages should be displayed on click of submit button before posting to the server. Is this possible with expressive annotations nuget package?
Yes it's possible with ExpressiveAnnotations.
#jwaliszko mentioned it.
You have to set the configuation of ea like this at client-side:
<script>
ea.settings.dependencyTriggers = '';

Partialview not returning model for a sortedlist

I am very, very new to MVC, so please bear with my question, I have to work with the following structure.
I have the following models, Facility and Address. Facility contains a SortedList of Address, I have reduced the number of properties for clarity,
public class AppFacility
{
public AppFacility()
{
this.Addresses = new SortedList<string, AppAddress>();
}
public SortedList<string, AppAddress> Addresses { get; set; }
[DisplayNameAttribute("Facility ID")]
public int FacilityID { get; set; }
[Required(ErrorMessage = "Facility Name is a required field")]
[DisplayNameAttribute("Facility Name")]
public string FacilityName { get; set; }
[DisplayNameAttribute("Doing Business As")]
public string Dba { get; set; }
[DisplayNameAttribute("Nbr. Of Employees")]
public int NbrOfEmployees { get; set; }
}
public class AppAddress
{
[DisplayNameAttribute("City")]
public string City { get; set; }
[DisplayNameAttribute("State")]
public string State { get; set; }
[DisplayNameAttribute("Street Name")]
public string StreetName { get; set; }
}
Controller:
[HttpPost]
public ActionResult FacilityCreate(AppFacility objFacility)
{
facilityManager = new Manager.AppFacilityManager();
if (facilityManager.InsertAppFacility(objFacility))
{
return RedirectToAction("FacilityInfo", new { id = objFacility.FacilityID });
}
return View((AppFacility)Session["FacilityObject"]);
}
View:
FacilityCreate
#model Model.CORE.BO.AppFacility
<table width="100%" align="center" border="0" class="SectionTables">
<tr>
<td class="SubtitleHeader">
Facility
</td>
</tr>
<tr>
<td class="SubtitleHeader1">
Enter Facility Information
</td>
</tr>
<tr>
<td align="center">
#Html.Partial(p_CreateEditAppFacility, Model)
</td>
</tr>
Partial view:
p_CreateEditAppFacility:
This contains the p_CreateEditAddress partial view as well.
#model Model.CORE.BO.AppFacility
#using (Html.BeginForm("FacilityCreate", "Form", FormMethod.Post,
new { id = "saveForm", name = "saveForm" }))
{
#Html.ValidationSummary(true)
<div class="main">
<fieldset>
<legend>Operator Information</legend>
<div class="editor-label">
#Html.Label("Facility Name (Business Name of Operator to Appear): ")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FacilityName)
#Html.ValidationMessageFor(model => model.FacilityName)
</div>
<div class="editor-label">
#Html.Label("Owner's Business Name (If different from Business Name of Operator): ")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Dba)
#Html.ValidationMessageFor(model => model.Dba)
</div>
<div class="editor-label">
#Html.Label("No of Employees:")
</div>
<div class="editor-field">
#Html.EditorFor(model => model.NbrOfEmployees)
#Html.ValidationMessageFor(model => model.NbrOfEmployees)
</div>
</fieldset>
<fieldset>
<legend>Address Information</legend>
#{
int i = 0;
foreach (KeyValuePair<string, Model.CORE.BO.AppAddress> addressRow in Model.Addresses)
{
<div class="editor-field">
#Html.Partial(p_CreateEditAddress, addressRow.Value, new ViewDataDictionary(Html.ViewDataContainer.ViewData) { TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = string.Format("objFacility.Addresses[{0}]", i) } })
</div>
i++;
}
}
</fieldset>
<p>
<input id="SaveFacility" name="SaveInfo" type="submit" value="Save Information" />
</p>
</div>
}
PartialView:
p_CreateEditAddress
#model Model.CORE.BO.AppAddress
#Html.ValidationSummary(true)
<div class="editor-label">
#Html.LabelFor(model => model.StreetName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.StreetName)
#Html.ValidationMessageFor(model => model.StreetName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.City)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.City)
#Html.ValidationMessageFor(model => model.City)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.State)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.State)
#Html.ValidationMessageFor(model => model.State)
</div>
My question is that in the Controller the objFacility.Addresses does not get the values entered for the model AppAddress, it is always null. The AppFacility gets populated though.
The html behind looks like this for p_CreateEditAddress
<div class="editor-field">
<input class="text-box single-line"
id="objFacility_Addresses_0__StreetName"
name="objFacility.Addresses[0].StreetName" type="text" value="" />
<span class="field-validation-valid"
data-valmsg-for="objFacility.Addresses[0].StreetName" data-valmsg-replace="true"></span>
</div>
Please help.
You just need to change your Partial View call to take the correct prefix. You don't give it the Model name as the default model binder will be creating an instance of your class and looking for fields that match the names of the items in the Request.Form collection. It knows nothing about the variable name you've gave your model, just the properties of your Model's class.
Try this (I put line breaks in for readability):
#Html.Partial(p_CreateEditAddress, addressRow.Value,
new ViewDataDictionary(Html.ViewDataContainer.ViewData) {
TemplateInfo = new System.Web.Mvc.TemplateInfo {
HtmlFieldPrefix = string.Format("Addresses[{0}]", i)
}
})
I guess the generated HTML is not proper for model binding.
It should not be objFacility.Addresses[0].StreetName but Addresses[0].StreetName.

Select tab containing controls with validation errors

I have found something close to what I want to do here but not exactly.
I want to find the first tab that has a control which has a validation error and make that tab selected.
I have the JQUERY working to clicked through the tabs with next and previous links, now if I can just get to the tab with the validation errors that would be great.
MVC3 DataAnnotations are doing the validation. Any suggestion would be greatful. Note: I did shorten the model and view code.
What I want to do is when the button is clicked to "submit" the form and the validation is performed if any validation errors occurr then I would like the the first tab in the lists of tabs with a control that has a validation error to be selected.
Here is the view model.
public class RegistrationViewModel
{
[Required(ErrorMessageResourceType = typeof(ValidationMessages), ErrorMessageResourceName = "Required")]
[StringLength(50, ErrorMessageResourceType = typeof(ValidationMessages), ErrorMessageResourceName = "StringLength")]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[StringLength(100, ErrorMessageResourceType = typeof(ValidationMessages), ErrorMessageResourceName = "StringLength")]
[Display(Name = "Street")]
public string Street1 { get; set; }
public IEnumerable<SelectListItem> SecurityQuestionOneList { get; set; }
[Required(ErrorMessageResourceType = typeof(ValidationMessages), ErrorMessageResourceName = "Required")]
[Remote("DistinctSecurityQuestionOne", "Validation", AdditionalFields = "SecurityQuestionTwo, SecurityQuestionThree", ErrorMessageResourceType = typeof(ValidationMessages), ErrorMessageResourceName = "DistinctSecurityQuestions")]
public string SecurityQuestionOne { get; set; }
[Required(ErrorMessageResourceType = typeof(ValidationMessages), ErrorMessageResourceName = "Required")]
[StringLength(200, ErrorMessageResourceType = typeof(ValidationMessages), ErrorMessageResourceName = "StringLength")]
public string SecurityQuestionOneAnswer { get; set; }
}
Here is the code I have in my view.
#model SteadyPayCustomer.Models.RegistrationViewModel
#using Resources;
#{
ViewBag.Title = "Register";
}
<h2>Create a New Account</h2>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/jquery-ui.min.js" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function () {
var $tabs = $('#tabs').tabs();
$(".ui-tab-panel").each(function (i) {
var totalTabs = $(".ui-tab-panel").size() - 1;
if (i != totalTabs) {
next = i + 2;
$(this).append("<a href='#' class='next-tab mover' rel='" + next + "'>Next Step »</a>");
}
if (i != 0) {
previous = i;
$(this).append("<a href='#' class='previous-tab mover' rel='" + previous + "'>« Previous Step</a>");
}
});
$(".next-tab, .previous-tab").click(function () {
$tabs.tabs('select', $(this).attr("rel"));
return false;
});
});
</script>
<div id="tabs">
<ul id="tabstyle">
<li><span style="color:#000000;font-weight:bold;font-size:12px">User</span></li>
<li><span style="color:#000000;font-weight:bold;font-size:12px">Contact</span></li>
<li><span style="color:#000000;font-weight:bold;font-size:12px">Security</span></li>
</ul>
#using (Html.BeginForm())
{
#Html.ValidationSummary(true)
<div id="fragment-1" class="ui-tab-panel">
<fieldset>
<legend>User Information</legend>
<div class="editor-label">
#Html.Label(UserViewText.FirstNameLabel)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
</fieldset>
</div>
<div id="fragment-2" class="ui-tab-panel">
<fieldset>
<legend>Customer Information</legend>
<div class="editor-label">
#Html.Label(CustomerGeneralViewText.Street1Label)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Street1)
#Html.ValidationMessageFor(model => model.Street1)
</div>
</fieldset>
</div>
<div id="fragment-3" class="ui-tab-panel">
<fieldset>
<legend>Security Questions</legend>
<div class="editor-label">
#Html.Label(SecurityQuestionsViewText.SecurityQuestionOneLabel)
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.SecurityQuestionOne, Model.SecurityQuestionOneList, string.Empty, Model.SecurityQuestionOne)
#Html.ValidationMessageFor(model => model.SecurityQuestionOne)
</div>
<div class="editor-label">
#Html.Label(SecurityQuestionsViewText.SecurityQuestionOneAnswerLabel)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.SecurityQuestionOneAnswer)
#Html.ValidationMessageFor(model => model.SecurityQuestionOneAnswer)
</div>
<p>
<input type="submit" value="#General.FinishButtonText" />
</p>
</fieldset>
</div>
}
</div>

Resources