Reputation: 37
Im just starting to learn MVC 3 and i could do with some advice on the best way of achieving something.
I have a basic scenario where i can create a blog post with some text and a a collection of tag objects. Each blog can have multiple tags and each tag be attatched to multiple blogs.
public class BlogPost
{
public int ID { get; set; }
public string BlogText { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}
public class Tag
{
public int ID { get; set; }
public string TagText { get; set; }
public virtual ICollection<BlogPost> Blogs { get; set; }
}
This creates the 2 model tables with the join table as id expect.
Whats the best way to go about adding a section to the create view of the BlogPost model that will allow me to add, edit and delete a set of tags (like in the index view)?
My initial thought would be to use a partial view of the tag object passing through the Model.Tags property but it looks like the Model property is null. Is this a good way of doing it or is there a better way?
Ok, so the action to create the view is the standard one generated:
// GET: /Blog/Create
public ActionResult Create()
{
return View();
}
The view code is as follows:
@model MVC_ManyToManyTest.Models.BlogPost
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>BlogPost</legend>
<div class="editor-label">
@Html.LabelFor(model => model.BlogText)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.BlogText)
@Html.ValidationMessageFor(model => model.BlogText)
</div>
<div id="HolderForPartialView">
@Html.Partial("ViewUserControl1", Model.Tags);
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
the partial view created is:
@model IEnumerable<MVC_ManyToManyTest.Models.Tag>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
TagText
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.TagText)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
@Html.ActionLink("Details", "Details", new { id=item.ID }) |
@Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
</table>
My Problem
Once I load the partial view i get the null reference at this line:
@Html.Partial("ViewUserControl1", Model.Tags);
the Model object is null
Upvotes: 0
Views: 4510
Reputation: 47774
What I feel your code should be like is this,
public class MainModel
{
public BlogPost MyBlogPost {get; set;}
public Tags MyTags {get; set;}
}
First View
@model MVC_ManyToManyTest.Models.MainModel
// Use model.MyBlogPost.variables here
...
@Html.Partial("ViewUserControl1", Model.Tags);
....
Partial View
@model IEnumerable<MVC_ManyToManyTest.Models.Tag>
// Use model.MyTags.variables here
...
I am not very sure about this, but I once had a similar problem which I had solved using this. Hope this helps.
Upvotes: 0
Reputation: 15513
The Model is null because your action method is not sending one in:
return View();
You need to give it an empty model with an empty collection of Tags. Something like:
var model = new BlogPost { Tags = new Collection<Tag>() };
return View(model);
Alternatively, you can also make the creation of empty collections as part of your model constructor:
public class BlogPost
{
public BlogPost()
{
this.Tags = new Collection<Tag>();
}
public int ID { get; set; }
public string BlogText { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}
Upvotes: 2