26 messaggi dal 23 luglio 2013
Buon giorno a tutti,
avrei un quesito da sottoporvi... sto cercando di costruirmi una sezione utile all'inserimento di contenuti ma mi trovo davanti al problema del savataggio dati della collection relazionata. Nel model ho definito quanto segue:
    public class GuideDetail
    {
        public int Id { get; set; }
        [UIHint("Contents")]
        [AllowHtml]
        [DataType(DataType.MultilineText)]
        public string Contents { get; set; }
        public int GuideId { get; set; }
        // navigation property
        [ForeignKey("GuideId")]
        public Guide Guide { get; set; } 
    }

    public class Guide
    {
        [Key]
        [Column("Id")]
        public int Id { get; set; }
        [Required]
        [UIHint("Shortcut")]
        public string Shortcut { get; set; }
        [UIHint("Chapter")]
        public string Chapter { get; set; }
        [Required]
        [UIHint("AccessLevel")]
        public byte AccessLevel { get; set; }
        // navigation property
        public virtual ICollection<GuideDetail> GuideDetails { get; set; }
    }

    public class GuidesContext : DbContext
    {
        public GuidesContext() : base("name=DefaultConnection") { Database.SetInitializer<GuidesContext>(null); }
        public DbSet<Guide> Guides { get; set; }
        public DbSet<GuideDetail> GuideDetails { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            // uno a molti: Guide.Id --> GuideDetail.GuideId
            modelBuilder.Entity<Guide>()
               .HasMany(g => g.GuideDetails)
               .WithRequired()
               .HasForeignKey(d => d.GuideId)
               .WillCascadeOnDelete();
        }
    }

nel controller:
    public ActionResult Edit(int id)
    {
        return View(_context.Guides.Where(b => b.Id == id).FirstOrDefault());
    }

nella view:
    ......

    @foreach (var item in Model.GuideDetails)
    {
        @Html.EditorFor(model => item, "GuideDetail")
    }

dove GuideDetail è un edit template con quanto segue:
@model WSProxyServer.Areas.Guide.Models.GuideDetail

@using (Html.BeginForm())
{
    <fieldset>
        @if (Model != null)
        {
            <div class="form-group">
                @Html.Label("Culture " + Model.Culture, htmlAttributes: new { @class = "control-label col-md-2" })
                <div class="col-md-10">
                    @Html.HiddenFor(m => Model.Id)
                    @Html.EditorFor(m => Model.Contents, new { htmlAttributes = new { @class = "form-control", @rows = 15 } })
                </div>
            </div>
        }
    </fieldset>
}

tutto sembra funzionare ma quando salvo, model.GuideDetail è a null mentre collection ha tutto ma non relazionato
        [HttpPost]
        public ActionResult Edit(int id, Guide.Models.Guide model, FormCollection collection)
        {
            try
            {
                // TODO: Add update logic here
                var guide = _context.Guides.Where(b => b.Id == id).FirstOrDefault();
                if (TryUpdateModel(guide, collection))
                {
                    _context.SaveChanges();
                }
                return RedirectToAction("Details", new { id = guide.Id});
            }
            catch
            {
                return View();
            }
        }

perchè model.GuideDetails è a null mentre il resto dei campi è popolato correttamente con le modifiche opportune? come si edita una collection relazionata?
16 messaggi dal 06 marzo 2017
Per far si che EF gestisca in modo corretto le virtual ICollection di una classe non basta definirla, devi instanziarla nel costruttore della classe stessa della tabella:

    public class Guide
    {
        [Key]
        [Column("Id")]
        public int Id { get; set; }
        [Required]
        [UIHint("Shortcut")]
        public string Shortcut { get; set; }
        [UIHint("Chapter")]
        public string Chapter { get; set; }
        [Required]
        [UIHint("AccessLevel")]
        public byte AccessLevel { get; set; }
        // navigation property
        public virtual ICollection<GuideDetail> GuideDetails { get; set; }

        public Guide()
        {
            GuideDetails = new HashSet<GuideDetail>();
        }
    }
26 messaggi dal 23 luglio 2013
Grazie per la risposta ma purtroppo non cambia molto, invece che null ritorna istanziato con 0 item. Diverso invece se uso IList al posto di ICollection, in questo caso tutto funziona correttamente. Alla fine uso IList però mi sarebbe piaciuto capire il perché anche se a naso ipotizzo che il problema sia legato a qualche indice gestito in modo diverso tra le due interface

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.