Chekbox from partial view isn't mapped

Laurent Guigon 276 Reputation points
2022-11-10T13:55:46.21+00:00

Hi,
1st sorry for my bad english :-/

In my Razor pages app, I built a form using partial views since this options are shared with many pages like this :

<form method="post">  
    <div asp-validation-summary="All" class="text-danger"></div>  
    <div class="row">  
        <div class="col-12 col-sm-4 col-lg-3 col-xl-3 col-xxl-2 mb-sm-2 text-primary">  
            @Html.DisplayNameFor(model => model.Chapter.Title)  
        </div>  
        <div class="col-12 col-sm-8 col-lg-7 col-xl-6 col-xxl-4 my-2 mt-sm-0 mb-sm-2 ps-4 ps-sm-0">  
            <input asp-for="Chapter.Title" class="form-control border-primary rounded-xl" placeholder="@Html.DisplayNameFor(model => model.Chapter.Title)" />  
        </div>  
        <div class="col-12 col-sm-4 col-lg-3 col-xl-3 col-xxl-2 mb-sm-2 text-primary">  
            @Html.DisplayNameFor(model => model.Chapter.Order)  
        </div>  
        <div class="col-12 col-sm-8 col-lg-7 col-xl-6 col-xxl-4 my-2 mt-sm-0 mb-sm-2 ps-4 ps-sm-0">  
            <input asp-for="Chapter.Order" class="form-control border-primary rounded-xl" placeholder="@Html.DisplayNameFor(model => model.Chapter.Order)" />  
        </div>  
    </div>  
  
    @await Html.PartialAsync("_PropertyPartial", Model.Chapter)  
    @Html.HiddenFor(model=>model.Chapter.CreatedBy)  
    @Html.HiddenFor(model=>model.Chapter.ModifiedBy)  
    @Html.HiddenFor(model=>model.Chapter.CreationDate)  
    @Html.HiddenFor(model=>model.Chapter.ModificationDate)  
    @Html.HiddenFor(model=>model.Chapter.ParentId)  
    @await Html.PartialAsync("Status/_StatusPartial", Model.Chapter)  

// this part work if I use it instead of the partial above.
@*<div class="row">
<div class="col-12 col-sm-4 col-lg-3 col-xl-3 col-xxl-2 mb-sm-2 text-primary">
@azzedinehtmlsql .DisplayName("Etat")
</div>

        <div class="col-12 col-sm-8 col-lg-9 col-xxl-10 text-primary fa-xl ps-4 ps-sm-0">  
            <div class="row">  
                <div class="col-6 col-xl-3 mb-2">  
                    <label class="form-check-label select-none">  
                        <small>  
                            @Html.CheckBoxFor(model => model.Chapter.IsPrivate)  
                            <i class="fa-duotone fa-user-secret text-primary" title="@Html.DisplayNameFor(model =>model.Chapter.IsPrivate)"></i>  
                            <i class="far fa-toggle-on text-success unchecked" title="Cliquez pour mettre au statut @Html.DisplayNameFor(model => model.Chapter.IsPrivate).ToLower()"></i>  
                            <i class="far fa-toggle-off text-muted checked" title="Cliquez pour mettre au statut @Html.DisplayNameFor(model => model.Chapter.IsPrivate).ToLower()"></i>  
                            <i class="fa-duotone fa-user text-primary" title="@Html.DisplayNameFor(model => model.Chapter.IsPrivate)"></i>  
                        </small>  
                    </label>  
                </div>  
            </div>  
        </div>  
    </div>*@  
  
    <hr class="bg-primary" />  
  
    <div class="row">  
    </div>  
  
    <div class="form-group mt-5 text-center">  
        <button type="submit" class="btn btn-primary text-white-50 rounded-pill">  
            <i class="fa-solid fa-save pr-1"></i>  
            Sauvegarder  
        </button>  
    </div>  
</form>  

the partial called is

@model WikiGuidIdBase  
  
<div class="row">  
    <div class="col-12 col-sm-4 col-lg-3 col-xl-3 col-xxl-2 mb-sm-2 text-primary">  
        @Html.DisplayName("Etat")  
    </div>  
  
    <div class="col-12 col-sm-8 col-lg-9 col-xxl-10 text-primary fa-xl ps-4 ps-sm-0">  
        <div class="row">  
            @if (Model is TopicBase)  
            {  
                @await Html.PartialAsync("./Status/_PrivateStatusPartial", Model)  
                @await Html.PartialAsync("./Status/_DeletedStatusPartial", Model)  
            }  
  
            @if (Model is IDraft)  
            {  
                @await Html.PartialAsync("./Status/_WritingProgressStatusPartial", Model)  
            }  
  
            @if (Model is Topic)  
            {  
                @await Html.PartialAsync("./Status/_OnlineStatusPartial", Model)  
            }  
        </div>  
    </div>  
