This is in reference to this page: https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection
The documentation does a good job of showing how to register your services, but how do you then use these services from within a function?
For example, lets say I registered ITimestampService
in startup as a singleton, and want to use it within a function. If I just declare the interface, the function run-time will not automatically pick this up. Does it need to be prefixed with an attribute?
[FunctionName(nameof(PingContainerHttpTrigger))]
public static IActionResult PingContainerHttpTrigger(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "ping")] HttpRequest req,
ITimestampService timestamps)
{
var now = timestamps.Now();
return new OkObjectResult(new { timestamp = now });
}
⚠Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.
After a bit of research I figured out that you no longer need to use static for function declarations so, you can use constructor inject just like you would with a Controller.
So here's the above example refactored to work:
public class HealthFunctions
{
private readonly ITimestampService _timestamps;
public HealthFunctions(ITimestampService timestamps)
{
_timestamps = timestamps;
}
[FunctionName(nameof(PingHttpTrigger))]
public IActionResult PingHttpTrigger(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "ping")] HttpRequest req)
{
var now = _timestamps.Now();
return new OkObjectResult(new { timestamp = now });
}
}
Either way, the documentation should explain this to the user. My 2 cents.
@Dave76 Thanks for the feedback! We have assigned this issue to the content author for review.
@Dave76 Hi I'm trying your sample above but apparently, I have an error during runtime
Here is my Interface declaration
namespace Microsoft.Azure.Functions.Samples.DependencyInjectionScopes.Services
{
public class TimeStamps : ITimeStamps
{
public DateTime Now()
{
return DateTime.Now;
}
}
public interface ITimeStamps
{
DateTime Now();
}
}
And this is the one I implemented the DI for TimeStamps
```
public class SampleFunction
{
private readonly ITimeStamps _timeStamps;
public SampleFunction(ITimeStamps timeStamps)
{
_timeStamps = timeStamps;
}
[FunctionName(nameof(PingHttpTrigger))]
public IActionResult PingHttpTrigger(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "ping")] HttpRequest req, ILogger log)
{
log.LogInformation("Welcome call");
var now = _timeStamps.Now();
return new OkObjectResult(new { timestamp = now });
}
}
```
Here is the error :
Executed 'PingHttpTrigger' (Failed, Id=4edee1ef-c12b-4855-b5df-63076a689192)
[5/20/2019 8:05:52 AM] Microsoft.Extensions.DependencyInjection.Abstractions: Unable to resolve service for type 'Microsoft.Azure.Functions.Samples.DependencyInjectionScopes.Services.ITimeStamps' while attempting to activate 'Microsoft.Azure.Functions.Samples.DependencyInjectionScopes.SampleFunction'.
Any idea?
Thanks
Did you add the startup class and register the service?
[assembly: FunctionsStartup(typeof(Startup))]
namespace Your.Name.Space
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddSingleton
}
}
}
On Mon, May 20, 2019 at 2:18 AM John Christopher Eniego <
[email protected]> wrote:
@Dave76 https://github.com/Dave76 Hi I'm trying to your sample but
apparently, I have an error during runtimeHere is my Interface declaration
namespace
Microsoft.Azure.Functions.Samples.DependencyInjectionScopes.Services
{
public class TimeStamps : ITimeStamps
{
public DateTime Now()
{
return DateTime.Now;
}
}public interface ITimeStamps
{
DateTime Now();
}}
And this is the one I implemented the DI for TimeStamps
public class SampleFunction
{
private readonly ITimeStamps _timeStamps;public SampleFunction(ITimeStamps timeStamps) { _timeStamps = timeStamps; } [FunctionName(nameof(PingHttpTrigger))] public IActionResult PingHttpTrigger( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "ping")] HttpRequest req, ILogger log) { log.LogInformation("Welcome call"); var now = _timeStamps.Now(); return new OkObjectResult(new { timestamp = now }); }
}
Here is the error :
Executed 'PingHttpTrigger' (Failed,
Id=8dd36883-b24c-4037-b5dc-7cf876ded4a7)
[5/20/2019 6:05:57 AM]
Microsoft.Extensions.DependencyInjection.Abstractions: Unable to resolve
service for type
'Microsoft.Azure.Functions.Samples.DependencyInjectionScopes.Services.ISampleService'
while attempting to activate
'Microsoft.Azure.Functions.Samples.DependencyInjectionScopes.SampleFunction'.Any idea ?
Thanks—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/MicrosoftDocs/azure-docs/issues/31278?email_source=notifications&email_token=AAEOS4SZD6RAETD2TLR4JYDPWI7DZA5CNFSM4HNDEK4KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODVXZPWA#issuecomment-493852632,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAEOS4V2R7JE7EYC7GXR3QLPWI7DZANCNFSM4HNDEK4A
.
Hi @Dave76
Thank you for your reply. I did add the configuration in the startup but it still doesn't work.
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddSingleton
}
The only thing that I can make it work is this :
I create an instance of a class instead which is not the ideal behavior when doing dependency injection
public class SampleFunction
{
private TimeStamps timeStamps = new TimeStamps();
public SampleFunction()
{
}
[FunctionName(nameof(PingHttpTrigger))]
public IActionResult PingHttpTrigger(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "ping")] HttpRequest req, ILogger log)
{
log.LogInformation("Welcome call");
var now = timeStamps.Now();
return new OkObjectResult(new { timestamp = now });
}
}
Hmm. That's strange. Works fine for me. Let me see if I can post my sample
to GitHub for you so you can get the whole solution.
Dave
On Mon, May 20, 2019 at 10:51 PM John Christopher Eniego <
[email protected]> wrote:
Hi @Dave76 https://github.com/Dave76
Thank you for your reply. I did add the configuration in the startup but
it still doesn't work.public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddSingleton();
}The only thing that I can make it work is this :
I create an instance of a class instead which is not the ideal behavior
when doing dependency injectionpublic class SampleFunction
{
private TimeStamps timeStamps = new TimeStamps();
public SampleFunction()
{[FunctionName(nameof(PingHttpTrigger))] public IActionResult PingHttpTrigger( [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "ping")] HttpRequest req, ILogger log) { log.LogInformation("Welcome call"); var now = timeStamps.Now(); return new OkObjectResult(new { timestamp = now }); }
}
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/MicrosoftDocs/azure-docs/issues/31278?email_source=notifications&email_token=AAEOS4URR57TD76YMCPOEBDPWNPTVA5CNFSM4HNDEK4KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODV2TDII#issuecomment-494219681,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAEOS4RSHP6KJL5NWQUIPCTPWNPTVANCNFSM4HNDEK4A
.
Sure thanks :)
+ @jeffhollan who drafted this dependency injection article.
cc. @craigshoemaker
hi guys, I just had the same issue today, @oracle000 try to upgrade Microsoft.NET.Sdk.Functions to latest version 1.0.28. @ggailey777 maybe it good idea to add version which start support this behavior?
Yes this was a requirement I didn’t realize when writing the docs. In addition to installing the extension documented you do need to use a later version of function SDK. @craigshoemaker can you track this?
@rjxby sure will try it. Thank you
serverless-seminar-master.zip
Hi,
I have attached a zip of my solution which shows DI working (injecting a
service from another project).
As others have chimed in, I think your missing piece was you need to be on
the latest function sdk: 1.0.28.
Dave
On Wed, May 22, 2019 at 11:48 AM John Christopher Eniego <
[email protected]> wrote:
@rjxby https://github.com/rjxby sure will try it. Thank you
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/MicrosoftDocs/azure-docs/issues/31278?email_source=notifications&email_token=AAEOS4VO7BR5Y3GZV7JYXM3PWVTMFA5CNFSM4HNDEK4KYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODV7PT3I#issuecomment-494860781,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAEOS4TIHQBYRNEQFZGOSOLPWVTMFANCNFSM4HNDEK4A
.
Hi @rjxby, @Dave76
My current version of .NET.Sdk.Function is 1.0.26 and updating it to version 1.0.28 works!
Thanks a lot for the effort guys :)
Also, thank you for including a zip file in your solution @Dave76, will check it later :)
Most helpful comment
After a bit of research I figured out that you no longer need to use static for function declarations so, you can use constructor inject just like you would with a Controller.
So here's the above example refactored to work:
Either way, the documentation should explain this to the user. My 2 cents.