skip to Main Content

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


  1. Chosen as BEST ANSWER

    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

    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.");
    
                ModelState.Remove(nameof(IsApple));
                ModelState.Remove(nameof(IsBanana));
    
                IsApple = true; //works.
                IsBanana = false;  //works.
            }
        }
    }
    

    However, I haven't found any documentation that mentions this. If you know, please let me know.


  2. OnGet to initialize state needed for the page. In the preceding code, the OnGet method displays the CreateModel.cshtml Razor Page.

    enter image description here


    Phenomenon

    The submit button been clicked in Get form, the url will be https://localhost:7217/caseget?IsApple=true&IsApple=false&IsBanana=false.

    The submit button been clicked in Post form, the url will be https://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.

    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.RazorPages;
    using System.ComponentModel;
    
    namespace WebApplication3.Pages
    {
        public class CasePostModel : PageModel
        {
            [TempData]
            public bool IsApple { get; set; }
    
            [TempData]
            public bool IsBanana { get; set; }
    
            public void OnGet()
            {
                if (TempData.ContainsKey("IsApple"))
                {
                    IsApple = (bool)TempData["IsApple"];
                }
                if (TempData.ContainsKey("IsBanana"))
                {
                    IsBanana = (bool)TempData["IsBanana"];
                }
            }
    
            public IActionResult OnPost()
            {
                System.Diagnostics.Debug.WriteLineIf(IsApple, "I got Apple.");
                System.Diagnostics.Debug.WriteLineIf(IsBanana, "I got Banana.");
    
                TempData["IsApple"] = true;
                TempData["IsBanana"] = false;
                return RedirectToPage();
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search