question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

BindingDataProvider.FromType Fails to Resolve Shadowed Properties

See original GitHub issue

When a trigger binds to a type that shadows a base class property, the call to BindingTypeProvider.FromType fails with:

Error Message:

Microsoft.Azure.WebJobs.Host.Indexers.FunctionIndexingException : Error indexing method '[[ METHOD ]]'
----> System.InvalidOperationException : Multiple properties named '[[ PROPERTY ]]' found in type '[[ TYPE ]]'.

Stack Trace:

--InvalidOperationException
   at Microsoft.Azure.WebJobs.Host.Bindings.BindingDataProvider.FromType(Type type) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Bindings\BindingDataProvider.cs:line 103
   at Microsoft.Azure.WebJobs.Host.Triggers.CustomTriggerArgumentBinding`2..ctor(ITriggerBindingStrategy`2 bindingStrategy, IConverterManager converterManager, FuncAsyncConverter converter, Type userType) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Triggers\TriggerArgumentBinding\CustomTriggerArgumentBinding.cs:line 37
   at Microsoft.Azure.WebJobs.Host.Bindings.BindingFactoryHelpers.GetDirectTriggerBindingWorker[TMessage,TTriggerValue](ITriggerBindingStrategy`2 bindingStrategy, IConverterManager converterManager, Type userType) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Bindings\BindingFactoryHelpers.cs:line 42
   at Microsoft.Azure.WebJobs.Host.Bindings.BindingFactoryHelpers.GetDirectTriggerBinding[TMessage,TTriggerValue](Type exactType, ITriggerBindingStrategy`2 bindingStrategy, IConverterManager converterManager) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Bindings\BindingFactoryHelpers.cs:line 30
   at Microsoft.Azure.WebJobs.Host.Bindings.BindingFactoryHelpers.GetTriggerArgumentElement

When FromType processes properties of the target type returned by PropertyHelper.GetProperties(type), it adds them to a dictionary in the order that they’re returned, failing by design if there are any duplicate names (src):

// The properties on user-defined types are valid binding data.
IReadOnlyList<PropertyHelper> bindingDataProperties = PropertyHelper.GetProperties(type);
if (bindingDataProperties.Count == 0)
{
    return null;
}

Dictionary<string, Type> contract = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
foreach (PropertyHelper property in bindingDataProperties)
{
    if (contract.ContainsKey(property.Name))
    {
        throw new InvalidOperationException(
            string.Format(CultureInfo.InvariantCulture,
            "Multiple properties named '{0}' found in type '{1}'.", property.Name, type.Name));
        }
        contract.Add(property.Name, property.Property.PropertyType);
    }
}

This disallows binding to types with properties that shadow a base class member.

Repro steps

  • Create a function that references the Microsoft.Azure.WebJobs.Extensions.EventHubs v5.x+ and the latest nightly build of Azure.Messaging.EventHubs from the Azure SDK development package feed.

  • Create a function with an Event Hubs trigger, such as:

public static void ProcessMultipleEvents([EventHubTrigger(TestHubName, Connection = TestHubName)] EventData[] events)
{
    // Code
}
  • Observe the exception due to the new hierarchy for EventData where property shadowing is used:

EventData (src)

public class EventData : MessageWithMetadata
{
    public new string ContentType { get;  set; }

    [EditorBrowsable(EditorBrowsableState.Never)]
    protected override ContentType? ContentTypeCore
    {
        get => new ContentType(ContentType);
        set => ContentType = value.ToString();
    }
}

MessageWithMetadata (src)

public class MessageWithMetadata
{
    public virtual ContentType? ContentType
    {
        get => ContentTypeCore;
        set => ContentTypeCore = value;
    }

    [EditorBrowsable(EditorBrowsableState.Never)]
    protected virtual ContentType? ContentTypeCore { get; set; }
}

Expected behavior

The binding succeeds by selecting the property declared on the type being bound rather than giving equal consideration to properties deeper in the hierarchy. In this case, the ContentType property from EventData should have been selected and the property from the base class ignored.

Actual behavior

Error Message

Microsoft.Azure.WebJobs.Host.Indexers.FunctionIndexingException : Error indexing method 'EventHubTestInitialOffsetFromEnqueuedTimeJobs.ProcessMultipleEvents'
----> System.InvalidOperationException : Multiple properties named 'ContentType' found in type 'EventData'.

Stack Trace

