简体   繁体   中英

ModelState.IsValid contains errors when using MongoDB

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?

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());
}

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)

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM