Asp.NET Core Model Binding input type checkbox not remains unchecked - asp.net-core

I am facing some strange issue, I am using Asp.net Core.
I have Model class which I am binding to my razor view and here is the model implementation.
{
PatientDetailReport = new ReportModel();
itemid = true;
}
public ReportModel PatientDetailReport { get; set; }
public bool itemid { get; set; }
Report Model Class has few bool properties like
public bool IdentityNumberDisplay { get; set; }
I am trying to bind model in both of these ways as mentioned by mostly blogs and also on stackoverflow
(1) <input type="checkbox" asp-for="#Model.PatientDetailReport.IdentityNumberDisplay" />
(2) #Html.CheckBoxFor(m=>m.PatientDetailReport.IdentityNumberDisplay,new { })
</td>
but both of these cases remains unchecked.
for first case, I also tried with value=#Model.PatientDetailReport.IdentityNumberDisplay
but at jquery level I have to check it with value =True or False (as string) I am able to modify the checkbox, but the value is not posting on Controller.
Please can anyone guide me regarding to this case.
Why the case 2 is not working,however most of the blogs are saying to use like that?
Thanks

I could reproduce your problem, make sure PatientDetailReport.IdentityNumberDisplay has been set to true in your case.
Since your code does not assign value to it and the default value false results in checkbox unchecked.
You could set default value like below to have a test:
public bool IdentityNumberDisplay { get; set; } = true;
<form method="post">
#Model.PatientDetailReport.IdentityNumberDisplay
#*see the value of IdentityNumberDisplay*#
<input type="checkbox" asp-for="#Model.PatientDetailReport.IdentityNumberDisplay" />
#Html.CheckBoxFor(m=>m.PatientDetailReport.IdentityNumberDisplay,new { })
<input type="submit" value="submit" />
</form>

I resolved this issue using JQuery by checking Checkbox value from Model which is coming as 'True' in string format, and then assigned checked property to true.
#Html.CheckBoxFor(m=>m.PatientDetailReport.IdentityNumberDisplay
,new {value=Model.PatientDetailReport.IdentityNumberDisplay })
$.each($("input[type='checkbox']"), function (e) {
console.log($(this).val());
//debugger;
if ($(this).val() === 'True') {
$(this).prop('checked', true);
}
})
I am not sure it is correct or not but this resolved my issue for asp.net core model's bool property for checkbox or radio button.

Related

ASP.Net core Model's date property is blank in edit mode

