0

I am trying to convert a route from an old controller based api to a new dotnet7 api, however for some reason the temporary endpoint is not being hold. The basic idea is to create a temporary endpoint inside the main endpoint, and if no one calls this endpoint, then it breaks the function. This has been so far experimental but we would like to see if we could put this to work.

Can someone help me converting this code?

old code:

public class EndpointController : ControllerBase
{
    private bool endpointCalled = false;
    private HttpListener listener;

    [HttpGet]
    public IActionResult Endpoint1()
    {
        listener = new HttpListener();
        listener.Prefixes.Add("http://localhost:7195/");
        listener.Start();

        // Create a temporary POST endpoint
        listener.BeginGetContext(new AsyncCallback(Endpoint2), listener);

        // Close the endpoint after 20 seconds if it has not been called
        var timer = new Timer(20000);
        timer.Elapsed += CloseEndpoint;
        timer.Start();

        return Results.Ok(new { message = "Endpoint2 created" });
    }

    private void Endpoint2(IAsyncResult result)
    {
        var context = listener.EndGetContext(result);
        var request = context.Request;
        var response = context.Response;

        string responseString = "<HTML><BODY> Hello from Endpoint2!</BODY></HTML>";
        byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
        response.ContentLength64 = buffer.Length;
        System.IO.Stream output = response.OutputStream;
        output.Write(buffer, 0, buffer.Length);
        output.Close();

        endpointCalled = true;
    }

    private void CloseEndpoint(object sender, ElapsedEventArgs e)
    {
        if (!endpointCalled)
        {
            listener.Stop();
        }
    }
}

new code:

app.MapPost("/supplier/listen2", () =>
{
    bool endpointCalled = false;
    HttpListener listener = new HttpListener();

    listener.Prefixes.Add("http://localhost:7195/testi2/");
    listener.Start();

    listener.BeginGetContext(new AsyncCallback(Endpoint2), listener);
    var timer = new System.Timers.Timer(20000);
    timer.Elapsed += CloseEndpoint;
    timer.Start();

    void Endpoint2(IAsyncResult result)
    {
        var listener = (HttpListener)result.AsyncState;
        var context = listener.EndGetContext(result);
        var request = context.Request;
        var response = context.Response;

        string responseString = "<HTML><BODY> Hello from Endpoint2!</BODY></HTML>";
        byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
        response.ContentLength64 = buffer.Length;
        System.IO.Stream output = response.OutputStream;
        output.Write(buffer, 0, buffer.Length);
        output.Close();

        endpointCalled = true;
    }
    
    void CloseEndpoint(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (!endpointCalled)
        {
            listener.Stop();
        }
    }


    return Results.Ok(new { message = "Endpoint2 created" });

    // return Results.Ok(new { token = "-1" });
});

UPDATE:

Ok, there was an error before because I wrote the wrong port. Now I get an error because the listener is calling the already open door:

System.Net.HttpListenerException (48): Address already in use

Any tips to solve this?

thelittlemaster
  • 157
  • 1
  • 8
  • 1
    _"however for some reason the temporary endpoint is not being hold"_ - can you please elaborate? – Guru Stron Dec 29 '22 at 19:22
  • Hi Guru, yes, basically this should keep the nested endpoint open for 20 sec, and only resolve if the same got called, but it is not doing that. – thelittlemaster Dec 29 '22 at 19:43
  • TBH worked fine for me (though I've changed `MapPost` to `MapGet`). – Guru Stron Dec 29 '22 at 19:47
  • Ok. I had an error on the code above. The port was different, but I need it on the same port. When I change that I get an error. Will update the post. – thelittlemaster Dec 29 '22 at 19:53
  • The original code has the same port specified for both cases (`7195`). – Guru Stron Dec 29 '22 at 19:54
  • Check what is using this port and kill it. Have you checked if the new app is not running on the same port? – Guru Stron Dec 29 '22 at 20:03
  • I wanted it to run on the same port, because basically the idea was to solve the problem of here: https://stackoverflow.com/questions/74944358/net7-asp-net-state-listening-for-function?noredirect=1#comment132254311_74944358 And I don't want to listen to other libraries. – thelittlemaster Dec 29 '22 at 20:21
  • I'm not following. What should run on the same port? The "main" solution and temporary listener? – Guru Stron Dec 29 '22 at 20:25
  • 1
    Also not sure why can't you just track the 20 seconds on token in the service which created it. Why do you need to standalone listener for it? Sounds like a huge overkill for pretty trivial task (though maybe I'm not getting something). – Guru Stron Dec 29 '22 at 20:26
  • Agree with @GuruStron, this looks entirely too complex to accomplish what you want to do. If you want a temporary endpoint, just expose the endpoint and then set a bool after the time is up to "disable" it. You can do more advanced things like remove the endpoint but that requires a little more work. – davidfowl Jan 05 '23 at 08:58

0 Answers0