2010-06-29 18 views
9

Estoy comenzando un nuevo proyecto con Mongo, NoRM y MVC .Net.Cómo pasar ObjectId desde MongoDB en MVC.net

Antes de utilizar FluentNHibernate, por lo que mis ID eran enteros, ahora mis ID son ObjectId. Así que cuando tengo un enlace Editar mi URL se parece a esto:

sitio web/Admin/Editar/23,111,160,3,240,200,191,56,25,0,0,0

Y no se une automaticamente a mi controlador como un Id. de objeto

¿Tiene alguna sugerencia o mejores prácticas para trabajar con esto? ¿Debo codificar/decodificar la identificación cada vez?

Gracias!

Respuesta

14

yo uso siguiente

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

y

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

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

casi lo olvido, que las direcciones URL de ObjectId.ToString()

+1

Esta solución no funciona cuando los valores se pasan en un formulario. Vea mi respuesta para una solución que funciona sin importar cómo se pasen los valores. (También valdría la pena señalar para qué controlador C# MongoDB era esto, ya que su sintaxis varía). –

+0

La pregunta original estaba en el contexto ASP.NET MVC y el código estándar que permitiría que el controlador analizara ObjectId desde url. – Sherlock

0

No estoy familiarizado con el tipo ObjectId pero se podría escribir un custom model binder que se encargará de convertir la restricción id ruta a una instancia de ObjectId.

0

¿Sabía que puede usar el atributo [MongoIdentifier] para hacer que cualquier propiedad actúe como la clave única?

He estado resolviendo este problema tomando prestada una técnica de WordPress haciendo que cada entidad también sea representada por una propiedad "url slug" y decorando esa propiedad con [MongoIdentifier].

Así que si tuviera una persona llamada Johnny Walker crearía una babosa de "johnny-walker". Solo tienes que asegurarte de que estas barras url permanezcan únicas y consigas mantener las URL limpias sin identificadores de objetos desagradables.

+0

Sí lo sé, ya que es sólo para la administración No necesito tener URL limpias. Por ahora, agregué una propiedad IdValue que representa el valor de ObjectId como una cadena y cuando necesito recuperar los datos solo hago .Single (nuevo ObjectId (id)) no estoy seguro si es la mejor manera, pero funciona bien ... – VinnyG

13

Use un ligante modelo personalizado así ... (trabajando en contra del oficial de C# Controlador MongoDB)

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

Esto arroja una excepción cuando se manipula el parámetro. Creo que usar TryParse y devolver ObjectId.Empty cuando no es válido es una mejor manera de manejarlo. – phloopy

0

Para Web API puede agregar personalizado ULE enlace de parámetros en WebApiConfig:

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

y usarla sin ningún atributo adicional en el regulador:

[Route("{id}")] 
public IHttpActionResult Get(ObjectId id) 
Cuestiones relacionadas