2

I've been following Darin's answer to a question I had on slimming down my controllers and I'm running into problems with this IEntityChangeTracker exception:

An entity object cannot be referenced by multiple instances of IEntityChangeTracker.

Here's my model binder:

public class PostModelBinder : IModelBinder
{
    private readonly IPostRepository _repository;

    public PostModelBinder(IPostRepository repository)
    {
        _repository = repository;
    }

    public object BindModel(ControllerContext controllerContext,
                            ModelBindingContext bindingContext)
    {
        var postIDValue = controllerContext.Controller.ValueProvider.GetValue("postID");
        int postID;

        if (postIDValue == null || !int.TryParse(postIDValue.AttemptedValue, out postID))
            return null;

        return _repository.FindPost(postID, filterByPublished: true);
    }
}

After this, my custom action filter simply carries out a bit of validation on the post and redirects if the post isn't valid. Up until this point, everything is fine. The error happens in my controller when I try to update the post read count:

public class PostsController : Controller
{
    private IPostRepository postRepository;

    // snip...

    [AutoMap(typeof(Post), typeof(PostViewModel)), HttpGet]
    [PostActionFilter]
    public ActionResult ShowPost(Post model)
    {
        postRepository.PostVisited(model);

        return View(model);
    }
}

I understand IEntityChangeTracker's complaining because I effectively end up with 2 repositories referencing the same object and that just seems like bad mojo waiting to happen. I know I could push the PostVisited() call into PostModelBinder but updating a model doesn't seem like behaviour that belongs there.

Is there another way around this?

Thank you.

Community
  • 1
  • 1
John H
  • 14,422
  • 4
  • 41
  • 74
  • out of curiosity, why are you posting to ShowPost but specifying HttpGet, and then in turn showing a View, rather than redirecting to a HttpGet action (Post/Redirect/Get pattern?) am I reading this properly? – Adam Tuliper Jan 30 '12 at 20:43
  • @AdamTuliper ShowPost is displaying a blog post within my PostsController. It's not handling HttpPost. – John H Jan 30 '12 at 20:49

1 Answers1

2

From the error, I assume your two IPostRepository implementation objects use different Entity Framework object contexts; you can fix this by using the same object context throughout a request.

Some DI containers support per-request object lifetimes, otherwise you can lazy-load and store your object context in HttpContext.Items and dispose of it at the end of the request, as mentioned in this question.

Community
  • 1
  • 1
Steve Wilkes
  • 7,085
  • 3
  • 29
  • 32
  • Hi Steve, thanks for the answer and the question link. Does this mean I'd create an object manager for the context, create a new context on each request, give that to the repositories in their constructors and then dispose of the context at the end of the request? – John H Jan 30 '12 at 21:06
  • Sorry it's taken me such a long time to accept your answer. I was sick for a few weeks and after that I decided this was a good excuse to learn to use dependency injection. I ended up having to ask a related question for Ninject and I've [self-answered](http://stackoverflow.com/a/9231697/729541) that question with a test implementation, for anyone interested. – John H Feb 10 '12 at 17:07
  • Hey John, no problem, glad you're feeling better. Good for you for going the more 'proper' route and using DI :) – Steve Wilkes Feb 11 '12 at 09:21
  • Hey Steve, thanks for the help and the words of encouragement. Have a good weekend! :) – John H Feb 11 '12 at 13:16