0

I've got a legacy service that I need to emulate that uses Soap as the message format. Unfortunately, due to various circumstances, I'm stuck using asmx and .Net Framework (due to it's Soap handling capabilities)

My problem is that I now need to call a certain API from within the service, and having used NSWAG to auto generate the client api, I'm finding that when I try and call it, it's giving a 500 error. This isn't necessairly a problem, as I'm sort of expecting that at the moment.

The issue is that when it throws the auto generated ApiException message as part of the 500 processing, it's jumping to the 'Finally' section for the response and the client, and then just throws an object reference exception...somewhere.

There's very little detail at all in the Exception, with the only bit of interest (I think) being that it says "This exception was originally thrown at this call stack: System.Web.ThreadContext.AssociateWithCurrentThread(bool)"

I'm sort of lost on where to start with this one, but I'm hoping it's a common enough problem that there's a solution out there somewhere!

[Edit - updated to include code]

public System.Threading.Tasks.Task<SomeDto> RetrieveAsync(string someIdentifier, string includePermissibleActions)
        {
            return RetrieveAsync(someIdentifier, includePermissibleActions, System.Threading.CancellationToken.None);
        }

        
        public async System.Threading.Tasks.Task<SomeDto> RetrieveAsync(string someIdentifier, string includePermissibleActions, System.Threading.CancellationToken cancellationToken)
        {
            if (someIdentifier == null)
                throw new System.ArgumentNullException("someIdentifier");

            var urlBuilder_ = new System.Text.StringBuilder();
            urlBuilder_.Append(BaseUrl != null ? BaseUrl.TrimEnd('/') : "").Append("/api/v1/someName/{someIdentifier}?");
            urlBuilder_.Replace("{someIdentifier}", System.Uri.EscapeDataString(ConvertToString(someIdentifier, System.Globalization.CultureInfo.InvariantCulture)));
            if (includePermissibleActions != null)
            {
                urlBuilder_.Append(System.Uri.EscapeDataString("includePermissibleActions") + "=").Append(System.Uri.EscapeDataString(ConvertToString(includePermissibleActions, System.Globalization.CultureInfo.InvariantCulture))).Append("&");
            }
            urlBuilder_.Length--;

            var client_ = _httpClient;
            var disposeClient_ = false;
            try
            {
                using (var request_ = new System.Net.Http.HttpRequestMessage())
                {
                    request_.Method = new System.Net.Http.HttpMethod("GET");

                    PrepareRequest(client_, request_, urlBuilder_);

                    var url_ = urlBuilder_.ToString();
                    request_.RequestUri = new System.Uri(url_, System.UriKind.RelativeOrAbsolute);

                    PrepareRequest(client_, request_, url_);

                    var response_ = await client_.SendAsync(request_, System.Net.Http.HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
                    var disposeResponse_ = true;
                    try
                    {
                        var headers_ = System.Linq.Enumerable.ToDictionary(response_.Headers, h_ => h_.Key, h_ => h_.Value);
                        if (response_.Content != null && response_.Content.Headers != null)
                        {
                            foreach (var item_ in response_.Content.Headers)
                                headers_[item_.Key] = item_.Value;
                        }

                        ProcessResponse(client_, response_);

                        var status_ = (int)response_.StatusCode;
                        if (status_ == 200)
                        {
                            var objectResponse_ = await ReadObjectResponseAsync<SomeDto>(response_, headers_).ConfigureAwait(false);
                            if (objectResponse_.Object == null)
                            {
                                throw new ApiException("Response was null which was not expected.", status_, objectResponse_.Text, headers_, null);
                            }
                            return objectResponse_.Object;
                        }
                        else
                        if (status_ == 401)
                        {
                            string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
                            throw new ApiException("Unauthorized", status_, responseText_, headers_, null);
                        }
                        else
                        if (status_ == 403)
                        {
                            string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
                            throw new ApiException("Forbidden", status_, responseText_, headers_, null);
                        }
                        else
                        if (status_ == 404)
                        {
                            string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
                            throw new ApiException("NotFound", status_, responseText_, headers_, null);
                        }
                        else
                        if (status_ == 500)
                        {
                            string responseText_ = (response_.Content == null) ? string.Empty : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
                            throw new ApiException("InternalServerError", status_, responseText_, headers_, null);
                        }
                        else
                        {
                            var responseData_ = response_.Content == null ? null : await response_.Content.ReadAsStringAsync().ConfigureAwait(false);
                            throw new ApiException("The HTTP status code of the response was not expected (" + status_ + ").", status_, responseData_, headers_, null);
                        }
                    }
                    finally
                    {
                        if (disposeResponse_)
                            response_.Dispose();
                    }
                }
            }
            finally
            {
                if (disposeClient_)
                    client_.Dispose();
            }
        }
AmFearLiathMor
  • 183
  • 1
  • 11
  • can you show some of the code to point us where your exact problem is? – Stefan Aug 05 '21 at 15:18
  • 1
    Code now added - the issue I'm having is the 500 error above, it throws the exception, jumps to the 'finally' and then....falls apart! – AmFearLiathMor Aug 05 '21 at 15:42
  • Okay, so looking at this, the handling of the exception is left to the caller. If you `await` the task, you should be able to properly capture the exception details. Would that be sufficient? Or do you need something further? – Stefan Aug 05 '21 at 15:54
  • Unfortunately, it doesn't - there's something happening in between that means that it's not returning from the call to the second method from the first 'wrapper' (for want of a better phrase) method with the same name. I tried putting a catch in above, but it didn't get that far. It's something about the second RetrieveAsync above that's not returning. – AmFearLiathMor Aug 05 '21 at 16:20
  • It doesnt return because the exception is thrown. Can you show how and where you've put the catch, and how you're calling this function? Because, as far as I can see it should work. – Stefan Aug 06 '21 at 06:55
  • I'd initially put a try/ catch around the call to the larger method within the smaller one, but it didn't appear to be getting back to there. – AmFearLiathMor Aug 10 '21 at 10:45
  • I undestand, and thats why I would like to see how you did this. It's clear the exception is raised. Now it key to catch it. Since it's a Task, it's easy to step in the pitfall of not being able to catch it. As an example, see https://stackoverflow.com/questions/15667595/async-exception-not-caught – Stefan Aug 10 '21 at 13:14
  • Apologies for not getting back to you sooner - I think I've found the issue, and it's to do with the ancient set up that I'm using, combined with lack of experience on my part. To emulate the old service, I ideally need to have SOAP webmethods as Synchronous, but the generated API methods require Async - so it was really the age old 'calling async methods in an sync method' problem, and one of the sideffects of that was, I think, the process losing it's bearings! Basically, I needed to go through and add 'ConfigureAwait(false) to each await, and that seems to have cured it – AmFearLiathMor Aug 16 '21 at 15:39
  • Glad you found it and thank you for the follow up. – Stefan Aug 16 '21 at 20:56

0 Answers0