I have a Razor pages web app and one of the models' is for colleague info and includes their date of birth.
When I look at the scaffolded pages for a colleague, the Date of Birth field is populated in the details page but not the edit page.
Images below will show what I mean.
Here is the Details page
And here is the Edit page
As you will know, as the Edit page is blank, If I change another field e.g. Staff Position and save, the DOB for the colleague becomes null.
As I say the pages are from the EF Core scaffolding so I believe the HTML for the form should be correct.
Edit Page HTML
<div class="form-group">
<label asp-for="Colleague.DateOfBirth" class="control-label"></label>
<input asp-for="Colleague.DateOfBirth" class="form-control" />
<span asp-validation-for="Colleague.DateOfBirth" class="text-danger"></span>
</div>
Colleague is a bind Property of the Colleague model in the Page Model. ALl other fields, as seen in the image populate fine.
Update
As I say it is using Model Binding
[BindProperty]
public Colleague Colleague { get; set; }
OnPost
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
_context.Attach(Colleague).State = EntityState.Modified;
try
{
selectedBranch = Colleague.BranchID;
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ColleagueExists(Colleague.ColleagueID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToPage("../BranchColleagues", new { id = selectedBranch });
}
[DataType(DataType.Date)]
[Display(Name = "Date of Birth")]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime? DateOfBirth { get; set; }
I also faced the same problem. It works while I use .Value in input tag
<input asp-for="Colleague.DateOfBirth.Value" class="form-control" />
I am placing my quick fix solution as the question has been empty now for a month.
By removing this annotation from the POCO class:
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
The date value now appears in the edit form as required.

Razor Pages CheckBox throwing error in Edit Page

I need some help in inserting checkbox value to mssql database and retrieving the same in edit page.
This is model class
public class RequestForm{
[Key]
public int ID { get; set; }
public string OtherCompetitorsChecked { get; set; }
public string OtherCompetitorName { get; set; }
}
This is my RequestForm.cshtml file
<div class="tr">
<div class="td">
<input id="ChkOthers" style="margin-left:40px;" asp-for="RequestForm.OtherCompetitorsChecked" type="checkbox" value="Others" /> Others
</div>
<div class="td">
<input id="CompetitorsOthersName" title="Please Fill In Other Competitor Name" asp-for="RequestForm.OtherCompetitorName" type="text" class="form-control-slp" required disabled style="width:50%" />
</div>
</div>
When checking im inserting the checkbox value into database thats why i used string datatype in model class.Im able to insert the data to the database,when im fetching the data its showing error like below
InvalidOperationException: Unexpected expression result value 'Others' for asp-for. 'Others' cannot be parsed as a 'System.Boolean'.
is there any way to fix this?
InvalidOperationException: Unexpected expression result value 'Others'
for asp-for. 'Others' cannot be parsed as a 'System.Boolean'.
public string OtherCompetitorsChecked { get; set; }
This issue relates the OtherCompetitorsChecked data type. The Input Tag Helper sets the HTML type attribute based on the .NET type. Form the following list, we can see that, for the Input checkbox, the .Net type should be Bool type.
So, to solve the above issue, change the OtherCompetitorsChecked's data type to the bool type:
public class RequestForm
{
[Key]
public int ID { get; set; }
public bool OtherCompetitorsChecked { get; set; }
public string OtherCompetitorName { get; set; }
}
Then, in the Get or Post method, when you set its value, it should be true or false.
public void OnGet()
{
RequestForm = new RequestForm() {
ID = 1001,
OtherCompetitorName = "AA",
OtherCompetitorsChecked = true
};
}
Besides, in your application, might be you want to display a list of selected items using checkbox, and want to use a string type to store the selected value. If that is the case, you could try to use the html <input type="checkbox" name ="selectedCourses"> element to display the items (without using Tag helper) or use a <select> tag, then, in the Post method, get the selected option's value via the html element's name property.
Code like this (you could change the checkbox value to the model data, model detail information, refer this tutorial):
<input type="checkbox" name="selectedCompetitorName" value="Others" />
the Post method:
public void OnPost(string selectedCompetitorName)
{
if (ModelState.IsValid)
{
var data = RequestForm;
}
}
<input id="CompetitorsOthersName" title="Please Fill In Other Competitor Name" asp-for="RequestForm.OtherCompetitorName" type="text"
class="form-control-slp" required disabled style="width:50%" />
At the end, according to the above code, I assume you want to make the CompetitorsOthersName text box readonly, if that is the case, try to remove the disabled attribute, and add the readonly attribute. Because, if using the disabled attribute, after submitting the form, the submitted model's CompetitorsOthersName property will be null. You can check it.

ASP.Net Core Razor Pages: How to return the complex model on post?

I created a new ASP.Net Core 2 (Razor Pages) Project
My model is:
public class FormularioGenerico
{
public FormularioGenerico()
{
}
public string IP { get; set; }
public List<string> items { get; set; } = new List<string>();
}
On the page I put
on the page.cshtml.cs
public class EditarModel : PageModel
{
[BindProperty]
public FormularioGenerico ff { get; set; }
[BindProperty]
public string Message { get; set; }
public void OnGet()
{
this.ff = new FormularioGenerico();
ff.IP = "C# FORM";
ff.items.Add("OK1");
ff.items.Add("OK2");
ff.items.Add("OK3");
}
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
var m = ModelState.IsValid; // true
Debug.WriteLine(this.ff.IP); // is Always returning null
Debug.WriteLine(this.ff.items.Count); // is Always returning null
}
}
on the page.cshtml:
#model Formulario.Pages.EditarModel
...
<h1>#Model.ff.IP</h1>
#foreach (var i in Model.ff.items)
{
<div>#i</div>
}
<button type="submit">Enviar</button>
The items are correctly output. But the complete object does not go to the OnPost.
The problem is: The model is not coming fully populated on the OnPost.
How to receive the full object that was created on the OnGet, plus the changes made by the user on the form, on the post to OnPostAsync() ?
The BindProperty attribute is used to inform ASP.NET Core that the values that the form submitted should be mapped to the specified object. In your case you set the values for the ff property but you do not have the equivalent input values so that ASP.NET Core will get these values in order to store them back to the ff property.
In order to make it work you will have to replace your razor code with the following code:
<form method="post">
<h1>#Model.ff.IP</h1>
<input asp-for="#Model.ff.IP" type="hidden" /> #* create a hidden input for the IP *#
#for (int i = 0; i < Model.ff.items.Count(); i++)
{
<input asp-for="#Model.ff.items[i]" type="hidden" /> #* create a hidden input for each item in your list *#
<div>#Model.ff.items[i]</div>
}
<button type="submit">Enviar</button>
</form>
Very important. To make this work you can not use the foreach loop because ASP.NET core will not be able to find the values. You will have to use a for loop.
The inputs that I added are hidden because I guess you do not want them to be visible but you can remore the type="hidden" so that you will be able to see them. Every change that you make to these inputs will be submitted to the OnPostAsync method.

