RenderAction calls wrong action method
Asked Answered
P

4

6

I'm struggling with renderaction, the problem is that it calls the wrong action method on my controller.

On my "Users" controller there are two action methods called edit, one for get and one for post requests:

public virtual ActionResult Edit(int id)
{
 //return a view for editing the user
}


[AcceptVerbs(HttpVerbs.Post)]
public virtual ActionResult Edit(UserViewModel model)
{
 //modify the user...
}

In my view, I'm calling Renderaction it as follows:

Html.RenderAction("Edit", "Users", new { id = 666});

Now the problem is that I want the GET action method to be rendered. However (perhaps because the model also contains a property called ID?), Renderaction calls my POST action method instead.

What's the proper way to do this? I'm using ASP.NET MVC 3 RC in case it matters.

Thanks,

Adrian

Pietrek answered 19/11, 2010 at 17:57 Comment(1)
I opened a bug for this aspnetwebstack.codeplex.com/workitem/2295Affaire
L
12

Sub action uses HTTP method of its parent action

The problem is that your view is being rendered after a postback action. All sub-action renderings in the view use the same HTTP method. So POST is being replicated on them. I'm not sure about MVC3, but in MVC2 there was no built-in way to overcome this problem.

So the problem is that you want your Edit() action to be rendered as a GET on a POST view. Out of the box. No way.

You can of course do it by providing your own functionality = classes.

Longlegged answered 19/11, 2010 at 21:3 Comment(3)
Yup, that's correct. I am using Renderaction as part of a postback. I guess I'll have to use RenderView instead... :-\Pietrek
If you can get away with RenderPartial use that by all means. It's also faster compared to RenderAction.Longlegged
I've written functionality in the past where you could write something like Html.RenderAction<Home>(HttpMethod.Get, c => c.Index()); where a sub action in a view was always rendered independently of the parent action HTTP method. I've taken basic functionlity from the MvcFutures project that was used in MVC1 where RenderAction didn't exist in the framework yet.Longlegged
R
2

This won't even compile:

public virtual ActionResult Edit(UserViewModel model) {}

[AcceptVerbs(HttpVerbs.Post)]
public virtual ActionResult Edit(UserViewModel model) {}

You cannot have two methods with the same name and same arguments on the same class. Also why your actions are virtual?


UPDATE:

Unable to repro. This doesn't seem to be the case:

public class UserViewModel
{
    public int Id { get; set; }
}

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Edit(int id)
    {
        return View(new UserViewModel());
    }

    [HttpPost]
    public ActionResult Edit(UserViewModel model)
    {
        return View(model);
    }
}

And in Index.cshtml render the edit action calls the correct Edit action (the one with id parameter):

@{Html.RenderAction("edit", "home", new { id = "123" });}
Reminiscence answered 19/11, 2010 at 18:3 Comment(2)
oh, about the virtual: It's because I am using the T4MVC template for strong naming of action methods / controller names, et. The example above doesn't use it, but usually am not using any magic strings in my views.Pietrek
As suggested by Robert Koritnik, it appears that you are using RenderAction as part of a GET request, whereas I am using it in a POST request and the current HTTP method is inherited by Renderaction. It explains the behavior, but I am still not sure how to work around this (without giving up on Renderaction)Pietrek
S
0

I'm not 100% sure if this is available in MVC3, but in MVC2 (with MvcFutures: Microsoft.Web.MVC) I would use:

Html.RenderAction<UsersController>(c => c.Edit(666));
Sturmabteilung answered 19/11, 2010 at 19:50 Comment(2)
This looks like a good solution, but sadly it doesn't seem to have made it into MVC 3.Pietrek
Check the MVC3 Futures at aspnet.codeplex.com/releases/view/54306#DownloadId=159305 as it might be in there rather than base MVC3Sturmabteilung
B
0

I know this is extremely old, and we're on MVC5 now - but this is still the behavior exhibited when running Html.RenderAction().

My solution to this particular case, was to make a check in my [HttpPost] action for values on my view model, and if they were null (or whatever) I called my return Edit(), and if they weren't I called AntiForgery.Validate() to properly validate the token.

Bignonia answered 16/3, 2017 at 23:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.