2012-04-11 2 views
0

Ich kann nicht die ObjectId für ein Modell mit der offiziellen MongoDB csharp offiziellen Bibliothek zurückgeben. Wenn ich das Formular zurückschicke, das zurück zum Controller sendet, kommt die PageID immer im Modell zurück {000000000000000000000000}. Der gerenderte HTML-Code hat die gültige ID, dass ein Feld nie korrekt aus dem Formularpost zurückkommt.MongoDB: MVC Serialisierung BsonId auf Post

Die html macht: <input id="PageID" name="PageID" type="hidden" value="4f83b5ccd79f660b881887a3" />

Dies ist, was ich habe.

Modell:

public class PageModel 
    { 
     public PageModel() 
     { 
      CanEdit = false; 
      CancelRequest = false; 
     } 

     [BsonId] 
     public ObjectId PageID { get; set; } 

     [Display(Name = "Page URL")] 
     public string PageURL { get; set; } 

     [AllowHtml] 
     [Display(Name = "Content")] 
     public string Value { get; set; } 

     [Display(Name = "Last Modified")] 
     public DateTime LastModified { get; set; } 

     [BsonIgnore] 
     public bool CancelRequest { get; set; } 
     [BsonIgnore] 
     public bool CanEdit { get; set; } 

    } 

Controller-Beitrag:

[HttpPost] 
     public ActionResult Edit(PageModel model) 
     { 
      // check to see if the user canceled 
      if (model.CancelRequest) 
      { 
       return Redirect(model.PageURL); 
      } 

      // check for a script tag to prevent 
      if (!model.Value.Contains("<script")) 
      { 
       // save to the database 
       model.LastModified = DateTime.Now; 
       collection.Save(model); 

       // return to the page 
       return Redirect(model.PageURL); 
      } 
      else 
      { 
       ModelState.AddModelError("Value", "Disclosures discovered a script in the html you submitted, please remove the script before saving."); 
      } 

      return View(model); 
     } 

Ausblick:

@model LeulyHome.Models.PageModel 

@{ 
    ViewBag.Title = ""; 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
} 

@using (Html.BeginForm()) 
{ 
    <fieldset> 
     <legend>Edit Page</legend> 
     <div class="control-group"> 
      @Html.LabelFor(m => m.PageURL, new { @class = "control-label" }) 
      <div class="controls"> 
       @Html.TextBoxFor(m => m.PageURL, new { @class = "input-xlarge leu-required span9" }) 
       @Html.ValidationMessageFor(m => m.PageURL, null, new { @class = "help-block" }) 
      </div> 
     </div> 
     <div class="control-group"> 
      @Html.LabelFor(m => m.Value, new { @class = "control-label" }) 
      <div class="controls"> 
       @Html.TextAreaFor(m => m.Value) 
       @Html.ValidationMessageFor(m => m.Value, null, new { @class = "help-block" }) 
      </div> 
     </div> 
     <div class="control-group"> 
      @Html.LabelFor(m => m.LastModified, new { @class = "control-label" }) 
      <div class="controls"> 
       @Html.DisplayFor(m => m.LastModified) 
       @Html.HiddenFor(m => m.LastModified) 
      </div> 
     </div> 

     @Html.HiddenFor(m => m.PageID) 
     @Html.HiddenFor(m => m.CancelRequest) 

     <div class="form-actions"> 
      <button type="submit" class="btn btn-primary">Save Page</button> 
      <button type="button" class="btn btn-danger" id="cancelBtn">Cancel Changes</button> 
     </div> 
    </fieldset> 
} 

@section Footer { 
    <script type="text/javascript" src="@Url.Content("~/Content/ckeditor/ckeditor.js")"></script> 
    <script language="javascript" type="text/javascript"> 
     $(document).ready(function() { 
      // adjust the editor's toolbar 
      CKEDITOR.replace('Value', { 
       toolbar: [["Bold", "Italic", "Underline", "-", "NumberedList", "BulletedList", "-", "Link", "Unlink"], 
        ["JustifyLeft", "JustifyCenter", "JustifyRight", "JustifyBlock"], 
        ["Cut", "Copy", "Paste", "PasteText", "PasteFromWord", "-", "Print", "SpellChecker", "Scayt"], ["Source", "About"]] 
      }); 

      $("#cancelBtn").click(function() { 
       $("#CancelRequest").val("True"); 
       $("#updateBtn").click(); 
      }); 
     }); 
    </script> 
} 

Antwort

2

Es sieht aus wie Sie einen String-Wert für PageID senden, die Sie ein Objekt erwarten Geben Sie Objekt-ID ein.

Die Bindung des Modells wird nicht wissen, wie man diese Zeichenfolge nimmt und sie in eine ObjectId verwandelt. Wenn Sie sich die ObjectId-Klasse im MongoDriver ansehen, werden Sie sehen, dass sie ziemlich haarig ist.

Wir verwenden mongodb ziemlich viel und für unsere IDs verwenden wir einfach Strings, die viel Flexibilität bieten. Ich bin mir nicht sicher, für welchen Anwendungsfall Sie die ObjectId-Klasse als Dokument-ID benötigen, aber möglicherweise nicht.

So von hier scheint es, als ob Sie zwei Möglichkeiten haben.

  1. Dokument-IDs auf Strings oder etwas ändern sonst
  2. ein benutzerdefiniertes Modell Binder schreiben für die ObjectId Klasse

Hoffnung, das hilft :)

+0

Vielen Dank für die Informationen. Ich bin in MVC gewürzt, aber neu in MongoDB. Ihre zweite Option gab mir tatsächlich genug Informationen, um weiterzumachen und ich konnte ein Modellbinder erstellen, um das für mich zu erledigen. Hier ist ein Beispiel von einem. http://www.joe-stevens.com/2011/06/12/model-binding-mongodb-objectid-with-asp-net-mvc/ – uadrive

1

erstellen Bindung:

Öffentlichkeit Klasse ObjectIdBinder: IModelBinder {

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
{ 
    var result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 
    return !string.IsNullOrWhiteSpace(result.AttemptedValue) ? ObjectId.Parse(result.AttemptedValue) : ObjectId.Empty; 
} 

}

erstellen ModelBinderConfig:

Namespace Nasa8x.CMS { public class ModelBinderConfig { public static void Register (ModelBinderDictionary Bindemittel) { binder.Add (typeof (ObjectId), neuer ObjectIdBinder());

 binder.Add(typeof(string[]), new StringArrayBinder()); 

     binder.Add(typeof(int[]), new IntArrayBinder()); 

    } 
} 

}

Register auf Global.cs:

protected void Application_Start() 
      { 

       ModelBinderConfig.Register(ModelBinders.Binders); 

       WebApiConfig.Register(GlobalConfiguration.Configuration); 
       FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 
       RouteConfig.RegisterRoutes(RouteTable.Routes);  

      } 
0

Wenn Sie die PageID Eigenschaft in Ihrem C# Klasse brauchen nicht von Typ ObjectId zu sein, aber die Vorteile dieser Art auf der MongoDB-Side nehmen möchten, können Sie die Treiber kümmern lassen die Umwandlung in Ihrer Klasse-Definition:

public class PageModel 
{ 

    [BsonId] 
    [BsonRepresentation(BsonType.ObjectId)] 
    public string PageID { get; set; } 

}