Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC3 - Insert using ViewModel - Object reference not set to an instance of an object

I have got two models, seen below, and am trying to insert one of each to the database from one view. I have created a view model in an attempt to do this.

public class Blog
{
    public int BlogID { get; set; }
    public string Title { get; set; }
    public DateTime CreatedOn { get; set; }

    public virtual User User { get; set; }
    public virtual ICollection<BlogPost> Posts { get; set; }     
}

public class BlogPost
{
    public int PostID { get; set; }
    public string Body { get; set; }
    public DateTime CreatedOn { get; set; }

    public int UserID { get; set; }
    public virtual User User { get; set; }
}

public class BlogViewModel
{
    public Blog Blog { get; set; }
    public BlogPost BlogPost { get; set; }
}

Using the view model i am posting to the create controller:

[HttpPost]
    public ActionResult Create(BlogViewModel blog)
    {
        if (ModelState.IsValid)
        {
            User user = unit.UserRepository.GetUser();
            blog.Blog.User = user;
            blog.Blog.CreatedOn = DateTime.Now;

            unit.BlogRepository.Insert(blog.Blog);
            unit.BlogPostRepository.Insert(blog.BlogPost);
            unit.Save();

            return RedirectToAction("Index");  
        }

        return View(blog);
    }

This keep throwing the error

Object reference not set to an instance of an object.

on the line blog.Blog.User = user.

Any thoughts on what i'm doing wrong?

EDIT I checked the POST data and it was all there and correct but it was posting everything as Blog.Title = and BlogPost.Body = so the viewmodel in the controller wasn't receiving anything. If i change the controller actionresult to:

public ActionResult Create(Blog blog, BlogPost post)

Then it all works. So why doesn't data sent in the viewmodel format? I am using explicit view model based interaction between your views and controller

@model Test.Models.BlogViewModel
@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Blog</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.Blog.Title)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Blog.Title)
            @Html.ValidationMessageFor(model => model.Blog.Title)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.BlogPost.Body)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.BlogPost.Body)
            @Html.ValidationMessageFor(model => model.BlogPost.Body)
        </div>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>
like image 235
Michael Willmott Avatar asked Nov 05 '11 13:11

Michael Willmott


2 Answers

Simply rename your action argument:

public ActionResult Create(BlogViewModel viewModel)

There is a conflict because your action argument is called blog and yet your view model (BlogViewModel) has a property called Blog. The problem is that the default model binder no longer knows what to do in such situation.

Oh and if you absolutely need to have your action argument called blog then you could also rename the Blog property on your view model.

like image 110
Darin Dimitrov Avatar answered Sep 21 '22 09:09

Darin Dimitrov


I have ran in these kinds of situation before. This happens, when the data that you are sending from your view is not in a format, that MVC default model binding engine can understand or can map to your view model object. Try using "FireBug" and see as how the data is being passed via POST. And then see, if that data can be mapped to the definition of your view model.

One more thing, are you using jQuery to pass the data or you are using explicit view model based interaction between your views and controller ?

like image 23
Pawan Mishra Avatar answered Sep 21 '22 09:09

Pawan Mishra