An unexpected method call was detected in the ConfigureHowToFindSaga

I’m running NServiceBus 7.4.4 and NServiceBus.Persistence.Sql 6.1.1

When I have two messages mapped in ‘ConfigureHowToFindSaga’ I receive the following error:

Unable to determine Saga correlation property because an unexpected method call was detected in the ConfigureHowToFindSaga method.

So, this compiles:

protected override void ConfigureHowToFindSaga(SagaPropertyMapper<MySagaData> mapper)
        {
            mapper.MapSaga(saga => saga.MyId)
                .ToMessage<Message1>(msg => msg.MyId);
        }

This doesn’t:

protected override void ConfigureHowToFindSaga(SagaPropertyMapper<MySagaData> mapper)
        {
            mapper.MapSaga(saga => saga.MyId)
                .ToMessage<Message1>(msg => msg.MyId)
                .ToMessage<Message2>(msg => msg.MyId);
        }

What am I doing wrong?

Could this be a bug in InstructionAnalyzer?

In method CallUnexpectedMethods the following code is executed:

		var badCalls = interestingCalls
		.Where(item => !item.IsConfigureMapping && !item.IsToSaga)
		.Where(item => !(item.IsExpressionCall && item.ExpressionCallsAllowed.Value))
		.ToArray();

When changing this to the following code, everything works:

		var badCalls = interestingCalls
		.Where(item => !item.IsConfigureMapping && !item.IsToSaga)
		.Where(item => item.IsExpressionCall && item.ExpressionCallsAllowed == false)
		.ToArray();

Hey @Bjorn,

I was prepared to admit that SQL Persistence had a bug, because this is our only test for that style of saga mapping and it only includes one ToMessage call:

However, I copied and pasted your code and built the saga around it and it compiled just fine, and the script was generated with the correct correlation id MyId.

Is it possible you have an IL-level AOP tool like Fody or PostSharp that is adding additional IL to the method?

If not, I would love to see a minimal repro - is it possible to create one? If you could send the repro to support and flag my name, we could probably get a test case added for that exact scenario and then get to the bottom of it.

As a workaround, you can probably do the older style of saga mapping:

mapper.ConfigureMapping<Message1>(msg => msg.MyId).ToSaga(saga => saga.MyId);
mapper.ConfigureMapping<Message2>(msg => msg.MyId).ToSaga(saga => saga.MyId);

Hello David,

I will prepare a repo first thing tomorrow. I can already confirm that the old style exhibits the same problem. The moment I put in the second line, the compilation error is there.

I’m not using Fody or Postsharp or any such tool.

Hello David,

I have sent the minimal repo in a support ticket. It is case ID#00063090.

Thanks

The problem is right here…the mapped property from the message is implemented as a field instead of a property. What’s happening is that the field access is creating different-enough IL that the IL interpreter we wrote to determine the correlation ID thinks you’re calling off into a different method (which is incorrect) because if you were, you could be doing all sorts of things to the mapping from that external method that we wouldn’t be able to observe from the IL.

I’ve raised a bug for this, which includes details on the IL involved if you’re interested. Whether or not fields are OK in messages has more to do with your choice of serializer than anything else, but the SQL script generation certainly shouldn’t fail because of it.

This is probably pretty low priority though and likely won’t get handled until swept up with other low-priority bugs into a maintenance release. The obvious workaround is to not use fields and use a property instead.