Jason
Jason

Reputation: 33

InvalidOperationException: Templates can be used only with field access, property access, single-dimension array index custom indexer expressions

Why am I receiving the input form error?

@foreach (var user in Model.UsersWithItemsOption2)
{
<div>
    <div>@user.Items</div>

    @string.Join(", ", user.Items.Select(a => a.ItemName).ToList());

    <div>@user.Items.Select(a => a.ItemName)</div>

    <form method="post">
        //error 
        <input asp-for="@user.Items.Select(a => a.ItemName)" />
        //error 
        <button type="submit">Save</button>
    </form>
</div>
}

Here's the C# file for it.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using ArrayCheckNetCore.Areas.Identity.Data;
using ArrayCheckNetCore.Data;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System.Linq;

namespace ArrayCheckNetCore.Areas.Identity.Pages.Account.Manage
{
    public class PersonalDataModel : PageModel
    {
        /// Inject DbContext
        readonly CheckArrayContext Context;

        /// Inject UserManager
        readonly UserManager<ApplicationUser> UserManager;


        public IEnumerable<ApplicationUser> UsersWithItemsOption2 { get; set; } = new 
List<ApplicationUser>();
        public IEnumerable<ApplicationUser> UsersWithItemsOption1 { get; set; } = new 
List<ApplicationUser>();
        public string Name { get; set; }

        public PersonalDataModel(
            CheckArrayContext Context,
            UserManager<ApplicationUser> UserManager)
        {
            this.Context = Context;
            this.UserManager = UserManager;
        }

        public async Task<IActionResult> OnGetAsync()
        {
            UsersWithItemsOption2 = await UserManager
                .Users
                .Include(a => a.Items)
                .ToListAsync();

            return Page();
        }

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

            await Context.SaveChangesAsync();

            return RedirectToPage("");
        }
    }
}

I get an error of

InvalidOperationException: Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions

What I think the issue is, is that it can't set a property on the form submit or maybe the asp-for='@user.Items.Select(a => a.ItemName)' isn't defined in the context of the file.

If anyone knows how to fix this error, thank you.

Upvotes: 0

Views: 2083

Answers (1)

Yiyi You
Yiyi You

Reputation: 18209

Firstly,asp-for cannot bind a tag.You can refer to the link,asp-forthere are samples about using taghelper.

If you want to post one user's items one time,here is a demo(.net core bind data with name attribute):

Models:

public class ApplicationUser
    {
        public List<Item> Items { get; set; }
    }
    public class Item
    {
        public string ItemName { get; set; }
    }

PersonData.cshtml:

@{ var usercount = 0;}

    @foreach (var user in Model.UsersWithItemsOption2)
    {
<div>
    <form method="post">
        @{ var itemscount = 0;}
        @foreach (var item in user.Items)
        {
            <input value="@item.ItemName" name="Items[@itemscount].ItemName" />
            itemscount++;
        }
        <button type="submit">Save</button>
    </form>

</div>
        usercount++;
    }

PersonData.cshtml.cs:

public class PersonalDataModel : PageModel
    {

        [BindProperty]
        public IEnumerable<ApplicationUser> UsersWithItemsOption2 { get; set; } = new
List<ApplicationUser>();
        public IEnumerable<ApplicationUser> UsersWithItemsOption1 { get; set; } = new
List<ApplicationUser>();
        public string Name { get; set; }

        public async Task<IActionResult> OnGetAsync()
        {
            UsersWithItemsOption2 = new List<ApplicationUser> { 
                new ApplicationUser { Items=new List<Item> { new Item {  ItemName="item01"}, new Item { ItemName = "item02" } } } ,
                new ApplicationUser { Items=new List<Item> { new Item {  ItemName="item11"}, new Item { ItemName = "item12" } } } ,
                new ApplicationUser { Items=new List<Item> { new Item {  ItemName="item21"}, new Item { ItemName = "item22" } } } ,

            };
            
                return Page();
        }

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


            return RedirectToPage("");
        }
    }

result: enter image description here And if you want to post all the users' items.Here is a demo(I bind form data with UsersWithItemsOption2):

PersonData.cshtml:

@{ var usercount = 0;}
<form method="post">
    @foreach (var user in Model.UsersWithItemsOption2)
    {
        <div>

            @{ var itemscount = 0;}
            @foreach (var item in user.Items)
            {
                <input value="@item.ItemName" name="UsersWithItemsOption2[@usercount].Items[@itemscount].ItemName" />
                itemscount++;
            }


        </div>
        usercount++;
    }
    <button type="submit">Save</button>
</form>

PersonData.cshtml.cs:

public class PersonalDataModel : PageModel
    {

        [BindProperty]
        public IEnumerable<ApplicationUser> UsersWithItemsOption2 { get; set; } = new
List<ApplicationUser>();
        public IEnumerable<ApplicationUser> UsersWithItemsOption1 { get; set; } = new
List<ApplicationUser>();
        public string Name { get; set; }

        public async Task<IActionResult> OnGetAsync()
        {
            UsersWithItemsOption2 = new List<ApplicationUser> { 
                new ApplicationUser { Items=new List<Item> { new Item {  ItemName="item01"}, new Item { ItemName = "item02" } } } ,
                new ApplicationUser { Items=new List<Item> { new Item {  ItemName="item11"}, new Item { ItemName = "item12" } } } ,
                new ApplicationUser { Items=new List<Item> { new Item {  ItemName="item21"}, new Item { ItemName = "item22" } } } ,

            };
            
                return Page();
        }

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


            return RedirectToPage("");
        }
    }

result: enter image description here

Upvotes: 2

Related Questions