views:

786

answers:

2

With ASP.net MVC is it possible to POST a form to a controller action which includes parameters not in the form, but from the URL?

For example

The Action method in GroupController:

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create(int idOne, int idTwo, Model model)
    { ... }

The route:

"{controller}/{action}/{idOne}/{idTwo}"

Posted URL:

/Employee/Show/1/42

In this example, the form is being posted to a different controller, the model has the correct value, however the other parameters have default values 0.

The behavior I was expecting is that the ModelBinder would see that I have two parameters that match the given route, and assign the current values of 1 and 42 to the parameters in the same same way a GET operation works.

Is this behavior not supported, or am I missing something?

EDIT: To be clear, the form on the Show view for the controller Employee contains a form which is posting to a different controller. We can call it Group.

The form action URL looks like this

/Groups/Create/0/0

The form is declared as follows

Html.BeginForm("Create", "Groups")

After trying many different overloads for Html.BeginForm I have found that the parameters are only mapped when the form action URL matches the current URL in the browser address bar.

So if i navigate to the URL /Groups/Create/1/42 I will have a new form. If I then submit the form, the URL route values are passed to the POST action.

A: 

If I understand your question correctly, you want the action of the rendered <form> element pointing to URL containing route values. This should be possible with one of the overloads of the HtmlHelper.BeginForm() extension method:

Html.BeginForm("action","controller", new { idOne=1, idTwo=2 }, FormMethod.Post);

Let me know if I got your question all wrong :)

Jørn Schou-Rode
Sort of. As i stated in the question, the for action already contains a URL with the correct route values (1 and 42 from the example). The problem is when i step into the executing action, the two parameters have value 0. I tried your suggestion, but the values were still 0.
Karl
+1  A: 

I'm pretty sure that you can only post form data from inputs inside the form. Have you considered rendering the view in such a way to create form input values off of the URL (perhaps with an HTML helper?).

UPDATE: If you don't want to use the form at all, use ControllerContext.RouteData.Values["idOne"] as opposed to passing it in through the method signature.

Brandon Linton
Within the form I made a query to the route values, ViewContext.RouteData.Values["idOne"], however on the final rendered page has a value of 0, not the value from the route. Is there another approach to get the current URL route values from within a View/Partial?
Karl
If you use an Html helper extension, you should be able to see it off of the helper instance itself. The syntax would look like `helper.ViewContext.RouteData.Values["idOne"]`. Alternately, you could store those ID values in a view model and pass it to the view that way.
Brandon Linton
+1 Same thoughts. Why not include the it in values as hidden fields within the Html.BeginForm("Create", "Groups")? Also, should you be 'Posting' to Create a new form?
Ahmad
What is the alternative to posting to create a new entity? I was trying to avoid placing hidden fields because it adds extra work for passing them between views/controllers. Especially since this functionality does work in other cases. At this point, it seems that is the only way to get past this issue
Karl
Karl - I played around with it a bit, and it looks like you can snag the values you're interested in through the `ControllerContext` object (see my update). Let me know if that works out!
Brandon Linton
@Brandon I will give that a try. Thanks for help!
Karl
@Karl did you end up getting to the bottom of this one?
Brandon Linton
@Brandon What i ended up doing was including the id I wanted in the model itself, and passing it as a parameter to the form action. It isnt the cleanest way, but It is working for now. I tried your updated answer, however that did not return the correct value.
Karl