开发者

How to pass ObjectId from MongoDB in MVC.net

I'm starting a new project with Mongo, NoRM and MVC .Net.

Before I 开发者_如何学编程was using FluentNHibernate so my IDs were integer, now my IDs are ObjectId. So when I have an Edit link my URL looks like this :

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

And it does not bind automaticly to my controller as an ObjectId

Do you have any suggestions/best practices to work with this? Do I need to encode/decode the ID everytime?

Thanks!


Use a custom model binder like this ... (working against the offical C# MongoDB driver)

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


I Use following

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

and

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

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

almost forgot, make URLs from ObjectId.ToString()


I am not familiar with the ObjectId type but you could write a custom model binder that will take care of converting the id route constraint to an instance of ObjectId.


Did you know you can use the [MongoIdentifier] attribute to make any property act as the unique key?

I've been solving this issue by borrowing a technique from WordPress by having every entity also be represented by a "url slug" property and decorating that property with [MongoIdentifier].

So if I had a person named Johnny Walker I'd create a slug of "johnny-walker". You just have to make sure these url slugs stay unique and you get to keep clean urls without ugly object ids.


For Web API you can add Custom parameter binding ule in 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");
            }
        }
    }
}

And use it Without any additional attributes in controller:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