</div>  

and the last partial, which is not mapped when I submit the form is

@{  
    var type = Model.GetType().Name;  
    var name = string.Empty;  
    var id = string.Empty;  
    if (!string.IsNullOrWhiteSpace(type))  
    {  
        name = string.Concat(type, "_IsPrivate");  
        id = string.Concat(type, ".IsPrivate");  
    }  
}  
  
@{  
    @if ((bool)ViewData["WritingMode"])  
    {  
        <div class="col-6 col-xl-3 mb-2">  
            <label class="form-check-label select-none">  
                <small>  
                    @*@Html.CheckBoxFor(model => (model as TopicBase).IsPrivate, htmlAttributes:new {@name = name, @id = id})*@  
                    @Html.CheckBox(name,(Model as TopicBase).IsPrivate, htmlAttributes:new{@id=id})  
                    <i class="fa-duotone fa-user-secret text-primary" title="@Html.DisplayNameFor(model => (model as TopicBase).IsPrivate)"></i>  
                    <i class="far fa-toggle-on text-success unchecked" title="Cliquez pour mettre au statut @Html.DisplayNameFor(model => (model as TopicBase).IsPrivate).ToLower()"></i>  
                    <i class="far fa-toggle-off text-muted checked" title="Cliquez pour mettre au statut @Html.DisplayNameFor(model => (model as TopicBase).IsPublic).ToLower()"></i>  
                    <i class="fa-duotone fa-user text-primary" title="@Html.DisplayNameFor(model => (model as TopicBase).IsPublic)"></i>  
                </small>  
            </label>  
        </div>  
    }  
    else  
    {  
        <div class="col-6 col-xl-3 mb-2">  
            <small>  
                <i class="fa-duotone fa-user-secret text-primary" title="@Html.DisplayNameFor(model => (model as TopicBase).IsPrivate)"></i>  
                @if (!(Model as TopicBase).IsPrivate)  
                {  
                    <i class="far fa-toggle-on text-success"></i>  
                }  
                else  
                {  
                    <i class="far fa-toggle-off text-muted"></i>  
                }  
                <i class="fa-duotone fa-user text-primary" title="@Html.DisplayNameFor(model => (model as TopicBase).IsPublic)"></i>  
            </small>  
        </div>  
    }  
}  

model heritage is correct,

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,156 questions
{count} votes

Accepted answer
  1. Bruce (SqlWork.com) 55,601 Reputation points
    2022-11-10T16:19:17.167+00:00

    When you pass a model property, rather than the model, to a partial then the binding name in the partial will not match the model for postback. You can use a different model for postback that matches the new binding names. You can also make a custom viewdata dictionary where you set the prefix


3 additional answers