at Microsoft.Azure.WebJobs.Host.RecoverableException.TryRecover(ILogger logger) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Exceptions\RecoverableException.cs:line 81
   at Microsoft.Azure.WebJobs.Host.Indexers.FunctionIndexer.IndexTypeAsync(Type type, IFunctionIndexCollector index, CancellationToken cancellationToken) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Indexers\FunctionIndexer.cs:line 94
   at Microsoft.Azure.WebJobs.Host.Indexers.FunctionIndexProvider.CreateAsync(CancellationToken cancellationToken) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Indexers\FunctionIndexProvider.cs:line 97
   at Microsoft.Azure.WebJobs.Host.Indexers.FunctionIndexProvider.GetAsync(CancellationToken cancellationToken) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Indexers\FunctionIndexProvider.cs:line 69
   at Microsoft.Azure.WebJobs.Host.Executors.JobHostContextFactory.Create(JobHost host, CancellationToken shutdownToken, CancellationToken cancellationToken) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\JobHostContextFactory.cs:line 119
   at Microsoft.Azure.WebJobs.JobHost.InitializeHostAsync(CancellationToken cancellationToken, TaskCompletionSource`1 initializationTask) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\JobHost.cs:line 347
   at Microsoft.Azure.WebJobs.JobHost.StartAsyncCore(CancellationToken cancellationToken) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\JobHost.cs:line 95
   at Microsoft.Azure.WebJobs.Host.EndToEndTests.WebJobsEventHubTestBase.BuildHost[T](Action`1 configurationDelegate, Action`1 preStartCallback) in /Users/runner/work/1/s/sdk/eventhub/Microsoft.Azure.WebJobs.Extensions.EventHubs/tests/WebJobsEventHubTestBase.cs:line 92
   at Microsoft.Azure.WebJobs.Host.EndToEndTests.EventHubEndToEndTests.EventHub_InitialOffsetFromEnqueuedTime() in /Users/runner/work/1/s/sdk/eventhub/Microsoft.Azure.WebJobs.Extensions.EventHubs/tests/EventHubEndToEndTests.cs:line 411
   at Microsoft.Azure.WebJobs.Host.EndToEndTests.EventHubEndToEndTests.EventHub_InitialOffsetFromEnqueuedTime() in /Users/runner/work/1/s/sdk/eventhub/Microsoft.Azure.WebJobs.Extensions.EventHubs/tests/EventHubEndToEndTests.cs:line 430
   at Microsoft.Azure.WebJobs.Host.EndToEndTests.EventHubEndToEndTests.EventHub_InitialOffsetFromEnqueuedTime() in /Users/runner/work/1/s/sdk/eventhub/Microsoft.Azure.WebJobs.Extensions.EventHubs/tests/EventHubEndToEndTests.cs:line 430
   at NUnit.Framework.Internal.TaskAwaitAdapter.GenericAdapter`1.BlockUntilCompleted()
   at NUnit.Framework.Internal.MessagePumpStrategy.NoMessagePumpStrategy.WaitForCompletion(AwaitAdapter awaiter)
   at NUnit.Framework.Internal.AsyncToSyncAdapter.Await(Func`1 invoke)
   at NUnit.Framework.Internal.Commands.TestMethodCommand.RunTestMethod(TestExecutionContext context)
   at NUnit.Framework.Internal.Commands.TestMethodCommand.Execute(TestExecutionContext context)
   at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.<>c__DisplayClass1_0.<Execute>b__0()
   at NUnit.Framework.Internal.Commands.BeforeAndAfterTestCommand.RunTestMethodInThreadAbortSafeZone(TestExecutionContext context, Action action)
--InvalidOperationException
   at Microsoft.Azure.WebJobs.Host.Bindings.BindingDataProvider.FromType(Type type) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Bindings\BindingDataProvider.cs:line 103
   at Microsoft.Azure.WebJobs.Host.Triggers.CustomTriggerArgumentBinding`2..ctor(ITriggerBindingStrategy`2 bindingStrategy, IConverterManager converterManager, FuncAsyncConverter converter, Type userType) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Triggers\TriggerArgumentBinding\CustomTriggerArgumentBinding.cs:line 37
   at Microsoft.Azure.WebJobs.Host.Bindings.BindingFactoryHelpers.GetDirectTriggerBindingWorker[TMessage,TTriggerValue](ITriggerBi

Proposed fix

Update BindingDataProvider.FromType on L99 to consider the type declaring the property. If a property is declared on the type parameter directly, remove other members discovered lower in the hierarchy. Throw only when there is a naming conflict and the property does not exist directly on type.

Related information

This behavior can be observed running tests for the Microsoft.Azure.WebJobs.Extensions.EventHubs package from the Azure SDK for .NET repository.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:13 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
mathewccommented, May 12, 2022

The new tools version is in testing now and will hopefully be released by mid next week. You’ll then be able to update just the tools - no VS update needed.

0reactions
ThomasVandenboncommented, Jun 14, 2022

@mathewc I had used npm to update my version as described here, which had no effect.

I’ve now used the Windows installer (MSI) (from the link you provided) and this does work.

Thank you! 👍

Read more comments on GitHub >

github_iconTop Results From Across the Web

no-shadow - ESLint - Pluggable JavaScript Linter
A pluggable and configurable linter tool for identifying and reporting on patterns in JavaScript. Maintain your code quality with ease.
Read more >
tslint error Shadowed name: 'Observable' - angular
The shadowed name error usually happens when you are using a variable from an "outside" scope, in an inside scope.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found