2012-11-09 40 views
3

我正在嘗試使用ASP.NET MVC 4和MongoDB創建基本電影數據庫。我的問題是在我的MovieController的POST更新方法。ModelState.IsValid在使用MongoDB時包含錯誤

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

      _movies.Edit(movie); 

      return RedirectToAction("Index"); 
     } 

     return View(); 
    } 

的ModelState中包含了電影的ID字段中的錯誤(這是一個的ObjectId對象),並拋出以下異常:

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

這是更新視圖:

@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> 
} 

模型中的電影類:

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

編輯:解決方案 我添加了[ScaffoldColumn(false)]到Id,以便瀏覽器不會嘗試呈現它。不過,我仍然需要實施Mihai提供的解決方案才能通過正確的ID。

我假設在視圖中導致問題,因爲它試圖發送一個字符串,而不是一個ObjectId對象。但我無法弄清楚如何解決這個問題,有什麼想法?

回答

3

問題是,MVC不知道如何將您的Id轉換爲ObjectId類型。它只將它看作字符串。

您必須爲您的方法使用自定義聯編程序。 看一看這個鏈接http://www.dotnetcurry.com/ShowArticle.aspx?ID=584

看一看這個

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

,改變你的更新方法,所以

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

對不起,等待,正在嘗試。它沒有完全工作,但我認爲你在正確的軌道上。發送到該方法的電影現在具有正確的Id(一個ObjectId),但ModelState仍然給我提供了相同的錯誤。我會繼續研究它,謝謝你的幫助到目前爲止 – Matt

+0

嗯..你可以用你自己的驗證邏輯替換ModelState.IsValid,但我假設你想使用該MVC屬性:) – Mihai

+0

得到它的工作,看到我的編輯。謝謝您的幫助! – Matt

9

爲別人尋找這個答案,從這篇文章,它完美的作品:http://www.joe-stevens.com/2011/06/12/model-binding-mongodb-objectid-with-asp-net-mvc/

創建一個模型綁定:

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

然後在應用程序註冊開始:

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

+1這是這裏最好的答案 - 通用和作品! –

+0

我喜歡這個,因爲在所有的控制器上都不需要那麼混亂[ModelBinder(typeof(MovieModelBinder))]。 – ChiliYago

+0

Upvoted用於鏈接Joe Stevens博客。這工作就像買了一個。 –