skip to Main Content

I am using .NET nanoFramework with this sample as a base project to make a REST API that reads and serve my sensors data from ESP32.

using (WebServer server = new WebServer(80, HttpProtocol.Http, new Type[] { typeof(DHTController) }))
{
    Debug.WriteLine("Iniciando server...");
    var temp = server.Start();
    var nis = NetworkInterface.GetAllNetworkInterfaces();
    foreach (var ni in nis)
    {
        Debug.WriteLine("Seu endereço de IP é: " + ni.IPv4Address.ToString());
    }

    Thread.Sleep(Timeout.Infinite);
}

Everything works fine until i decide to use dependency injection solution for nanoCRL.
The dependency injection seems to work properly but i notice that the constructor Controller dont get called when a request from postman is done. The route responds as spected, but the constructor dont get called and the dependency is not injected as i expected.

private readonly IDHTService service;

public DHTController(IDHTService service) 
{
    this.service = service;
}

[Route("dht")]
[Method("GET")]
public void Get(WebServerEventArgs e) 
{
    try
    {
        var result = service.GetTemperatura();
        e.Context.Response.ContentType = "text/plain";
        WebServer.OutPutStream(e.Context.Response, result.ToString());
    }
    catch (Exception)
    {
        WebServer.OutputHttpCode(e.Context.Response, HttpStatusCode.BadRequest);
    }
}

When i make a call from postman, the constructor breakpoint is skiped by the code and the route breakpoint gets called. But without the dependency injected the route dont work properly too.

constructor breakpoint skiped

Can someone help me to understand what is happening in the code? If it is something expected, or a bug. And help me to use dependency injection with nanoFramework, if has another solution.

2

Answers


  1. Seems that you’re running into two separate issues.
    From your code above it’s not obvious what could be the root cause…
    Know that work it’s underway to offer an official DI library for nanoFramework.

    Until that happens you’re better raising an issue on the github of the DI library.

    Login or Signup to reply.
  2. I had the same issue. Fortunatly, I found the answer in the nanoframework WebServer sample called "WebServer.DI". (As you stated previously, the simple sample does not allow Dependency Injection because it does not create an instance of the controller)

    https://github.com/nanoframework/Samples/tree/main/samples/Webserver/WebServer.DI

    You first have to create a class that inherit from the WebServer class and use the IServiceProvider as follow:

        internal class WebServerDi : WebServer
        {
            private readonly IServiceProvider _serviceProvider;
    
            public WebServerDi(int port, HttpProtocol protocol, Type[] controllers, IServiceProvider serviceProvider) : base(port, protocol, controllers)
            {
                _serviceProvider = serviceProvider;
            }
    
            protected override void InvokeRoute(CallbackRoutes route, HttpListenerContext context)
            {
                route.Callback.Invoke(ActivatorUtilities.CreateInstance(_serviceProvider, route.Callback.DeclaringType), new object[] { new WebServerEventArgs(context) });
            }
        }
    

    Then, when creating your Web Server, create it using your new class instead of "WebServer":

            using (var webServer = new WebServerDi(80, HttpProtocol.Http, new Type[] { typeof(ControllerTest) }, serviceProvider))
            {
                webServer.Start();
                Thread.Sleep(Timeout.Infinite);
            }
    

    Now, the instance of the controller will be created using the service provider, allowing some dependency injection magic in your constructor, as we are used to when using the real .Net Framework:

    public class ControllerTest
    {
        private readonly ITextService _textService;
        private readonly ITextServiceSingleton _textServiceSingleton;
    
        public ControllerTest(ITextService textService, ITextServiceSingleton textServiceSingleton)
        {
            _textService = textService;
            _textServiceSingleton = textServiceSingleton;
        }
    
        [Route("test")]
        [Method("GET")]
        public void RoutePostTest(WebServerEventArgs e)
        {
            var content = $"Response from {nameof(ITextService)}: {_textService.GetText()}. Response from {nameof(ITextServiceSingleton)}: {_textServiceSingleton.GetText()}";
            e.Context.Response.ContentType = "text/plain";
            WebServer.OutPutStream(e.Context.Response, content);
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search