ASP.NET MVC 4 - ListBoxFor, send selectedValue in ActionLink

I have a list of model. I want to retrieve the listBoxSelectedValue to send it in my actionLink to edit it.
This is my view :
#using (Html.BeginForm())
{
#Html.ListBoxFor(a => a.SelectedApplis, new SelectList(ViewBag.Applis,"ID","Name", Model.SelectedApplis))<br/>
#Html.ActionLink("Add","Create","Application")<br/>
#Html.ActionLink("Edit","Edit","Application", null, new { listAppId = Model.SelectedApplis})<br/>
#Html.ActionLink("Delete","Delete","Application")<br/>
}
I created a class "ListBoxApplication" with the List which will contain the selectedValue of the ListBox.
public class ListBoxApplication
{
public IEnumerable<int> SelectedApplis { get; set; }
public ListBoxApplication()
{
SelectedApplis = new List<int>();
}
}
I have 2 controllers : Application and Home
In HomeController, I created the model ListBoxApplication which contain the List. In my ViewBag.Applis, i have all my ApplicationModel.
public ActionResult Index()
{
ListBoxApplication listeApplis = new ListBoxApplication();
ViewBag.Applis = ApplicationModels.GetListApplications();
return View(listeApplis);
}
In my ApplicationController :
public ActionResult Edit(ListBoxApplication listAppId)
{
// I WANT TO RETRIEVE MY listAppId HERE, but it is always 'null'
return View();
}
So I think my problem is in the actionLink :
#Html.ActionLink("Edit","Edit","Application", null, new { listAppId = Model.SelectedApplis})
Me Edit Method is not is the actual controller (Home/Index). I need to send the selectedValue of my ListBox in my actionLink to (Application/Edit).
The listAppId is always 'null'. It doesn't retrieve the value... Is there a mistake in my actionLink ?
Thanks for advance
I don't believe that action links will trigger a postback to the server. Try this instead:
#Html.ActionLink("Delete","Delete","Application")<br/>
#Html.ActionLink("Add","Create","Application")<br/>
#using (Html.BeginForm("Detail","Application"))
{
#Html.ListBoxFor(a => a.SelectedApplis, new SelectList(ViewBag.Applis)) //not sure what the other params you had here were for, but it should work like this
<br/>
<input type="submit" name="Edit" value = "Edit"/>
#*added in response to comment*#
<input type="submit" name="Delete" value = "Delete"/>
<input type="submit" name="Add" value = "Add"/>
}
If you plan on having all of those buttons post back to the server, you could also use ajax (and javascript) to accomplish this same goal, without needing to write out a form for each individual button. Both ways would work just fine, multiple forms is technically easier though.
public ActionResult Detail(ListBoxApplication listAppId, bool Edit, bool Add, bool Delete)
{
if(//check your bools here){
}
return View();
}

Failing getting checkboxes values on the controller

I have a web page with a lot of checkboxes in the view in this form:
#using (Html.BeginForm("PerformDiagnostic", "Tests", FormMethod.Post))
{
(...)
#Html.CheckBox("Something01", false)<span>Something 01</span><br />
#Html.CheckBox("Something02", false)<span>Something 02</span><br />
(...)
<input type="submit" value="Submit" />
}
When I press submit button, I pass all the checkboxes statuses to the controller that has the following signature:
public ActionResult DoSomeTasks(FormCollection form)
{
int isSomething01Checked= Convert.ToInt32(form["Something01"]);
int isSomething02Checked= Convert.ToInt32(form["Something02"]);
....
}
In the controller I want to know for each checkbox whether it is checked or unchecked but the problem is that form["SomethingXX"] returns something like {true,false} but it is not telling me its current status (checked or unchecked). Also what return form["SomethingXX"] cannot be converted.
I have checked that if checkbox is checked, form["SomethingXX"] returns {true,false} and if it is unchecked then form["SomethingXX"] returns {false}, I do not understand why when checkbox is checked is returning {true,false} instead of {true}.
Any idea what is happening?
Maybe I'm missing something, but it seems like you're needlessly do an end-run around the MVC pattern, and therefore missing out on the convenience of pre-defined model binding. Why not just create a strongly-typed model?
public class ViewModel
{
[Display(Name="Something 01")]
public bool Something01 { get; set; }
[Display(Name="Something 02")]
public bool Something02 { get; set; }
}
Then use the HTML helper to generate check-boxes for the model properties:
#Html.CheckBoxFor(model => model.Something01)
#Html.CheckBoxFor(model => model.Something02)
And now the controller code is straight-forward. Simply call for the view-model type:
public ActionResult DoSomeTasks(ViewModel model)
{
bool isSomething01Checked = model.Something01;
bool isSomething02Checked = model.Something02;
}