C# – Action with set of fixed parameters in url and a set of optional parameters either from post or from querystring

asp.net-mvccmodel-bindingnetquery-string

In my route collection I have

routes.MapRoute(
"Recalculate",
"{siteLanguage}/Formula.mvc/relcalculate/{identifierString}/{formulaId}/{wratio}/{customRecalcString}",
new { controller = "Formula", action = "Recalculate", wratio = "", customRecalcString = "" }
);

The action it maps to is

public ActionResult Recalculate(string identifierString, int formulaId, string wratio, string customRecalcString, string targetQuantity, int? targetUnit)

As you can see there are severa paremeters that are not in the route description.
These are optional parameters.
When I come in with a POST, the values I put in my form are properly mapped to these parameters.
When I enter with a GET however, the variables are added to the querystring:

/en/Formula.mvc/relcalculate/493133---GREEN%20TILE%20TEST%20PLAQUE---SPECTROSYSTEM/2972591?targetQuantity=1&targetUnit=1

But when arriving at the action, the parameters and the querystring are empty…

Any ideas?

Edit
It seems the querystring just dissapeared halfway.
Altered OP to reflect this
Edit2
After further investigation it appears that once again it comes down to asp.net-mvc's encoding algorithms that seem to fail (or is it me?)
If I fill in the URL in the browser address bar, it works perfectly.
Only when the string is used as an action="" attribute value the querystring dissapears.
If I'm not mistaking the '&' of the querystring should be encoded.

Why isn't Url.RouteUrl() doing this?
Why is Url.Encode() giving me all kinds of bull?
How can I encode only the querystring part without encoding the values?
Edit3
I surrounded the action with Html.Encode() which I should have done from the start off course. Now the page validates again.. but to no avail.
Edit4
Found it!
Basically it's this HTML that's failing

<form action="/en/Formula.mvc/relcalculate/493133---GREEN%20TILE%20TEST%20PLAQUE---SPECTROSYSTEM/2972591?targetQuantity=50&amp;targetUnit=0" method="get">
    <div>
        <input type="submit" class="noPrint" value="Remove RFU" />
    </div>
</form>

As soon as I change the method of the form from get to post, everything works out fine.
That were 2 hours well spent!
Update
In response to comment:
With regard of non-disclosure paranoia I will leave out some stuff, but here's the gist of the page:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="ReadyForUse.aspx.cs" Inherits="CommonProject.Web.Shared.Views.ProductMix.ReadyForUse" %>
<asp:Content ContentPlaceHolderID="headerContentPlaceHolder" runat="server">
    <link href="<%=PathHelper.CssUrl("productMix.css")%>" rel="Stylesheet" type="text/css"/>    
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="mainContentPlaceHolder" runat="server">
    <%string action = Url.RouteUrl("Recalculate",
          new { 
              siteLanguage = ViewData.Model.SiteLanguage.Iso6391[0],
              identifierString = ColorService.GetIdentifierString(ViewData.Model.ActiveColor),
              formulaId = ViewData.Model.ActiveFormula.FormulaId,
              targetQuantity = FormulaService.ParseQuantityFromVolumeString(ViewData.Model.TargetVolume),
              targetUnit = FormulaService.ParseUnitFromVolumeString(ViewData.Model.TargetVolume).Id,
              wratio = ViewData.Model.Wratio.ToString(),
              customRecalcString = ProductMixService.GetCustomRecalcValuesString(ViewData.Model.GaugesStructure)
          });
      string removeAction = Url.RouteUrl("Recalculate",
          new { 
              siteLanguage = ViewData.Model.SiteLanguage.Iso6391[0],
              identifierString = ColorService.GetIdentifierString(ViewData.Model.ActiveColor),
              formulaId = ViewData.Model.ActiveFormula.FormulaId,
              targetQuantity = FormulaService.ParseQuantityFromVolumeString(ViewData.Model.TargetVolume).ToString(),
              targetUnit = FormulaService.ParseUnitFromVolumeString(ViewData.Model.TargetVolume).Id,
          });
    %> 
    <snip/>
    <table width="100%">
        <tr>
            <td width="50%">
                <div>   
                    <a href="<%=Html.Encode(action)%>" alt="test">thisWorks</a>
                    <form action="<%=Html.Encode(action)%>" method="get">
                        <div>
                            <input type="submit" value="thisDoesnt" />
                        </div>
                    </form>
                </div>
            </td>
            <td width="50%">
                <div>                
                    <a href="<%=Html.Encode(removeAction)%>" alt="test">thisWorks</a>
                    <form action="<%=Html.Encode(removeAction)%>" method="get">
                        <div>                                        
                            <input type="submit" value="thisDoesnt" />
                        </div>
                    </form>
                </div>
            </td>
        </tr>
    </table>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="javaScriptPlaceHolder" runat="server">
    <script src="/Content/scripts/effects.core.min.js" type="text/javascript"></script>
    <script src="<%=PathHelper.JsUrl("productMix.js")%>" type="text/javascript"></script>
</asp:Content>

I tend to define the action urls at the start of the page so I can find it easely and it doesn't litter my page. Also, I know the table is blasphemy, but with the time I've wasted yesterday it will have to do for the time being. I'll have to pay the programmer's tax in a later cycle.

Best Answer

I just created sample application =>

controller:

 public class FooController : Controller
    {
        public ActionResult Bar
            (string fizz1, int fizz2, string fizz3, string fizz4, 
             string fizz5, int? fizz6)
        {
            var sb = new StringBuilder();

            sb.AppendLine(string.Format("{0} | {1} | {2} | {3} | {4} | {5}", 
                fizz1, fizz2, fizz3, fizz4, fizz5, fizz6.HasValue ? fizz6.Value.ToString():""));

            return Content(sb.ToString());
        }

    }

global.asax:

 public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            //routes.MapRoute(
            //    "Default",                                              // Route name
            //    "{controller}/{action}/{id}",                           // URL with parameters
            //    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            //);

            routes.MapRoute(
                    "FooBar",
                    "{siteLanguage}/bar/{fizz1}/{fizz2}/{fizz3}/{fizz4}",
                    new { controller = "Foo", action = "Bar", fizz3 = "", fizz4 = "" }
            );

        }

        protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
        }
    }

Results:

http://localhost:4038/en/bar/fizz1/2?fizz5=val&fizz6=1

returns

fizz1 | 2 | | | val | 1

Problem seems to be elsewhere. Are there any filters/model binders doing something?