System.MissingMethodException after adding an optional parameter

sandeep picture sandeep · Mar 27, 2012 · Viewed 8.5k times · Source

I am getting error of System.MissingMethodException after I have an optional parameter in one component and the other component which call it was not build as it call it with old number of parameters.

Only component in which parameter is added was build an deployed as patch. The calling component is old as there is no change in it.

When the calling component run it gives error :

Exception Information

Exception Type: System.MissingMethodException Message: Method not found: 'LabelURLs IPSD.BnB.Transaction.Postage.GetLabelURLs(System.String)'. Data: System.Collections.ListDictionaryInternal TargetSite: Void GenerateScanForm(Int32, Int32) HelpLink: NULL Source: BnBDispenseQueueProcess

As far as i know it should not raise an error as new parameter is optional. One more thing calling component(EXE) run as windows service.

we found an very wired workaround to make it run. By Removing the changed component once and run calling component which will say DLL not found. The place the same DLL again and calling component works fine:).

I think i am missing some internals of .net.

Let me know if more info needed.

Answer

Jon Skeet picture Jon Skeet · Mar 27, 2012

Only component in which parameter is added was build an deployed as patch. The calling component is old as there is no change in it.

There should be a change in it, because the old code calls a method which no longer exists!

As far as i know it should not raise an error as new parameter is optional.

That's not an execution-time decision - it's a compile-time decision. If you have a method like this:

void Foo(int x, int y = 5)

and you call it like this:

Foo(10);

then the compiler effectively converts that into a call of:

Foo(10, 5);

The call has the full argument list in the binary. If you want to go from the single-parameter version to the multi-parameter version in a way which doesn't affect binary compatibility, you'd have to add an overload instead, e.g.

void Foo(int x)
{
    Foo(x, 5);
}

void Foo(int x, int y)
{
    ...
}

Alternatively, you could rebuild the calling code and redeploy that as well.

I'm deeply suspicious of your workaround. Are you sure you when you put the DLL back in place you replaced it with the new version (with the optional parameter) rather than the old version?