1

Is there a pre-built ModelBinder I can use with LINQ to get an object from a DataContext and update it on a HTTP post?

For example, currently I have this block of code:

[AcceptVerbs (HttpVerbs.Post)]
public ActionResult Edit (Project project)
{
    var projectService = Factory.GetService<IProjectService> ();
    project = projectService.GetProject (project.ProjectId);

    UpdateModel<Project> (project);

    if (!ModelState.IsValid)
        return View (project);

    project = projectService.SaveProject (project);

    return RedirectToAction ("Details", new { id = project.ProjectId });
}

(IProjectService wraps up calls to a LINQ data context)

In order to actually perform the update to the database via the LINQ data context, I need to get the project instance again and then update that instance.

Any attempt to simply save the project instance without first getting it from the data context results in nothing being written back to the database - I'm assuming because the LINQ data context knows nothing of the object it doesn't do anything with it.

Using the Attach method on the Projects table class doesn't work either btw, it throws an exception.

3 Answers 3

3
+100

You should look at the implementation in Mike Hadlow's (new BSD) SutekiShop.

In there you will find a DataBindAttribute and BindUsingAttribute which, if I understand correctly, do exactly what you want to do. Notice how the DataBindAttribute.Fetch property is used to rebind the incoming data, or not, (from an HttpPost) to a LINQ entity.

I followed this pattern for one of my projects using ASP.NET MVC and LINQ-To-SQL. It works beautifully.

Here's the source: http://www.google.com/codesearch?hl=en&lr=&q=DataBind+package%3Ahttp%3A%2F%2Fsutekishop.googlecode.com&sbtn=Search

Sign up to request clarification or add additional context in comments.

1 Comment

SutekiShop has a lot of great code, glad it is working for you.
0

I think the project you pass in to the method is the one you want to perform UpdateModel with isn't it?

Otherwise you are trying to update with pre-existing values not new ones.

Just a thought,

Dan

Code cut out below

[AcceptVerbs (HttpVerbs.Post)]
public ActionResult Edit (Project project)

    UpdateModel<Project> (project);

    if (!ModelState.IsValid)
            return View (project);

    var projectService = Factory.GetService<IProjectService> ();

    project = projectService.SaveProject (project);

    return RedirectToAction ("Details", new { id = project.ProjectId });
}

2 Comments

project and not projectToUpdate is the one using the ModelBinder
The problem, which I not explaining very well, is that the project instance that comes from the binder is all well and good, apart from the fact it was constructed by the MVC FW somewhere down the line, and not retrieved from the DataContext. When updating that instance, the DataContext basically does nothing, probably because it knows nothing of that object.
0

You need to retrieve the original project as you do then to update it with the properties that have changed in project to update then to submit the update request.

EDIT

Try this code I found:

public static void CloneProperties(this object origin, ref object destination)
{ 
    if (destination == null) throw new ArgumentNullException("destination", "Destination object must first be instantiated."); 
    foreach (var destinationProperty in destination.GetType().GetProperties()) 
    {
       if (origin != null && destinationProperty.CanWrite) 
       { 
          origin.GetType().GetProperties().Where(x => x.CanRead && (x.Name == destinationProperty.Name && x.PropertyType == destinationProperty.PropertyType)) .ToList() .ForEach(x => destinationProperty.SetValue(destination, x.GetValue(origin, null), null)); 
       } 
    } 
} 

3 Comments

Yeah, that's what I'm doing - what I'd like is to maybe create a ModelBinder that would do that for me...simply so I don't have to do a get in the controllers every time. If I change to another ORM later, I'll be doing extra gets that aren't required. All I'd need to do with the binder is remove/ restore the original. Any thoughts?
@Gregorie, I tried using the Attach method a while back, but it throws an exception about the object already exists (I assume it's checking based on it's PK).
That's what the UpdateModel method will do with the freshly retrieved projectToUpdate instance.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.