Ctrl_Alt_Defeat
Ctrl_Alt_Defeat

Reputation: 4009

Methods in MVC with same signature

I have a GET and POST method with the same signature which is giving a compile time error.

    [HttpGet]
    public ActionResult MyAction(string myString) 
    {
        // do some stuff
        return View();
    }

    [HttpPost]
    public ActionResult MyAction(string myOtherString) 
    {
        // do different stuff
        return View();
    }

So I have to do something with myString in the Get Request but I have to do something else with myOtherString in POST request. Doing some research I have see the following stack overflow answer - post and get with same method signature

Accepted answer was:

[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Friends()
{
    // do some stuff
    return View();
}

// Post:
[ActionName("Friends")]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Friends_Post()
{
    // do some stuff
   return View();
}

My question really is - in the accepted answer will a POST Request to "SomeController", "Friends" still result in the Friends_Post action being executed?

Upvotes: 3

Views: 2298

Answers (4)

lazydeveloper
lazydeveloper

Reputation: 961

You can achieve this using Routing(>=MVC 5),Controller methods with same signature and different routing attribute

[ActionName("ConfirmDelete")]
    public ActionResult Delete(int id)
{
    ...
}

[ActionName("Delete")]
public ActionResult DeleteConfirm(int id)
{
    ...
}

Upvotes: 0

Chris Pratt
Chris Pratt

Reputation: 239300

There's two sides to creating valid action methods. 1) The routing framework has to be able to make a distinction and 2) it has to be compile-able code in the first place.

Making one GET and one POST satisfies the first requirement: the routing framework will know which action to call. However, from a basic C# perspective, you still have two methods in the same class with the same signature: name, parameter types and count, and return value. If you change just one of these factors, the code can compile.

The easiest way, and you'll actually see this used in a scaffolded controller with CRUD actions, is to change the name of the POST action, but then decorate it with the ActionName attribute to keep the URL the same. As I said, a scaffolded controller with CRUD actions uses the following as an example:

public ActionResult Delete(int id)
{
    ...
}

[HttpPost]
[ActionName("Delete")]
public ActionResult DeleteConfirm(int id)
{
    ...
}

Upvotes: 3

Christian Phillips
Christian Phillips

Reputation: 18769

I would expect a Post to take an Object / Entity or at least a ViewModel of what you're actually updating or inserting. So, in the case of Friend...

To get a list of friends...

[HttpGet]
public ActionResult MyAction(string myString) 
{
   //return all friends or friends that satisfy filter passed in...
}

Not sure if the string is required, but it could be used as a filter.

As for the Post...

[HttpPost]
public ActionResult MyAction(Friend friend) 
{
 //add new friend
}

or...

[HttpPost]
public ActionResult MyAction(Friend friend, int id) 
{
 //update friend by id
}

You can see the signatures are all different, since they should be performing different actions. You can call them the same method name, but this wouldn't make too much sense to a developer picking the code up after you. Names like GetFriends / UpdateFriend / InsertFriend / UpsertFriend etc are self explanatory.

Upvotes: 1

Anthony Shaw
Anthony Shaw

Reputation: 8166

create a view model to pass and post back, this will work for what you are trying to do.

[HttpGet]
public ActionResult MyAction(string myString) 
{
    var model = new MyActionModel();
    // do some stuff
    return View(model);
}

[HttpPost]
public ActionResult MyAction(string myString, MyActionModel model) 
{
    // do different stuff
    return View(model);
}

Upvotes: 0

Related Questions