2010-06-29 59 views
9

我正在用Mongo,NoRM和MVC .Net开始一个新项目。如何在MVC.net中从MongoDB传递ObjectId

在我使用FluentNHibernate之前,我的ID是整数,现在我的ID是ObjectId。所以,当我有一个编辑链接我的网址是这样的:

网站/管理/编辑/ 23,111,160,3,240,200,191,56,25,0,0,0

它不全自动绑定到我的控制器一个ObjectId

你对此有何建议/最佳实践?我需要每次编码/解码ID吗?

谢谢!

回答

14

我用以下

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

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

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

差点忘了,从ObjectId.ToString()

+1

当在表单中传递值时,此解决方案不起作用。无论值如何传递,请参阅我的答案,以获得可行的解决方案。 (可能值得注意的是这是C#MongoDB驱动程序,因为它们的语法各不相同)。 – 2010-12-04 07:10:41

+0

原始问题在ASP.NET MVC和标准代码中,允许控制器从url解析ObjectId。 – Sherlock 2010-12-13 19:51:19

0

我不熟悉ObjectId类型,但可以编写custom model binder,它将负责将id路由约束转换为ObjectId的实例。

0

您是否知道可以使用[MongoIdentifier]属性使任何属性充当唯一键?

我一直在解决这个问题,通过让每个实体都代表一个“url slug”属性并用[MongoIdentifier]装饰该属性来借用WordPress技术。

所以,如果我有一个名叫约翰尼沃克的人,我会创造一个“johnny-walker”的slu slu。你只需要确保这些url slugs保持独特,你就可以保持干净的网址,而不会有丑陋的对象id。

+0

是啊,我知道的是,因为它是只为管理我不需要有干净的网址。现在,我添加了一个IdValue属性,它将ObjectId值呈现为一个字符串,并且当我需要获取我刚刚做的数据时.Single(new ObjectId(id))不确定这是否是最好的方法,但它工作正常。 – VinnyG 2010-06-29 20:00:10

13

使网址使用这样的自定义模型粘合剂... (对官方C#工作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

这会在抛出参数时抛出异常。我认为使用TryParse并在无效时返回ObjectId.Empty是处理它的更好方法。 – phloopy 2012-10-23 15:16:47

0

对于Web API,你可以在WebApiConfig添加自定义参数绑定ULE:

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

而且使用它没有在控制器的任何附加属性:

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