blazorstatic-server-rendering

Model binding Blazor SSR pages


According to this Microsoft documentation page, the following code should render a page that allows the user to type in form data, and clicking the submit button should result in the Save method being executed whilst Model contains state bound from the submitted form.

When I run it, the values of the Person are always null.

@page "/"
<PageTitle>Home</PageTitle>

<form @formname="MyForm" method=post @onsubmit=Save>
    <AntiforgeryToken />
    Salutation <input name="Salutation" value=@Model.Salutation /><br/>
    Personal name <input name="PersonalName" value=@Model.PersonalName /><br />
    Family name <input name="FamilyName" value=@Model.FamilyName /><br />
    <button type=submit>Save</button>
</form>


@code {
    public class Person
    {
        public string? Salutation { get; set; }
        public string? PersonalName { get; set; }
        public string? FamilyName { get; set; }
    }

    [SupplyParameterFromForm(FormName = "MyForm")]
    public required Person Model { get; set; }

    protected override void OnInitialized()
    {
        base.OnInitialized();
        Model ??= new();
    }

    private void Save()
    {
        if (Model?.Salutation is null)
            throw new NullReferenceException("This should not happen");
    }
}

Solution

  • There are three ways your code differs from the StarShip example. All seem critical.

    1. You provide a name.

    2. You use the raw input, while the examples use InputText.

    3. You don't two-way bind the inputs to the Model, just one-way bind using value=.

    The important bit is the name. It needs to match the class.propertyname format.

    So this works:

    @page "/"
    
    <PageTitle>Home</PageTitle>
    
     <form @formname="Home" method="post" @onsubmit="this.Save">
    
        <AntiforgeryToken />
        Salutation: <input class="mb-3" name="Model.Salutation" value="this.Model.Salutation" /><br />
        Personal name: <input class="mb-3" name="Model.PersonalName" value="this.Model.PersonalName" /><br />
        Family name: <input class="mb-3" name="Model.FamilyName" value="this.Model.FamilyName" /><br />
    
        <button type=submit>Save</button>
    
    </form>
    
    @code {
        [SupplyParameterFromForm]
        public required Person Model { get; set; }
    
        protected override void OnInitialized()
        {
            this.Model ??= new();
        }
    
        private void Save()
        {
            if (Model?.Salutation is null)
                throw new NullReferenceException("This should not happen");
        }
    
        public class Person
        {
            public string? Salutation { get; set; }
            public string? PersonalName { get; set; }
            public string? FamilyName { get; set; }
        }
    }
    

    InputText adds the name field automatically.