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

Adrian Grigore
  • 33,034
  • 36
  • 130
  • 210

4 Answers4

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.

Robert Koritnik
  • 103,639
  • 52
  • 277
  • 404
  • Yup, that's correct. I am using Renderaction as part of a postback. I guess I'll have to use RenderView instead... :-\ – Adrian Grigore Nov 20 '10 at 00:10
  • If you can get away with `RenderPartial` use that by all means. It's also faster compared to `RenderAction`. – Robert Koritnik Nov 21 '10 at 08:43
  • I've written functionality in the past where you could write something like `Html.RenderAction(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. – Robert Koritnik Nov 21 '10 at 09:05
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" });}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • 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. – Adrian Grigore Nov 19 '10 at 18:07
  • 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) – Adrian Grigore Nov 20 '10 at 00:15
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));
ARM
  • 2,385
  • 1
  • 13
  • 11
  • This looks like a good solution, but sadly it doesn't seem to have made it into MVC 3. – Adrian Grigore Nov 20 '10 at 00:09
  • Check the MVC3 Futures at http://aspnet.codeplex.com/releases/view/54306#DownloadId=159305 as it might be in there rather than base MVC3 – ARM Nov 22 '10 at 20:44
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.

brazilianldsjaguar
  • 1,409
  • 1
  • 20
  • 45