Question

I'm trying to create a basic movie database using ASP.NET MVC 4 and MongoDB. My problem is in the POST Update method of my MovieController.

[HttpPost]
    public ActionResult Update(Movie movie)
    {
        if (ModelState.IsValid)
        {

            _movies.Edit(movie);

            return RedirectToAction("Index");
        }

        return View();
    }

The ModelState contains an error for the movie's Id field (which is an ObjectId object) and throws the following exception:

 {System.InvalidOperationException: The parameter conversion from type 'System.String' to type 'MongoDB.Bson.ObjectId' failed because no type converter can convert between these types

This is the Update view:

@model MVCMovie.Models.Movie

@{
    ViewBag.Title = "Update";
}

<h2>Update</h2>

@using (Html.BeginForm())
{
    @Html.HiddenFor(m => m.Id);
    @Html.EditorForModel()

    <p>
        <input type="submit" value="Update" />
    </p>
}

And the Movie class in Models:

namespace MVCMovie.Models
{
    public class Movie
    {
        [BsonId]
        public ObjectId Id { get; set; }

        public string Title { get; set; }

        public DateTime ReleaseDate { get; set; }

        public string Genre { get; set; }

        public decimal Price { get; set; }

        [ScaffoldColumn(false)]
        public DateTime TimeAdded { get; set; }
    }
}

EDIT: Solution I added the [ScaffoldColumn(false)] to the Id so that the browser does not attempt to render it. However I still needed to implement the solution provided by Mihai in order to pass the correct Id.

I'm assuming that the problem is being caused in the view because it tries to send a string instead of an ObjectId object. But I cannot figure out how to fix this, any ideas?

Was it helpful?

Solution 2

The problem is that MVC doesn't know how to convert your Id to ObjectId type. It only sees it as string.

You'll have to use a custom binder for your method. Have a look at this link http://www.dotnetcurry.com/ShowArticle.aspx?ID=584

Have a look at this

public class MovieModelBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var modelBinder = new DefaultModelBinder();
        var movie = modelBinder.BindModel(controllerContext, bindingContext) as Movie;
        var id = controllerContext.HttpContext.Request.Form["Id"];
        if (movie != null)
        {
            movie.Id = new ObjectId(id);
            return movie ;
        }

        return null;
    }
}

And change your Update method as so

public ActionResult Update([ModelBinder(typeof(MovieModelBinder))] Movie movie)

OTHER TIPS

For anyone else looking for this answer, from this post and it works perfectly : http://www.joe-stevens.com/2011/06/12/model-binding-mongodb-objectid-with-asp-net-mvc/

Create a Model Binder :

public class ObjectIdBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        return new ObjectId(result.AttemptedValue);
    }
}

Then register in app start :

protected void Application_Start()
{
    ModelBinders.Binders.Add(typeof(ObjectId), new ObjectIdBinder());
}

Seems you need to writer your own custom type converter.
Check out this discussion: ObjectId Type Converter

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top