views:

384

answers:

3

I am having trouble with an ASP.net MVC form Posting to an Action containing multiple parameters. The problem is only some of the parameters are being initialized.

The page has multiple forms each backed by a separate controller.

The controller action receiving the Post action looks like this

public ActionResult Create(int institutionId, int applicationId, [Bind(Prefix = "LogoutItem")]LogoutItemDetail logoutItemDetail)

The form looks like this:

<% using (Html.BeginForm<LogoutItemsController>( c => c.Create(0,0,null))) { %>
  <%= Html.AntiForgeryToken() %>
  <tr>
    <td><%= Html.SubmitButton("btnAdd", "Add") %></td>
    <td><%= Html.TextBox("LogoutItem.Path")%></td>
  </tr>
<% } %>

EDIT Form action URL

/Applications/LogoutItems/Create/0/0

I have verified this url matches the route below with the MVC Route Debugger, and with VS Debugger.

And the route

routes.MapRoute(null, "Applications/{controller}/{action}/{institutionId}/{applicationId}/")

The current URL

Applications/Show?institutionId=1001&applicationId=3003

When I step through, the Create method,

  • institutionId has a value of 1001,
  • applicationId has a value of 0, and
  • logoutItemDetail has the values of the form submission

Any ideas as to why the applicationId parameter does not appear to be initialized?

Edit

Doing a little more testing, I found that if i do not explicitly name the controller/action in the form

<% using (Html.BeginForm()) { %>

Every form in the page is Posted, and all of the correct parameter values. In this case, the forms action value is an empty string. This would be an acceptable solution if every form on the page was not also posted.

A: 

From the information you provided, one possibility is that you added your custom route after the default route in the global.asax file. When you define new routes, you need to add the most specific routes first and work down to the more general, similar to a sieve. If that's the case, simply move your custom route higher in the code so that it is listed before the default route. The reason that your LogoutItemDetail instance bound successfully was because you explicitly declared the binding.

More code would help to make a more accurate assessment, but based on what you shared, that's my best guess...

Neil T.
The additional route is added before the default route. Is there any other information that I can provide that you think will be helpful?
Karl
A: 

what happens if you navigate to /Applications/Show/1001/3003

???

what happens if you change the name of applicadionId to something else? maybe it's a reserved word?

JDPeckham
The URL /Applications/Show/1001/3003 returns a 404 Error. I am not sure why this URL does not work, and I would prefer the URL to not have the query parameters, but that isnt a huge concern for me right now.As for the second suggestion, I changed applicationId to appId with the same result.
Karl
A: 

I agree with Neil T. there's probably another route being picked first. If you could tell us all other mapped routes, that would help (or just comment out all the other routes to test).

In fact, I think JDPeckham's debugging is on the right track since the route mapping you describe doesn't default the {action} parameter, so I wonder how your test url is even getting mapped to the Create method. So try navigating to /Applications/Show/Create/1001/3003. If that url works, then I would definitely say it's the route entries.

Crispy
The only other route entry is the default root: routes.MapRoute(null, "{controller}/{action}", new { controller = "Home", action = "Index" }), routes.MapRoute(null, "{controller}/{action}/{id}")The URL you suggested results in a 404 Error. I have edited my post to show the Form Action which is valid.
Karl
Ok, I had misunderstood what you had meant by "current URL". To your update, I don't see how every form on the page could be posted. I'm assuming you have multiple `<% using (Html.BeginForm()) { %>` for each form, right? Also, what is the class (i.e., the controller) that defines the 'Create' action?I haven't used the generic version of the BeginForm method (which I believe comes from the futures.dll) so maybe there's a bug in it. You could just try the non-generic version so that your using reads:`<% using (Html.BeginForm("Create", new {controller=...,institutionId=...,..)) { %>`
Crispy