I have a Add view which uploads file which is element of Question class
@model PasmISO.Domain.Question
@using (Html.BeginForm("Add", "Photo", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="editor-field">
@Html.TextAreaFor(model => model.QuestionRevisions.First().Content)
@Html.ValidationMessageFor(model => model.QuestionRevisions.First().Content)
</div>
<input type="file" name="file" id="file" />
<br/>
<input type="submit" value="Ask" />
}
I have 2 actions in my controller
First action is when user clicks at Add button and he gets form to upload photo:
public ActionResult Add()
{
db.Users.Add(new User() { Avatar = new Avatar() { Link = new Uri("http://myUrl/%2E%2E/%2E%2E") }, CreationDate = DateTime.Now, LastActivityDate = DateTime.Now, LastLoginDate = DateTime.Now });
db.SaveChanges();
db.Users.Local.First().Questions = new Collection<Question>() { new Question() };
var question = new Question();
question.QuestionRevisions = new Collection<QuestionRevision>();
var questionRevision = new QuestionRevision();
questionRevision.Tags = new Collection<Tag>();
question.QuestionRevisions.Add(questionRevision);
return View(question);
}
and second action which fires when User accepts form:
[HttpPost]
public ActionResult Add(Question containers, HttpPostedFileBase file)
{
The problem is tha I see that Question hasn’t questionrevisions (is null)
Why this object is resetting?
I have a field in Controller:
PasmISOContext db = new PasmISOContext();
Here is a class Question
public class Question
{
[Key]
public int Id { get; set; }
public virtual User Creator { get; set; }
public int CreatorId { get; set; }
public int PhotoId { get; set; }
public virtual ICollection<QuestionRevision> QuestionRevisions { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
public virtual ICollection<QuestionVote> Votes { get; set; }
public virtual Photo Photo { get; set; }
}
Here is a definition of my context:
public class PasmISOContext : DbContext
{
public DbSet<Avatar> Avatars { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<Question> Questions { get; set; }
public DbSet<QuestionRevision> QuestionRevisions { get; set; }
public DbSet<Photo> Photos { get; set; }
public DbSet<Achievement> Achievements { get; set; }
public DbSet<Comment> Comments { get; set; }
public DbSet<Tag> Tags { get; set; }
public DbSet<QuestionVote> QuestionVotes { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
The reason the QuestionRevisions doesn’t get properly bound is because the corresponding textarea field doesn’t have a correct name so that the default model binder could bind it. You may take a look at the following blog post explaining what is the correct wire format for collections.
So to fix the problem one possibility is to change the type in your view model from
ICollection<QuestionRevision>toIList<QuestionRevision>so that you have indexer access to elements of the collection and then in the view simply:Now the generated HTML will look like this:
Notice how the name of the textarea respects the wire format expected by the default model binder to work with collections. Now when you submit the form the
QuestionRevisionslist will be correctly bound and it will contain a single element.