3

When implementing Edit action, I add two methods for Get and Post: Edit(string id)

Ideally, they need have same signature. But of course this is not compilable. So I add a dummy parameter to HttpPost method (form in my case):

[HttpGet]
public ActionResult Edit(string id)
{
    var user = Entities.Users.SingleOrDefault(s => s.UserID == id);
    return View(user);
}

[HttpPost]
public ActionResult Edit(string id, FormCollection form)
{
    var user = Entities.Users.SingleOrDefault(s => s.UserID == id);
    if (TryUpdateModel<User>(user, new[] { "Email", "FullName" }))
    {
        Entities.SaveChanges();
        RedirectToAction("Index");
    }
    return View(user);
}

Any better/cleaner way to implement Edit action?

Evgenyt
  • 10,201
  • 12
  • 40
  • 44
  • 2
    Why would they have the same signature, one takes an ID to display the edit form for, the other should take a domain/viewmodel object that you're editing? You may as well let ASP.NET populate the object for you instead of writing boilerplate code yourself. – Roman Jul 02 '10 at 15:33
  • I do let asp.net populate by using TryUpdateModel. Isn't it the right way to edit model (User entity in my case) – Evgenyt Jul 02 '10 at 15:38
  • Have your action take an instance of `User` as an argument. It'll save you a manual population step. – Roman Jul 02 '10 at 15:44
  • If I use Edit(User user), then how will ASP.NET know that I need to take actual user instance from database (by ID) and update fields from the form? This is why I query User instance from EF, and then update it. Any sample or link? – Evgenyt Jul 02 '10 at 15:48
  • It won't know, it'll create a new disconnected instance and populate it with the form data. You'll still have to retrieve the database data yourself. The other option is, since you're only allowing updating of two fields, you can have an action that takes two fields (and the ID) as arguments. – Roman Jul 02 '10 at 15:50
  • I do not see a way to merge DB data into a disconnected instance of Entity Framework. As for the second option, my example contains two fields just for short. It will have a dozen in a real life. Thanks. – Evgenyt Jul 02 '10 at 15:59
  • You could take a look at [Automapper](http://automapper.codeplex.com/) for copying data over. It would add an extra dependency to your project, but would also allow you to have separate view models and domain models with an easy way to copy data between them. If you decide to not go that route it would be overkill though. – Roman Jul 02 '10 at 16:16

4 Answers4

7

Give the methods a unique name in the controller e.g. add "_POST" as a suffix. You can then use the [ActionName("actualname")] attribute to mark you method with the name your action use.

Chris W
  • 3,304
  • 3
  • 26
  • 28
  • Same answer as: http://stackoverflow.com/questions/724386/post-and-get-with-same-method-signature/724416#724416 – fre0n Oct 17 '11 at 18:17
-1

I would combine them into one:

public ActionResult Edit(string id)
{
    if (Request.HttpMethod == "GET") {
        var user = Entities.Users.SingleOrDefault(s => s.UserID == id);
        return View(user);
    }

    // POST logic
}
Adrian Godong
  • 8,802
  • 8
  • 40
  • 62
  • 7
    This feels like it goes against having lean actions that have a single responsibility. – Roman Jul 02 '10 at 15:42
-1

Why not

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(string id,FormCollection form)  

and

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Edit(string id)  

This will cause the appropriate HTTP request to be handled by the proper method

Sparky
  • 14,967
  • 2
  • 31
  • 45
-1

The Post should have the id in a Model IMO:

[HttpGet]
public ActionResult Edit(string id)
{
    var user = Entities.Users.SingleOrDefault(s => s.UserID == id);
    return View(user);
}

[HttpPost]
public ActionResult Edit(User user)
{        
    if (TryUpdateModel<User>(user, new[] { "Email", "FullName" }))
    {
        Entities.SaveChanges();
        RedirectToAction("Index");
    }
    return View(user);
}
rick schott
  • 21,012
  • 5
  • 52
  • 81
  • So user does not come from DB in your case. SaveChanges will not work. Not sure why you use TryUpdateModel if you have user as action parameter. – Evgenyt Jul 10 '10 at 07:22