skip to Main Content

I have a view model like:

public class OrganisationViewModel
{
    public string OrganisationName { get; set; }
    public List<BranchViewModel> Branches { get; set; }
    // more properties...
}

public class BranchViewModel
{
    public string BranchName { get; set; }
    // more properties...
}

This is how the Organisation page looks like:

enter image description here

What I want to achieve is to allow user to update a single BranchViewModel, so I have created a Modal for each Branch and when user click on the Edit branch link, the modal will open:

@for (int i = 0; i < Model.BranchViewModels.Count(); i++)
{
    var branchModalId = OrganisationHelper.GetBranchModalId(Model.BranchViewModels[i].BranchId);

    <div class="modal fade" id="@branchModalId" tabindex="-1" role="dialog" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered" role="document">
            <div class="modal-content">
                <form action="/organisation/updateBranch" method="post" role="form">
                    <div class="modal-body">
                        @Html.AntiForgeryToken()
                        <div class="form">
                            <div class="form-group">
                                @Html.LabelFor(m => Model.BranchViewModels[i].BranchName, htmlAttributes: new { @class = "", @maxlength = GlobalConstants.MaxLengthForLongName })
                                @Html.TextBoxFor(m => Model.BranchViewModels[i].BranchName, new { @class = "form-control input-text" })
                                @Html.ValidationMessageFor(m => Model.BranchViewModels[i].BranchName, "", new { @class = "text-danger" })
                            </div>

                            @*more properties...*@
                        </div>

                    </div>
                    <div class="modal-footer">
                        <input type="button" value="Cancel" class="btn btn-secondary-grey" data-dismiss="modal" />
                        <input type="submit" class="btn btn-primary-action" value="Save" />
                    </div>
                </form>
            </div>
        </div>
    </div>
}

enter image description here

Now the problem is, since branches belong to an array the inputs on the page are generated as an array, so something like this:

<input class="form-control input-text" data-val="true" id="BranchViewModels_0__BranchName" name="BranchViewModels[0].BranchName" readonly="readonly" type="text" value="35671900246">

So when I submit the changes to the branch, the values are passed to the controller as List, so this controller will accept a List of one Branch:

public ActionResult UpdateBranch(List<BranchViewModel> branchViewModel)
{
}

What I want to achieve is to be able to pass the single branch to the controller, so I want the signature of the controller to be like:

public ActionResult UpdateBranch(BranchViewModel branchViewModel)
{
}

But I need the branch to be rendered as an array in the HTML, otherwise I will get duplicated input Ids… what is the best way to achieve this?

2

Answers


  1. Can you try instead of using the static @HTML.LabelFor and @HTML.TextBoxFor, you could write the html manually with <input> tags and specify the name of the input field. This way, it won’t have an index.

    <input name="BranchViewModel.BranchId" type="hidden" value="Model.BranchViewModels[i].BranchId" />
    <input name="BranchViewModel.BranchName" max="@GlobalConstants.MaxLenghForName" value="Model.BranchViewModels[i].BranchName" />
    

    Full modal code;

    @for (int i = 0; i < Model.BranchViewModels.Count(); i++)
    {
        var branchModalId = OrganisationHelper.GetBranchModalId(Model.BranchViewModels[i].BranchId);
    
        <div class="modal fade" id="@branchModalId" tabindex="-1" role="dialog" aria-hidden="true">
            <div class="modal-dialog modal-dialog-centered" role="document">
                <div class="modal-content">
                    <form action="/organisation/updateBranch" method="post" role="form">
                        <div class="modal-body">
                            @Html.AntiForgeryToken()
                            <div class="form">
                                <div class="form-group">
                                    <label>Model.BranchViewModels[i].BranchName</label>
                                    <input name="BranchViewModel.BranchId" type="hidden"value="Model.BranchViewModels[i].BranchId" />
                                    <input name="BranchViewModel.BranchName" max="@GlobalConstants.MaxLenghForName" value="Model.BranchViewModels[i].BranchName" />
                                </div>
    
                                @*more properties...*@
                            </div>
    
                        </div>
                        <div class="modal-footer">
                            <input type="button" value="Cancel" class="btn btn-secondary-grey" data-dismiss="modal" />
                            <input type="submit" class="btn btn-primary-action" value="Save" />
                        </div>
                    </form>
                </div>
            </div>
        </div>
    }
    
    Login or Signup to reply.
  2. ASP.NET MVC serialization works on html element names. Indexers will have html element names with _i__ (where i is index of branch in that collection) when you create them via for loop.
    So, instead of using indexers (accessing Model.BranchViewModels[i] via for loop), you can try using foreach.

    @{
        var idx = 0;
    }
    @foreach (var branch in Model.BranchViewModels)
    {
        var branchModalId = OrganisationHelper.GetBranchModalId(branch.BranchId);
    
        <div class="modal fade" id="@branchModalId" tabindex="-1" role="dialog" aria-hidden="true">
            <div class="modal-dialog modal-dialog-centered" role="document">
                <div class="modal-content">
                    <form action="/organisation/updateBranch" method="post" role="form">
                        <div class="modal-body">
                            @Html.AntiForgeryToken()
                            <div class="form">
                                <div class="form-group">
                                    @Html.LabelFor(m => branch.BranchName, htmlAttributes: new { @class = "", @maxlength = GlobalConstants.MaxLengthForLongName })
                                    @Html.TextBoxFor(m => branch.BranchName, new { @class = "form-control input-text", @id= Model.BranchViewModels[idx].BranchName})
                                    @Html.ValidationMessageFor(m => branch.BranchName, "", new { @class = "text-danger" })
                                </div>
    
                                @*more properties...*@
                            </div>
    
                        </div>
                        <div class="modal-footer">
                            <input type="button" value="Cancel" class="btn btn-secondary-grey" data-dismiss="modal" />
                            <input type="submit" class="btn btn-primary-action" value="Save" />
                        </div>
                    </form>
                </div>
            </div>
        </div>
        idx++;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search