简体   繁体   中英

ASP.NET Core MVC: asp-for is rendering incomplete id and name attributes

When I iterate over a list in my.cshtml file, for some reason the id and name attribute values are rendered incomplete. For example:

 @for (int i = 0; i < Model.product.ProductDetail.Count(); i++)
{
    <input type="text"
    asp-for="product.ProductDetail.ElementAt(i).Sku"
    class="form-control"
    placeholder="@SharedLocalizer["Sku"]" />
}

Is rendered as:

<input type="text" class="form-control" placeholder="Sku" id="Sku" name="Sku">

Instead of:

<input type="text" id="product.ProductDetail_0__Sku" name="product.ProductDetail[0].Sku" class="form-control" placeholder="Sku">

I am using Entity Framework Core 3.1.3, here is my model:

Product:

public partial class Product
{
     public Product()
     {
          ProductDetail = new HashSet<ProductDetail>();
     }

     /* More properties here... */

     public virtual ICollection<ProductDetail> ProductDetail { get; set; }
}

ProductDetail:

public partial class ProductDetail
{
    /* More properties here... */
    public string Sku { get; set; }
}

ProductViewModel:

public class ProductViewModel
{
    public Product product { get; set; }
    /* More properties here... */
}

Do you know why is this happening?

The asp-for is a ModelExpression that is evaluated in order to build up the id and name attributes. If you use ElementAt() , this expression cannot be evaluated fully.

Try using a direct indexer int your collection instead. Example as follows:

<input type="text"
asp-for="product.ProductDetail[i].Sku"
class="form-control"
placeholder="@SharedLocalizer["Sku"]" />

Edit: I strongly recommend using view models rather than data persistence level models with your views. You could then use a List in your view model (instead of an ICollection and apply the above indexing accordingly.

Firstly, using asp-for="product.ProductDetail[i].Sku" as CalC shared could work for me with testing model data.

If it indeed doesn't work for you, you can try to manually set id, name and value attributes for your input fields, like below.

Here is my code of Model:

products:

public class Products
{
    public Product product { get; set; }
}

Product:

public class Product
{
    public List<ProductDetail> ProductDetail { get; set; }
}

ProductDetail:

public class ProductDetail
{
    public string Sku { get; set; }
}

view:

<div>
    @for (int i = 0; i < Model.product.ProductDetail.Count(); i++)
    {
        <input type="text"
               asp-for="product.ProductDetail[i].Sku"
               class="form-control" 
               placeholder="@SharedLocalizer["Sku"]"/>
    }
    @for (int i = 0; i < Model.product.ProductDetail.Count(); i++)
    {
        <input type="text"
               id="product_ProductDetail_@(i)__Sku"
               name="product.ProductDetail[@(i)].Sku"
               value="@Model.product.ProductDetail.ElementAt(i).Sku"
               class="form-control"
               placeholder="@SharedLocalizer["Sku"]"/>
    }
</div>

And this is the result: 在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM