I have a form that a user needs to fill out. If they enter the correct values for all required fields including the "Date of Birth" and "Total number of persons to occupy apartment" the values they entered are removed during a Page Postback.
This occurs if the user fails to click on the checkbox to accept the terms and conditions. All other values including DropDownList values retain their selected values on Post-back except for the "Date of Birth" and "Total number of persons to occupy apartment".
How can I figure this out?
Application Model
public class Application
{
public int ApplicationId { get; set; }
public string AppFirstName { get; set; }
public string AppLastName { get; set; }
public DateTime AppDateOfBirth { get; set; }
public int AppTotalPersonsOccupy { get; set; }
public bool AppAgreeToTerms { get; set; }
public int StateId { get; set; }
public State State { get; set; }
}
ApplicationFormViewModel
public class ApplicationFormViewModel
{
[Required(ErrorMessage = "First Name is required")]
[Display(Name = "First Name")]
[StringLength(25)]
[MaxLength(25)]
public string AppFirstName { get; set; }
[Required(ErrorMessage = "Last Name is required")]
[Display(Name = "Last Name")]
[StringLength(25)]
[MaxLength(25)]
public string AppLastName { get; set; }
[Required(ErrorMessage = "Please make a selection")]
[Display(Name = "State")]
public int StateId { get; set; }
public IEnumerable<SelectListItem> States { get; set; }
[Required(ErrorMessage = "Date of Birth is required")]
[Display(Name = "Date of Birth")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
[DataType(DataType.Date)]
public DateTime AppDateOfBirth { get; set; }
[Required(ErrorMessage = "Total number of persons to occupy apartment is required")]
[Display(Name = "Total number of persons to occupy apartment")]
[Range(1, 10, ErrorMessage = "Must be between 1 to 10")]
public int AppTotalPersonsOccupy { get; set; }
//[Required(ErrorMessage = "You must exept terms to continue")]
[Display(Name = "I agree to the pre rental application terms & conditions")]
//[Range(typeof(bool), "false", "false", ErrorMessage = "You must accept the Terms")]
[Controllers.ApplicationController.CheckBoxRequired(ErrorMessage = "You must agree to the terms and condtions!")]
public bool AppAgreeToTerms { get; set; }
}
ApplicationController
public class ApplicationController : Controller
{
private readonly ApplicationDbContext _db;
public ApplicationController(ApplicationDbContext db)
{
_db = db;
}
// GET: /<controller>/
public IActionResult Index()
{
return View();
}
public class CheckBoxRequired : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
//get the entered value
var application = (ApplicationFormViewModel)validationContext.ObjectInstance;
//Check whether the IsAccepted is selected or not.
if (application.AppAgreeToTerms == false)
{
//if not checked the checkbox, return the error message.
return new ValidationResult(ErrorMessage == null ? "You must agree to the terms and condtions!" : ErrorMessage);
}
return ValidationResult.Success;
}
}
// GET: /Create
public IActionResult Create()
{
ApplicationFormViewModel renterdropdownvm = new ApplicationFormViewModel()
{
States = _db.States.Select(i => new SelectListItem
{
Text = i.StateInt,
Value = i.StateId.ToString()
}),
};
return View(renterdropdownvm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(ApplicationFormViewModel applicationVM)
{
if (ModelState.IsValid)
{
var applicationObj = new Application();
{
applicationObj.AppFirstName = applicationVM.AppFirstName;
applicationObj.AppLastName = applicationVM.AppLastName;
applicationObj.StateId = applicationVM.StateId;
applicationObj.AppDateOfBirth = applicationVM.AppDateOfBirth;
applicationObj.AppTotalPersonsOccupy = applicationVM.AppTotalPersonsOccupy;
applicationObj.AppAgreeToTerms = applicationVM.AppAgreeToTerms;
}
_db.Applications.Add(applicationObj);
await _db.SaveChangesAsync();
var newlyCreatedId = applicationObj.ApplicationId;
return RedirectToAction(nameof(Confirmation), new { id = newlyCreatedId });
}
// re-populate the dropdown field here before returning the view
ApplicationFormViewModel applicationvmrepopulate = new ApplicationFormViewModel()
{
States = _db.States.Select(i => new SelectListItem
{
Text = i.StateInt,
Value = i.StateId.ToString()
}),
};
return View(applicationvmrepopulate);
}
// GET: Application/Confirmation/id
public async Task<IActionResult> Confirmation(int? id)
{
if (id == null)
{
return NotFound();
}
var appconfirm = await _db.Applications.SingleOrDefaultAsync(m => m.ApplicationId == id);
if (appconfirm == null)
{
return NotFound();
}
return View(appconfirm);
}
}
Create View
<form method="post" asp-action="Create">
<div >
<label asp-for="AppFirstName" ></label>
<input asp-for="AppFirstName" />
<span asp-validation-for="AppFirstName" ></span>
</div>
<div >
<label asp-for="AppLastName" ></label>
<input asp-for="AppLastName" />
<span asp-validation-for="AppLastName" ></span>
</div>
<div >
<label asp-for="StateId" ></label>
<select asp-for="StateId" asp-items="@Model.States" >
<option></option>
</select>
<span asp-validation-for="StateId" ></span>
</div>
<div >
<label asp-for="AppDateOfBirth" ></label>
<input asp-for="AppDateOfBirth" type="date" value="" />
<span asp-validation-for="AppDateOfBirth" ></span>
</div>
<div >
<label asp-for="AppTotalPersonsOccupy" ></label>
<input asp-for="AppTotalPersonsOccupy" type="number" value="" />
<span asp-validation-for="AppTotalPersonsOccupy" ></span>
</div>
<p >“I AGREE TO THE TERMS AND CONDITIONS”</p>
<div >
<input asp-for="AppAgreeToTerms" >
<label asp-for="AppAgreeToTerms" ></label>
<span asp-validation-for="AppAgreeToTerms" ></span>
</div>
<div >
<input type="submit" value="Submit Rental Application" />
</div>
CodePudding user response:
This occurs if the user fails to click on the checkbox to accept the terms and conditions. All other values including DropDownList values retain their selected values on Post-back except for the "Date of Birth" and "Total number of persons to occupy apartment.
After a lot of investigation and research, I am able to find the issue
in your code. You have set the value empty as value=""
while the
page has been reloaded which is not correct.
Solution:
You should modify a few of the properties within your existing code at "Create View" as below:
Instead Of
<div >
<label asp-for="AppDateOfBirth" ></label>
<input asp-for="AppDateOfBirth" type="date" value="" />
<span asp-validation-for="AppDateOfBirth" ></span>
</div>
<div >
<label asp-for="AppTotalPersonsOccupy" ></label>
<input asp-for="AppTotalPersonsOccupy" type="number" value="" />
<span asp-validation-for="AppTotalPersonsOccupy" ></span>
</div>
Note: Setting value=""
as empty for your two-property AppDateOfBirth
and AppTotalPersonsOccupy
causing the removal of
this two input fields during post-back action.
Replace With
<div >
<label asp-for="AppDateOfBirth" ></label>
<input asp-for="AppDateOfBirth" type="date" />
<span asp-validation-for="AppDateOfBirth" ></span>
</div>
<div >
<label asp-for="AppTotalPersonsOccupy" ></label>
<input asp-for="AppTotalPersonsOccupy" type="number" />
<span asp-validation-for="AppTotalPersonsOccupy" ></span>
</div>
Output
I have tested that in my environment and it's working as expected.