Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a GUID as the ID in a database with ASP.NET MVC

I am learning ASP.NET MVC. I am following one of the basic tutorials on asp.net. Since I do not always follow the tutorials to the letter, I decided to use a GUID as the identity column instead of an integer. Everything was working fine until I got up to the point of adding a new record to the database through the MVC application. When I added the new record, it inserted a blank GUID instead of a generated one. Here is the segment of code-behind that handles the insertion:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "id")]Movie movieToCreate)
{
    try
    {
        _entities.AddToMovieSet(movieToCreate);
        _entities.SaveChanges();

        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}

The [Bind(Exclude = "id")] line 'ignores' the ID column, since it is autogenerated. In the tutorial, the ID is auto-incremented but I think that is because it is an integer. I tried adding a line to this method:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "id")]Movie movieToCreate)
{
    try
    {
        movieToCreate.id = Guid.NewGuid();
        _entities.AddToMovieSet(movieToCreate);
        _entities.SaveChanges();

        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}

But the id is still an empty GUID. Can anyone provide me with some information on why this is and perhaps how to resolve it?

like image 737
Anders Avatar asked Aug 19 '09 19:08

Anders


3 Answers

You could use a custom ModelBinder. I learned about those over here.

public class MyClassBinder : DefaultModelBinder {
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) {
        var model = (Movie)base.CreateModel(controllerContext, bindingContext, modelType);
        model.id = Guid.NewGuid();
        return model;
    }
}

And your action controller would be:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult MyAction(Movie movieToCreate) {
    // movie should have a new guid in the id
    _entities.AddToMovieSet(movieToCreate);
    _entities.SaveChanges();
}

And you would need to register the binder in Global.asax:

protected void Application_Start() {
    RegisterRoutes(RouteTable.Routes);
    ModelBinders.Binders.Add(typeof(Movie), new MyClassBinder());
}
like image 101
swilliams Avatar answered Sep 23 '22 21:09

swilliams


The SQL Server EF provider in .NET 3.5 SP1 cannot retrieve server-generated GUIDs, since archaic versions of SQL Server couldn't support that. So you need to generate the GUID client-side, until this limitation is fixed.

You can do this in a model binder, as swilliams suggests, but IMHO binders should only bind data in the request. So I do it on my model tier. But either way will work.

like image 32
Craig Stuntz Avatar answered Sep 23 '22 21:09

Craig Stuntz


What is the type of ID field in SQL database? Is it uniqueidentifier? If not, change it to uniqueidentifier and make it autogenerated. Check out this article.

like image 34
Sorantis Avatar answered Sep 23 '22 21:09

Sorantis