0

When writing a message to the Azure Service Bus (using Microsoft.Azure.ServiceBus standard library, not the .Net Framework version) it works fine. However, when switching networks to a network that blocks that traffic and running it again I would expect an error being raised by SendAsync yet no error is thrown, therefor the function considers the send successful even though it is not.

Am I missing some logic to make sure that errors do get raised and trapped, it seems to be inline with all the examples I have seen.

I have tried this possible solution ..

Trouble catching exception on Azure Service Bus SendAsync method

.ContinueWith(t => { Console.WriteLine(t.Status + "," + t.IsFaulted + "," + t.Exception.InnerException); }, TaskContinuationOptions.OnlyOnFaulted);

.. and at no point does ContinueWith get hit.

[HttpPost]
[Consumes("application/json")]
[Produces("application/json")]
public ActionResult<Boolean> Post(Contract<T> contract)
{
    Task.Run(() => SendMessage(contract)); 

    // Other stuff
}

private async Task<ActionResult<Boolean>> SendMessage(Contract<T> contract)
    {
        JObject json = JObject.FromObject(contract);
        Message message = new Message();
        message.MessageId = Guid.NewGuid().ToString();
        message.ContentType = ObjectType;
        message.PartitionKey = ObjectType;
        message.Body = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(contract));

        foreach (KeyValuePair<String, String> route in DataRouting)
        {
            JToken jToken = json.SelectToken(route.Value);
            if (jToken != null)
            {
                message.UserProperties[route.Key] = jToken.Value<String>();
            }
            else
            {
                String routeError = $"Could not find routing information in request for: {route.Key} in {route.Value}";
                Logger.LogError(routeError);
                return new UnprocessableEntityObjectResult(routeError);
            }
        }

        // Send the message
        try
        {
            await topicClient.SendAsync(message);
        }
        catch(Exception ex)
        {
            return new UnprocessableEntityObjectResult($"'Could not transmit message to service bus - {ex.Message}'");
        }

        return new OkObjectResult(true); 
    }

I expect that the error trap would be hit if the SendAsync fails to send the message. However it essentially fire and forgets, the message send is blocked by the firewall but is never reported to the caller by throwing an error.

Joe Walters
  • 641
  • 6
  • 7

1 Answers1

0

Ok, found the answer, but I will leave this out there in case anyone else does this to themselves. It was down to my general muppetry when putting the MVC Controller together. Set async on the Post action and configure the await on the send. Obvious really but I missed it.

    public virtual async Task<ActionResult<Boolean>> Post(Contract<T> contract){}

...

        // Send the message
        try
        {
            await topicClient.SendAsync(message).ConfigureAwait(false);
            return new OkObjectResult(true); // Success if we got here
        }
        catch(Exception ex)
        {
            return new UnprocessableEntityObjectResult($"'Could not transmit message to service bus - {ex.Message}'");
        }
Joe Walters
  • 641
  • 6
  • 7
  • Where you using ASP.NET Core? If yes, that would be strange, as ASP.NET Core doesn't require `.ConfigureAwait()` as there's no context switching. – Sean Feldman Mar 27 '19 at 21:24