Sort by: Most helpful
  1. Laurent Guigon 276 Reputation points
    2022-11-11T10:05:41.69+00:00

    Hi
    Thx for your answers.

    I should pass the model instead of the property, ok.
    But My Partial is a generic which accept many class from an heritage hierarchy.
    Topic, Chapter, Section, Sub-section, Paragraph, Alinea : all this classes implements one or many common Interfaces, and are derivated like this :

    259485-mymcd.pdf

    all of the final classes have the IsPrivate property, so I tried to built à single reusable partial and pass the good class as a property of my CreateModel page (inherits from PageModel)
    In ths CreateModel bind item is an instance of Chapter, in another use it will be Topic, Paragraph, etc.

    @ AgaveJoe in this use case of the partial, ((bool)ViewData["WritingMode"]) == true becaus it's a create form. The partial is also used in read page.
    @Bruce (SqlWork.com) : I don't know how to fix the problem... :`(

    0 comments No comments

  2. Laurent Guigon 276 Reputation points
    2022-11-11T13:07:52.147+00:00

    Ok, Since I need this function I wrote the code like this

    <form method="post">  
        <div asp-validation-summary="All" class="text-danger"></div>  
        <div class="row">  
            <div class="col-12 col-sm-4 col-lg-3 col-xl-3 col-xxl-2 mb-sm-2 text-primary">  
                @Html.DisplayNameFor(model => model.Chapter.Title)  
            </div>  
            <div class="col-12 col-sm-8 col-lg-7 col-xl-6 col-xxl-4 my-2 mt-sm-0 mb-sm-2 ps-4 ps-sm-0">  
                <input asp-for="Chapter.Title" class="form-control border-primary rounded-xl" placeholder="@Html.DisplayNameFor(model => model.Chapter.Title)" />  
            </div>  
            <div class="col-12 col-sm-4 col-lg-3 col-xl-3 col-xxl-2 mb-sm-2 text-primary">  
                @Html.DisplayNameFor(model => model.Chapter.Order)  
            </div>  
            <div class="col-12 col-sm-8 col-lg-7 col-xl-6 col-xxl-4 my-2 mt-sm-0 mb-sm-2 ps-4 ps-sm-0">  
                <input asp-for="Chapter.Order" class="form-control border-primary rounded-xl" placeholder="@Html.DisplayNameFor(model => model.Chapter.Order)" />  
            </div>  
        </div>  
      
        @await Html.PartialAsync("_PropertyPartial", Model.Chapter)  
        @Html.HiddenFor(model=>model.Chapter.CreatedBy)  
        @Html.HiddenFor(model=>model.Chapter.ModifiedBy)  
        @Html.HiddenFor(model=>model.Chapter.CreationDate)  
        @Html.HiddenFor(model=>model.Chapter.ModificationDate)  
        @Html.HiddenFor(model=>model.Chapter.ParentId)  
    @*    @await Html.PartialAsync("Status/_StatusPartial", Model.Chapter)*@  
      
        <div class="row">  
            <div class="col-12 col-sm-4 col-lg-3 col-xl-3 col-xxl-2 mb-sm-2 text-primary">  
                @Html.DisplayName("Etat")  
            </div>  
      
            <div class="col-12 col-sm-8 col-lg-9 col-xxl-10 text-primary fa-xl ps-4 ps-sm-0">  
                <div class="row">  
                    <div class="col-6 col-xl-3 mb-2">  
                        <label class="form-check-label select-none">  
                            <small>  
                                @Html.CheckBoxFor(model => model.Chapter.IsPrivate)  
                                <i class="fa-duotone fa-user-secret text-primary" title="@Html.DisplayNameFor(model =>model.Chapter.IsPrivate)"></i>  
                                <i class="far fa-toggle-on text-success unchecked" title="Cliquez pour mettre au statut @Html.DisplayNameFor(model => model.Chapter.IsPrivate).ToLower()"></i>  
                                <i class="far fa-toggle-off text-muted checked" title="Cliquez pour mettre au statut @Html.DisplayNameFor(model => model.Chapter.IsPrivate).ToLower()"></i>  
                                <i class="fa-duotone fa-user text-primary" title="@Html.DisplayNameFor(model => model.Chapter.IsPrivate)"></i>  
                            </small>  
                        </label>  
                    </div>  
      
                    <div class="col-6 col-xl-3 mb-2">  
                        <label class="form-check-label select-none">  
                            <small>  
                                @Html.CheckBoxFor(model => model.Chapter.IsDeleted)  
                                <i class="fa-duotone fa-trash-alt text-primary" title="@Html.DisplayNameFor(model => model.Chapter.IsDeleted)"></i>  
                                <i class="far fa-toggle-on text-success unchecked" title="Cliquez pour mettre au statut @Html.DisplayNameFor(model => model.Chapter.IsDeleted).ToLower()"></i>  
                                <i class="far fa-toggle-off text-muted checked" title="Cliquez pour mettre au statut @Html.DisplayNameFor(model => model.Chapter.IsNotDeleted).ToLower()"></i>  
                                <i class="fa-duotone fa-book-open text-primary" title="@Html.DisplayNameFor(model => model.Chapter.IsNotDeleted)"></i>  
                            </small>  
                        </label>  
                    </div>  
      
                    <div class="col-6 col-xl-3 mb-2">  
                        <label class="form-check-label select-none">  
                            <small>  
                                @Html.CheckBoxFor(model => model.Chapter.IsDraft)  
                                <i class="fa-duotone fa-person-digging text-primary" title="@Html.DisplayNameFor(model => model.Chapter.IsDraft)"></i>  
                                <i class="far fa-toggle-on text-success unchecked" title="Cliquez pour mettre au statut @Html.DisplayNameFor(model => model.Chapter.IsDraft).ToLower()"></i>  
                                <i class="far fa-toggle-off text-muted checked" title="Cliquez pour mettre au statut @Html.DisplayNameFor(model => model.Chapter.IsDrafted).ToLower()"></i>  
                                <i class="fa-duotone fa-book-open text-primary" title="@Html.DisplayNameFor(model => model.Chapter.IsDrafted)"></i>  
                            </small>  
                        </label>  
                    </div>  
      
                </div>  
            </div>  
        </div>  
      
        <div class="form-group mt-5 text-center">  
            <button type="submit" class="btn btn-primary text-white-50 rounded-pill">  
                <i class="fa-solid fa-save pr-1"></i>  
                Sauvegarder  
            </button>  
        </div>  
    </form>  
    

    But it'not DRY... If some has an idea, you're welcome


  3. Laurent Guigon 276 Reputation points
    2022-11-24T09:11:40.943+00:00

    Sorry, I don't have a GitHub account... Git is too cryptic too me.

    0 comments No comments