watch-mode broken on apphost with azure functions
Is there an existing issue for this?
- [x] I have searched the existing issues
Describe the bug
When trying to run an apphost in watch-mode, which includes an azure function project, either via
aspire run, when"features": { "defaultWatchEnabled": true }- Start debugging in vs-code on the default aphost-project (aspire-extension installed)
dotnet watch
the project won't start - respectively crashes shortly after startup.
This breaks our watch-loop for our frontend, as we rely on multiple things to be working in the functions-project. Workarounds like specified in #9142 either do not apply, or stopped working after our upgrade fom
net9->net10aspire 9.5->aspire 13
Expected Behavior
Running the apphost in watch-mode, doesn't crash an included azure functions project.
Steps To Reproduce
- clone the aspire-samples (dca86f21fc3cf0c04f54ff38dc93a5558c852e33)
- run
cd/samples/AspireWithAzureFunctions - run
aspire update - run either of one:
cd ImageGallery.AppHost&dotnet watchaspire config set defaultWatchEnabled true&aspire run- vs-code:
Aspire: launch default apphost
Observe the functions project crashing
Exceptions (if any)
An unhandled exception of type 'System.InvalidOperationException' occurred in System.Private.CoreLib.dll: 'Configuration is missing the 'HostEndpoint' information. Please ensure an entry with the key 'Functions:Worker:HostEndpoint' is present in your configuration.'
at Microsoft.Extensions.DependencyInjection.GrpcServiceCollectionExtensions.GetFunctionsHostGrpcUri(IConfiguration configuration) in D:\a\_work\1\s\src\DotNetWorker.Grpc\GrpcServiceCollectionExtensions.cs:line 83
at Microsoft.Extensions.DependencyInjection.GrpcServiceCollectionExtensions.GrpcWorkerStartupOptionsSetup.Configure(GrpcWorkerStartupOptions options) in D:\a\_work\1\s\src\DotNetWorker.Grpc\GrpcServiceCollectionExtensions.cs:line 98
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
at Microsoft.Extensions.Options.UnnamedOptionsManager`1.get_Value()
at Microsoft.Azure.Functions.Worker.Grpc.GrpcWorkerClientFactory..ctor(GrpcHostChannel outputChannel, IOptions`1 startupOptions) in D:\a\_work\1\s\src\DotNetWorker.Grpc\GrpcWorkerClientFactory.cs:line 29
at System.Reflection.MethodBaseInvoker.InvokeWithFewArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in /_/src/runtime/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs:line 136
at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in /_/src/runtime/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs:line 157
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(ServiceIdentifier serviceIdentifier)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory) in /_/src/runtime/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs:line 1201
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier serviceIdentifier, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) in /_/src/runtime/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderServiceExtensions.cs:line 45
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) in /_/src/runtime/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderServiceExtensions.cs:line 65
at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>d__14.MoveNext()
at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>d__14.MoveNext()
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.<RunAsync>d__4.MoveNext() in /_/src/runtime/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/HostingAbstractionsHostExtensions.cs:line 67
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.<RunAsync>d__4.MoveNext() in /_/src/runtime/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/HostingAbstractionsHostExtensions.cs:line 79
at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host) in /_/src/runtime/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/HostingAbstractionsHostExtensions.cs:line 53
at Program.<Main>$(String[] args) in /Users/<user>/<path>/dotnet/aspire-samples/samples/AspireWithAzureFunctions/ImageGallery.Functions/AppHost.cs:line 13
```
### .NET Version info
# dotnet
.NET SDK:
Version: 10.0.100
Commit: b0f34d51fc
Workload version: 10.0.100-manifests.4c0ca8ba
MSBuild version: 18.0.2+b0f34d51f
Runtime Environment:
OS Name: Mac OS X
OS Version: 26.1
OS Platform: Darwin
RID: osx-arm64
Base Path: /Users/earloc/.dotnet/sdk/10.0.100/
.NET workloads installed:
There are no installed workloads to display.
Configured to use workload sets when installing new manifests.
No workload sets are installed. Run "dotnet workload restore" to install a workload set.
Host:
Version: 10.0.0
Architecture: arm64
Commit: b0f34d51fc
.NET SDKs installed:
9.0.307 [/Users/<user>/.dotnet/sdk]
10.0.100 [/Users/<user>/.dotnet/sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 9.0.11 [/Users/<user>/.dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 10.0.0 [/Users/<user>.dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 9.0.11 [/Users/<user>/.dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 10.0.0 [/Users/<user>/.dotnet/shared/Microsoft.NETCore.App]
Other architectures found:
None
# aspire --version
13.0.0+7512c2944094a58904b6c803aa824c4a4ce42e11
# func --help
Azure Functions Core Tools
Core Tools Version: 4.4.1+e4b8a4bdc8fd3b73143908be867f029865b74647 (64-bit)
Function Runtime Version: 4.1043.200.25453
### Anything else?
If it would be working, all the recently added enhancments are really promising. Keep up the good work!
For now, we'd be fine if functions would just Start normally, w/o watch-Mode enabled (despite this would be nice, though 🫠)
For now, to get rid of the most pressing road block, we're gonna run functions as a container, when we detect watch-mode.
This should at least re-enable a tighter dev-loop for working on frontend stuff.
Building this around AddDockerFile, so #969 might have helped here alot. (especially, since functions can be quite some beast to tame, when running as a container).
Can we have an update in this? Especially since this used to work in 9.5?
@earloc , did running funcions as container solve the issue for you? if so can you share how you do the AddDockerFile with function? We might meet similar issue and want to see if you find a workaround for it.
@chuanboz Would need some time to port it somewhere, maybe onto the official samples.
Will come back when I found the time.
@chuanboz I tried to give the core idea / basic gist of it over at my fork of the official aspire-samples. In my original workaround I used a full blown container-file, but this approach outlined here seems to work just as fine, at least for this simple sample.
thanks @earloc to share the detail samples, i learned from you how to build the container at runtime.