1
votes

I m developing a worker role on Azure. It is using OWIN to start a web app on the port 8080 in the goal of working with SignalR. This works perfectly.

Now, I need to create an HTTP listener to listen to incoming POST requests on port 27045.

I did the following to create and run the HttpListener object:

var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["listenerendpoint"];
var port = endpoint.IPEndpoint.Port.ToString();   

var listener = new HttpListener();

listener.Prefixes.Add("http://*:" + port + "/");
listener.Start();

Now, in the worker role's Run method:

IAsyncResult listenerResult = null;

while (true)
{
    if (listenerResult == null || listenerResult.IsCompleted)
            listenerResult = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);

    Thread.Sleep(1000);
}

And here is the ListenerCallback method:

public static void ListenerCallback(IAsyncResult result)
{
    var listener = (HttpListener)result.AsyncState;
    var context = listener.EndGetContext(result);

    var request = context.Request;

    var reader = new StreamReader(request.InputStream);

    var payload = reader.ReadToEnd();
}

I set up the endpoint for my listener in the ServiceDefinition.csdef file as following:

<WorkerRole name="myworkerrole" vmsize="Standard_D1_v2">
    <ConfigurationSettings>
      <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" />
    </ConfigurationSettings>
    <Endpoints>
      <InputEndpoint name="mainendpoint" protocol="http" port="8080" localPort="8080" />
      <InputEndpoint name="listenerendpoint" protocol="http" port="27045" localPort="27045" />
    </Endpoints>
    <Runtime executionContext="elevated" />
</WorkerRole>

Finally, here is the AJAX test client I developed:

$.ajax({
  method: "POST",
  url: "http://myworkerrolename.cloudapp.net:27045/",
  data: "testdata",
  crossDomain: true,
  dataType: "jsonp"
}).done(function(msg) {
    console.log('done');
    console.log(msg);
}).fail(function(msg) {
    console.log('fail');
    console.log(msg);
});

When I run the worker role locally using Azure Compute Emulator, everything works perfectly, I m able to send a post request to the endpoint. But when I deploy in the cloud, I m always getting the same AJAX error:

readyState: 4
status: 404
statusText: error

And if I open my browser and try to reach the url provided in the AJAX client configuration, it gives me the following error: HTTP Error 503. The service is unavailable.

I've set up try/catch at HttpListener creation but it never goes on the catch block. Everything seems to run well but the error is still here.

Thanks

2

2 Answers

0
votes

I would suggest to add the complete prefix to your listener

So you may keep :

 listener.Prefixes.Add("http://*:" + port + "/");

But add also :

 listener.Prefixes.Add("http://yourapp.cloudapp.net:" + port + "/");

Hope this helps Best regards Stéphane

0
votes

The way you set-up your prefix does not work for me, but you can leave the whole prefix up to the RoleEntrypoint to give it to you.

This will bind the httpListener to the instance private IP address.

This approach works for me for both emulation and running in Azure.

E.g.

var prefix = endpoint.IPEndpoint.ToString();
listener.Prefixes.Add("http://" + prefix + "/");

/Mikkel