2010-06-29 63 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)