0

I have viewmodel with nested collection. I want to post that form through ajax but I cant serialize it properly. Here is my view

    @model ARM.Presentation.ViewModels.SecurityFormProfileViewModel
    
    @{
        ViewData["Title"] = "EditSecurityProfile";
    }    
    
    <hr />
    <div class="offset-1 row">
        <div class="col-md-12">
            <form asp-action="EditSecurityProfile" autocomplete="chrome-off" method="post" id="security- 
     profiles-form">
                <div class="form-row">
                    <div class="form-group">
                        <input asp-for="ProfileId" type="hidden" class="form-control" />
                    </div>
                    <div class="offset-2 col-md-2">
                        <h3>@Model.ProfileName</h3>
                    </div>
                    <div class="col-md-2">
                        <h5>Select Area to  Filter Items</h5>
                        <select id="areaid" class="form-control" asp-items="@Model.MainAreasList"> 
   </select>
                    </div>
    
                </div>
                <div class="form-row mt-2">
                    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                    <div class="col-md-6">
                        <div class="form-group">
                            <vc:security-form profile-id="@Model.ProfileId" area-id="null"></vc:security-form>
                        </div>
                    </div>
                </div>
                <div class="form-row">
                    <div class="form-group col-md-2">
                        <arm-submitbtn id="formprofilesubmit"></arm-submitbtn>
                        <arm-cancelbtn id="formprofilecancel"></arm-cancelbtn>
                    </div>
                </div>
            </form>
        </div>
    </div>
    <div class="offset-2 col-12">
        <vc:users-by-security-profile profile-id="@Model.ProfileId"></vc:users-by-security-profile>
    </div>
    <div>
        <a asp-action="Index">Back to List</a>
    </div>
    @section Scripts {
        @{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
        <script src="~/js/Areas/Administration/Views/SecurityProfiles/SecurityProfiles.js"></script>
        <script src="~/js/Areas/Administration//Views/SecurityProfiles/SecurityProfilesService.js"> 
</script>
    }

And here is my view component that I have called in the above view.

@model SecurityFormProfileViewModel

<div id="forms">
    <table class="table">
        <thead>
            <tr>
                <td></td>
                <td>Form Name</td>
                <td></td>
                <td></td>
                <td></td>
            </tr>

        </thead>
        <tbody>
            @for (int i = 0; i < Model.SecurityForms.Count; i++)
            {
              <tr>
                <td>
                    <input type="hidden" asp-for="@Model.SecurityForms[i].FormId" />
                    <input type="hidden" asp-for="@Model.SecurityForms[i].AreaId" />
                </td>
                <td>                        
                    <label class="form-check-label">@Model.SecurityForms[i].FormName</label>
                </td>
                @foreach (var item in Model.SecurityForms[i].AccessLevels)
                 {
                    <td>
                        <div class="form-check form-check-inline">
                            <input class="form-check-input" asp-for="@Model.SecurityForms[i].SelectedAccessLevelId" type="radio" id="inlineRaio1" 
                                   value="@item.AccessTypeId">
                            <label class="form-check-label">@item.AccessType</label>
                        </div>
                    </td>
                 }

            </tr>
            }
        </tbody>
    </table>
</div>

For all above I am using view model which has nested collections. Here is my view model that want to serialize from the view using jquery.

    public class SecurityFormProfileViewModel
{
    public int ProfileId { get; set; }
    public string ProfileName { get; set; }
    public List<SecurityFormViewModel> SecurityForms { get; set; }
    public IEnumerable<SelectListItem> MainAreasList { get; set; }
}
Usman Ahmed
  • 18
  • 1
  • 5
  • I am using simple serialization but on the controller action after submitting my Lists inside the view model are null. static GetDataArray(idOfForm: string): JQuery.NameValuePair[] { return $("#" + idOfForm).serializeArray(); } – Usman Ahmed Apr 07 '21 at 14:27

1 Answers1

1

First of all, why are you using a component as part of a form? Normally components are used to reuse some common functionality across pages. Their views can contain forms but I don't think that they can be a part of a parent form. If you want to reuse some .cshtml code in a form may be a partial view is a better approach? In this case list SecurityForms will be null because that when binding the form to a model the framework does not know that the data coming from the component's view belongs to the property SecurityForms i.e. it cannot bind the property from the form data. The easiest way to fix this is to replace the component with a partial view and add a prefix called SecurityForms this way on post the MVC framework will know that the data coming from the partial view belong to the property SecurityForms More on this here getting the values from a nested complex object that is passed to a partial view

Anton Kovachev
  • 322
  • 3
  • 6
  • I have used viewcomponent because it can be loaded through ajax by selecting some options from the dropdown list. I thought view component in mvc core is alternate of partial thats why I have used this. When I am submitting form by postback it works fine. It binds the SecurityForms. On Html side it wont matter if its viewcomponent or single form because in HTML it is showing as single form. The issue is with Jquery serialization. – Usman Ahmed Apr 08 '21 at 08:12