I’m a C# programmer. I’m learning ASP.NET Core Razor Pages by myself.
Please teach me.
What I don’t understand is why there is a difference between Post and Get.
In case of HTTP Get, Following code works to turn checkboxes on/off as I exptected.
When submit button click, apple checkbox turn on, banana checkbox turn off.
CaseGet.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel;
namespace RazorCheckBoxTest.Pages
{
public class CaseGetModel : PageModel
{
[BindProperty]
[DisplayName("Apple")]
public bool IsApple { get; set; }
[BindProperty]
[DisplayName("Banana")]
public bool IsBanana { get; set; }
public void OnGet()
{
System.Diagnostics.Debug.WriteLineIf(IsApple, "I got Apple.");
System.Diagnostics.Debug.WriteLineIf(IsBanana, "I got Banana.");
IsApple = true; //works.
IsBanana = false; //works.
}
}
}
CaseGet.cshtml
@page
@model RazorCheckBoxTest.Pages.CaseGetModel
<form method="get">
<input asp-for="IsApple" />
<label asp-for="IsApple"></label>
<input asp-for="IsBanana" />
<label asp-for="IsBanana"></label>
<input type="submit" />
</form>
But in case of HTTP Post, it doesn’t works.
Please give me the reason.
CasePost.cshtml.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.ComponentModel;
namespace RazorCheckBoxTest.Pages
{
public class CasePostModel : PageModel
{
[BindProperty]
[DisplayName("Apple")]
public bool IsApple { get; set; }
[BindProperty]
[DisplayName("Banana")]
public bool IsBanana { get; set; }
public void OnPost()
{
System.Diagnostics.Debug.WriteLineIf(IsApple, "I got Apple.");
System.Diagnostics.Debug.WriteLineIf(IsBanana, "I got Banana.");
IsApple = true; //doesn't works.
IsBanana = false; //doesn't works.
}
}
}
CasePost.cshtml
@page
@model RazorCheckBoxTest.Pages.CasePostModel
<form method="post">
<input asp-for="IsApple" />
<label asp-for="IsApple"></label>
<input asp-for="IsBanana" />
<label asp-for="IsBanana"></label>
<input type="submit" />
</form>
enviroment
Visual Studio 2022 (17.8.0)
.NET 8
I know the way to turn on/off checkbox in case of HTTP POST like follow.
<input name="IsBanana" id="IsBanana" type="checkbox" class="form-check-input" checked="@Model.IsBanana" value="true" />
2
Answers
I have figured out what happened. It's not difference between GET and POST. It depends on whether there is ModelState or not.
ModelState values take precedence over property values of the Model class. When first access of the page, ModelState is nothing, so property values of the Model class will set to HTML element which asp-for specified.
But when second access of the Page, there are some GET or POST parameters in HTTP request, so ModelState will be fill. Therefore values of ModelState will set to HTML element which asp-for specified (instead of property values of the model class).
This is how the phenomenon occurs.
Now, I figure out how it works, so I have better solution too.
Removing items from ModelState, we can set HTML element values via property of the Model class. You can also use ModelState.Clear instead of ModelState.Remove. You can also directly change ModelStateEntry's rawvalue.
CasePost.cshtml.cs
However, I haven't found any documentation that mentions this. If you know, please let me know.
OnGet to initialize state needed for the page. In the preceding code, the OnGet method displays the CreateModel.cshtml Razor Page.
Phenomenon
The submit button been clicked in
Get
form, the url will behttps://localhost:7217/caseget?IsApple=true&IsApple=false&IsBanana=false
.The submit button been clicked in
Post
form, the url will behttps://localhost:7217/casepost
.In a GET request, when you set the values for IsApple and IsBanana in the OnGet method, the values are reflected directly on the page as the page is reloaded and the values of these properties update the corresponding HTML control.
In a Post request, the status value is not saved. Here’s an alternative, tested and effective.