Best Practice to process checked/selected items in an MVC View?

Using ASP.NET & MVC.

I'm going to have a list of checkboxes in my View (1 checkbox per row/record), then have a "Process All Checked Rows" button that will perform an action on all of the checked rows. I would like to process the checked rows in the Controller.

I'm worried that I'll come up with some "kludge" when there's an elegant way to do it.

Suggestions?
cdakzAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

omgangIT ManagerCommented:
Who knows, maybe your "kludge" is more elegant than my solution.....

Anyway, I am doing something similar in an MVC 5 app.  I have a ViewModel to present a list of optional checkboxes.  In my Controller action I need to evaluate whether any were checked and, if so, which ones.

I pass in the checkbox as an array.  Let me know if you would like to see any additional code, e.g. from the ViewModel that constructs the selectedOpinions or the View itself.

OM Gang

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create ([Bind(Include = "larARRecNum,larRecDate,artID,larUserAgency")] LegAuditReport legAuditReport, int[] selectedOpinions)
        {
            //check to see if any report opinions were selected
            if (selectedOpinions != null)
            {
                //construct empty list for report opinions
                legAuditReport.LegAuditReportOpinions = new List<LegAuditReportOpinion>();
                foreach (var opinion in selectedOpinions)
                {
                    //add each report opinion selected
                    var opinionToAdd = new LegAuditReportOpinion();
                    opinionToAdd.aroID = opinion;
                    opinionToAdd.larID = legAuditReport.larID;
                    //use the userAgency value from the leg audit report record
                    opinionToAdd.laroUserAgency = legAuditReport.larUserAgency;
                    legAuditReport.LegAuditReportOpinions.Add(opinionToAdd);
                }
            }

Open in new window

cdakzAuthor Commented:
How are you populating the int[] selectedOpinions array from the View?
(Perhaps the crux of my question).
omgangIT ManagerCommented:
View

        @* checkboxes to select report opinions *@
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <table>
                    <tr>
                        @{
                            int cnt = 0;
                            List<GovCAP.ViewModels.AuditReportOpinionData> AuditReportOpinionTypes = ViewBag.AuditReportOpinionTypes;

                            foreach (var auditReportOpinion in AuditReportOpinionTypes)
                            {
                                if (cnt++ % 3 == 0)
                                {
                                    @:</tr><tr>
                                }
                                @:<td class="opiniontable">
                                    <input type="checkbox"
                                        name="selectedOpinions"
                                        value="@auditReportOpinion.OpinionID"
                                        @(Html.Raw(auditReportOpinion.Selected ? "checked=\"checked\"" : "")) />
                                        @auditReportOpinion.OpinionID @: @auditReportOpinion.Description
                                    @:</td>
                            }
                            @:</tr>
                        }
                </table>
            </div>
        </div>

Open in new window


Controller -- calls a method to construct the

                //construct empty entity object that we can pass to method to include releated records for report opinions
                var legAuditReport = new LegAuditReport();
                legAuditReport.LegAuditReportOpinions = new List<LegAuditReportOpinion>();
                PopulateAuditReportOpinionData(legAuditReport);

Open in new window



Controller method to construct the check box items and add to view bag

        // Constructs view model for report opinions for audit report passed as argument.
        private void PopulateAuditReportOpinionData(LegAuditReport legAuditReport)
        {
            // Get all opinion types from db.
            var allOpinions = db.AuditReportOpinionTypes;

            // Get opinions selected for the audit report we're working with.
            var reportOpinions = new HashSet<int>(legAuditReport.LegAuditReportOpinions.Select(c => c.AuditReportOpinionType.aroID));

            var viewModel = new List<AuditReportOpinionData>();
            foreach (var opinion in allOpinions)
            {
                // Construct the view model to include and opinion types from db and indicating which are selected for the report we're working with.
                viewModel.Add(new AuditReportOpinionData
                {
                    OpinionID = opinion.aroID,
                    AuditReportID = legAuditReport.larID,
                    Description = opinion.aroDescription,
                    Selected = reportOpinions.Contains(opinion.aroID)
                });
            }
            ViewBag.AuditReportOpinionTypes = viewModel;
        }

Open in new window

omgangIT ManagerCommented:
....so, in the Controller GET action, I call a method to construct the list of opinions (checkbox items) for the specified report.  The method adds the list to the ViewBag.  In the View, the list (from the ViewBag) is iterated and html checkboxes are constructed for each, including whether or not each one is 'checked'.

I believe this is probably NOT elegant from a pure MVC standpoint as I'm adding logic to the View when it SHOULD only present html.  A "kludge", perhaps.  It does exactly what I want it to, however.
OM Gang
omgangIT ManagerCommented:
I guess I should have also posted the POST controller action

The View has a group of checkboxes all with the same 'name' ( name="selectedOpinions" ).  On the POST action these checkboxes are sent to the Controller as a list named selectedOpinions


        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create ([Bind(Include = "larARRecNum,larRecDate,artID,larUserAgency")] LegAuditReport legAuditReport, int[] selectedOpinions)
        {
            //check to see if any report opinions were selected
            if (selectedOpinions != null)
            {
                //construct empty list for report opinions
                legAuditReport.LegAuditReportOpinions = new List<LegAuditReportOpinion>();
                foreach (var opinion in selectedOpinions)
                {
                    //add each report opinion selected
                    var opinionToAdd = new LegAuditReportOpinion();
                    opinionToAdd.aroID = opinion;
                    opinionToAdd.larID = legAuditReport.larID;
                    //use the userAgency value from the leg audit report record
                    opinionToAdd.laroUserAgency = legAuditReport.larUserAgency;
                    legAuditReport.LegAuditReportOpinions.Add(opinionToAdd);
                }
            }

            if (ModelState.IsValid)
            {
                db.LegAuditReports.Add(legAuditReport);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
ASP.NET

From novice to tech pro — start learning today.