2010-06-29 12 views
9

Ich beginne ein neues Projekt mit Mongo, NoRM und MVC .Net.Wie übergeben ObjectId von MongoDB in MVC.net

Bevor ich FluentNHibernate verwendet habe, waren meine IDs Integer, jetzt sind meine IDs ObjectId. Also, wenn ich ein Link Bearbeiten meine URL sieht wie folgt aus:

WebSite/Admin/Edit/23,111,160,3,240,200,191,56,25,0,0,0

Und es bindet nicht automatisch zu meinem Controller als eine ObjectId

Haben Sie irgendwelche Vorschläge/Best Practices, um damit zu arbeiten? Muss ich die ID jedes Mal codieren/decodieren?

Danke!

Antwort

14

Ich verwende folgende

public class ObjectIdModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     string value = controllerContext.RouteData.Values[bindingContext.ModelName] as string; 
     if (String.IsNullOrEmpty(value)) { 
      return ObjectId.Empty; 
     } 
     return new ObjectId(value); 
    } 
} 

und

protected void Application_Start() 
    { 
     ...... 

     ModelBinders.Binders.Add(typeof(ObjectId), new ObjectIdModelBinder()); 
    } 

fast vergessen, machen URLs von ObjectId.ToString()

+1

Diese Lösung funktioniert nicht, wenn die Werte in einem Formular übergeben werden. Sehen Sie meine Antwort für eine Lösung, die funktioniert, egal wie die Werte übergeben werden. (Vielleicht ist es auch erwähnenswert, für welchen C# MongoDB-Treiber das war, da ihre Syntax variiert). –

+0

Ursprüngliche Frage war im Zusammenhang mit ASP.NET MVC und Standardcode, der es dem Controller ermöglichen würde, ObjectId von der URL zu analysieren. – Sherlock

0

Ich bin nicht mit der ObjectId Art vertraut, aber man könnte ein custom model binder schreiben, die Pflege der Umwandlung die id Route Beschränkung auf eine Instanz ObjectId stattfinden wird.

0

Wussten Sie, dass Sie das Attribut [MongoIdentifier] verwenden können, um eine Eigenschaft als eindeutigen Schlüssel zu definieren?

Ich habe dieses Problem gelöst, indem ich eine Technik aus WordPress ausgeliehen habe, indem ich jede Entität auch durch eine "url slug" -Eigenschaft darstellen ließ und diese Eigenschaft mit [MongoIdentifier] dekorierte.

Also, wenn ich eine Person namens Johnny Walker hätte, würde ich eine Schnecke von "Johnny-Walker" erstellen. Sie müssen nur sicherstellen, dass diese URL-Slugs eindeutig bleiben und Sie saubere URLs ohne hässliche Objekt-IDs erhalten.

+0

Yup Ich weiß, dass, da es für die einzige ist Ich brauche keine sauberen URLs. Für den Moment habe ich eine IdValue-Eigenschaft hinzugefügt, die den ObjectId-Wert als String rendert und wenn ich die Daten abrufen muss, die ich gerade mache. Single (new ObjectId (id)) nicht sicher, ob es der beste Weg ist, aber es funktioniert gut ... – VinnyG

13

ein benutzerdefiniertes Modell Bindemittel wie diesen ... (Arbeits gegen die offical C# MongoDB-Treiber)

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

public class ObjectIdModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     var result = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 
     if (result == null) 
     { 
      return ObjectId.Empty; 
     } 
     return ObjectId.Parse((string)result.ConvertTo(typeof(string))); 
    } 
} 
+0

Dies löst eine Ausnahme aus, wenn der Parameter mit fiedled ist. Ich denke, TryParse verwenden und ObjectId.Empty zurückgeben, wenn es ungültig ist, ist eine bessere Möglichkeit, es zu behandeln. – phloopy

0

für Web-API können Sie benutzerdefinierte Parameter Bindung ule in WebApiConfig hinzufügen:

public static class WebApiConfig 
{ 
    public static void Register(HttpConfiguration config) 
    { 
     //... 
     config.ParameterBindingRules.Insert(0, GetCustomParameterBinding); 
     //... 
    } 

    public static HttpParameterBinding GetCustomParameterBinding(HttpParameterDescriptor descriptor) 
    { 
     if (descriptor.ParameterType == typeof(ObjectId)) 
     { 
      return new ObjectIdParameterBinding(descriptor); 
     } 
     // any other types, let the default parameter binding handle 
     return null; 
    } 

    public class ObjectIdParameterBinding : HttpParameterBinding 
    { 
     public ObjectIdParameterBinding(HttpParameterDescriptor desc) 
      : base(desc) 
     { 
     } 

     public override Task ExecuteBindingAsync(ModelMetadataProvider metadataProvider, HttpActionContext actionContext, CancellationToken cancellationToken) 
     { 
      try 
      { 
       SetValue(actionContext, new ObjectId(actionContext.ControllerContext.RouteData.Values[Descriptor.ParameterName] as string)); 
       return Task.CompletedTask; 
      } 
      catch (FormatException) 
      { 
       throw new BadRequestException("Invalid ObjectId format"); 
      } 
     } 
    } 
} 

Und sie ohne zusätzliche Attribute in Controller verwenden:

[Route("{id}")] 
public IHttpActionResult Get(ObjectId id) 
Verwandte Themen