1

I want to select multiple services for a client and save them to database, on single click.

When i click save, it stores only the first service. So far, on the backend side (OnPost), i have tried with: .add() , addrange(), foreach(), for(), but still no luck. I cant understand what i am doing wrong!

My frontend code is as below:

 <form method="post">
                <div class="col-md-12">
                        @for (int i = 18; i < 40; i++)
                        {
                            <input asp-for="ClientServices.CliId" class="form-control" value="@Model.CliIdOk" hidden />
                            <input class="form-control" asp-for="ClientServices.ServId" value="@i" hidden />
                            <div class="border-0" style="width: 6%; height: 150px; min-width: 30px; float: left; ">
                                <div class="form-group form-check" style="position:relative;left:-15px;">
                                    <label class="form-check-label btn btn-sm fw-bold border m-1 p-1" style="border-radius:16px;">
                                        <input asp-for="ClientServices.Active"
                                       style="border-radius:16px;position:relative;" />
                                        <br />
                                        @i
                                    </label>
                                </div>
                            </div>
                        }
            </div>
             <button class="btn btn-sm btn-outline-primary fw-bold" type="submit" name="id"
        style="font-size: 120%;float:unset;min-width:120px;">
            Save
        </button>
        </form>

My backend "OnPost" code is:

 public async Task<IActionResult> OnPostAsync()
    {
        try
        {
            //if (!ModelState.IsValid)
            //{
            //    return Page();
            //}

            _context.ClientServices.AddRange(ClientService);

            await _context.SaveChangesAsync();

            return RedirectToPage("./Index");
        }
        catch (Exception e)
        {
            e.ToString();
            return RedirectToPage("./Index");
        }
    }
3
  • What error you aree getting? Could you please share ClientService details? Commented Jan 24, 2023 at 0:49
  • On Post, it saves just the first value (service), there is no error. I want to save all the selected values at one single post. Can you help me? Commented Jan 24, 2023 at 0:55
  • Well, are you getting the list whilee submitting form data? In addition could you please share your dbcontext class? Commented Jan 24, 2023 at 1:18

1 Answer 1

1

When i click save, it stores only the first service. So far, on the backend side (OnPost), i have tried with: .add() , addrange(), foreach(), for(), but still no luck. I cant understand what i am doing wrong!

Well, couple of mistake has been found on your code.

Mistake: 1:

Getting only the first object while submitting list is pretty obvious as per your shared code snippet. You cannot save all list following this way because, your post method model doesn't aware of your list. As you are sending the flat object like this asp-for="ClientServices.CliId" so only the first object will be evaluated instead you outght to send like this way asp-for="@Model.clientServices[i].CliId". So that model binding can map the object list with your backed.

Mistake: 2:

On OnPostAsync() you supposed to send list of object not sure how you are passsing it AddRange(ClientService);. I think here in ClientService you are not getting the list as well.

Solution:

cshtml:

Your view should be modified as following:

@page
@model RazorPageDemoApp.Pages.AddMultipleDataModel



<form method="post">
    <div class="col-md-12">
        @for (int i = 0; i <Model.clientServices.Count(); i++)
        {
            <input asp-for="@Model.clientServices[i].CliId" class="form-control" value="@Model.clientServices[i].CliId" hidden />
            <input class="form-control" asp-for="@Model.clientServices[i].ServId" value="@Model.clientServices[i].ServId" hidden />
            <div class="border-0" style="width: 6%; height: 150px; min-width: 30px; float: left; ">
                <div class="form-group form-check" style="position:relative;left:-15px;">
                    <label class="form-check-label btn btn-sm fw-bold border m-1 p-1" style="border-radius:16px;">
                        <input asp-for="@Model.clientServices[i].Active" value="@Model.clientServices[i].CliId"
                           style="border-radius:16px;position:relative;" />
                        <br />
                        @i
                    </label>
                </div>
            </div>
           
        }
       
    </div>

    <div>

        <button class="btn btn-sm btn-outline-primary fw-bold" type="submit" name="id"
                style="font-size: 120%;float:unset;min-width:120px; margin-top:100px">
            Save
        </button>
    </div>

</form>

Note: The crucial part are Model.clientServices.Count() and asp-for="@Model.clientServices[i].CliId" if doesn't map your model this way, your model binding wouldn't be mapped accordingly.

cshtml.cs:

public class AddMultipleDataModel : PageModel
    {
        private readonly AppDbContext _context;

        public AddMultipleDataModel(AppDbContext context)
        {
            _context = context;
        }
       
        public List<ClientService> clientServices { get; set; }
        public void OnGet()
        {
            var clientServiceList = new List<ClientService>()
            {
                new ClientService(){ CliId ="CliId:1",ServId = "ServId-A",Active = false},
                new ClientService(){ CliId ="CliId:2",ServId = "ServId-B",Active = false},
                new ClientService(){ CliId ="CliId:3",ServId = "ServId-C",Active = true},
                new ClientService(){ CliId ="CliId:4",ServId = "ServId-D",Active = true},
                new ClientService(){ CliId ="CliId:5",ServId = "ServId-E",Active = false},
               
            };
            clientServices = clientServiceList;

        }
        [HttpPost]
        public async Task<IActionResult> OnPostAsync(List<ClientService> clientServices)
        {
            try
            {
                //if (!ModelState.IsValid)
                //{
                //    return Page();
                //}

                _context.clientServices.AddRange(clientServices);

                await _context.SaveChangesAsync();

                return RedirectToPage("./AddMultipleData");
            }
            catch (Exception e)
            {
                e.ToString();
                return RedirectToPage("./Index");
            }
        }
    }

Note: As you might notice, I have constructed post method as OnPostAsync(List<ClientService> clientServices) means it will accept list of object from your view.

Output:

enter image description here

Note: If you are interested to know more about Razor page post list and other stuff, please have a look our official document here.

Sign up to request clarification or add additional context in comments.

1 Comment

You are welcome and glad to assist you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.