SOAP Service call breaking ignores try catch - c#

I've got a dll that relies on a SOAP call to a web service, and I was provided with the WSDL file from the vendor, and after some testing, I've got code that will successfully call the service and get the response with no issue. However, when the vendor moved the service to a new server, my code starting failing.
Specifically, I get a NullRefernceException that, even though it is square in a try/catch block, ignores all of that and crashes anyway.
my call looks like this:
new ChannelFactory<GRChannel>(binding, address).Using(async(factory) =>
{
factory.Credentials.UserName.UserName = "TestUser";
factory.Credentials.UserName.Password = "1234";
var proxy = factory.CreateChannel();
proxy.Open();
var context = new OperationContext((IClientChannel)proxy);
var prevOpContext = OperationContext.Current;
OperationContext.Current = context;
try
{
var results = await proxy.ZBAPI_GOODSMVT_CREATEAsync(payload); //<-- Null happens here
System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(ZBAPI_GOODSMVT_CREATEResponse));
using (StringWriter text = new StringWriter())
{
serializer.Serialize(text, results.ZBAPI_GOODSMVT_CREATEResponse);
Message = text.ToString();
}
}
catch
{
//Nothing here matters, we never make it to this point
}
});
the Stack Trace is this at the time of failure:
at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass1_0.<CreateGenericTask>b__0(IAsyncResult asyncResult)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at RFCDLL.RFC.<>c__DisplayClass5_0.<<RunRequest>b__0>d.MoveNext() in C:\Users\User01\source\repos\RFCDLL\RFCDLL\RFC.cs:line 46
obviously, having a null failure is fine, and expected when the service isn't running, I just want to make sure the error handling works, and I can not have the whole app crash when that happens.

Related

Get LDAP TokenGroups using System.DirectoryServices.Protocols in .NET5

I'm porting some code from System.DirectoryServices to System.DirectoryServices.Protocols due to the need to run on linux.
The majority of the code is fine but this little piece that retrieves tokenGroups isn't coming across.
The original code reads:
using (var ldapObject = new DirectoryEntry(objectPath, username, password, AuthenticationTypes.Secure))
{
ldapObject.Options.Referral = ReferralChasingOption.All;
ldapObject.RefreshCache(new string[] { "tokenGroups" });
foreach (byte[] sid in ldapObject.Properties["tokenGroups"])
{
// Won't run on linux
var groupSID = new System.Security.Principal.SecurityIdentifier(sid, 0).ToString();
try
{
var group = this.GetSecurityGroupBySID(groupSID);
}
catch (Exception ex)
{
log.Warn($"Failed to get group with SID {groupSID}", ex);
}
}
}
Where objectPath is of the form $"LDAP://{domainName}/{distinguishedName}"
My attempt looks like this:
public void GetExpandedGroups(string objectMail, LdapConnection ldapConnection)
{
var usersPath = "OU=active,OU=users,DC=path,DC=etc"; //Not real values
var filter = $"(&(objectClass = user)(!userAccountControl:1.2.840.113556.1.4.803:= 2)(mail={objectMail}))";
var request = new SearchRequest(usersPath, filter, SearchScope.Subtree, new string[] { "tokenGroups" });
request.Controls.Add(new SecurityDescriptorFlagControl(SecurityMasks.Dacl | SecurityMasks.Group | SecurityMasks.Owner));
var ldapObject = (SearchResponse)ldapConnection.SendRequest(request); // Error thrown here
foreach (byte[] sid in ldapObject.Entries[0].Attributes["tokenGroups"])
{
// Do stuff...
}
}
Whenever this runs I get an error, thrown. The stack trace and error response are below:
at System.DirectoryServices.Protocols.LdapConnection.<ConstructResponseAsync>d__57.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Threading.Tasks.ValueTask`1.get_Result()
at System.Runtime.CompilerServices.ValueTaskAwaiter`1.GetResult()
at System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request, TimeSpan requestTimeout)
at System.DirectoryServices.Protocols.LdapConnection.SendRequest(DirectoryRequest request)
at LDAPTesting.Connectors.Protocols.GetExpandedGroups(String objectMail, LdapConnection ldapConnection) in C:\code\LDAPTesting\LDAPTesting\Connectors\Protocols.cs:line 62
at LDAPTesting.Connectors.Protocols.GetGroups() in C:\code\LDAPTesting\LDAPTesting\Connectors\Protocols.cs:line 103
at LDAPTesting.Program.Main(String[] args) in C:\code\LDAPTesting\LDAPTesting\Program.cs:line 17
00002120: SvcErr: DSID-031404CC, problem 5012 (DIR_ERROR), data 0
My thoughts are that I'm querying the wrong path but it looks to match the path that the original code requests on so I'm not sure what else I'm missing.
For anyone that comes along this, the solution is incredibly simple.
The SearchRequest object needs to be of the scope Base. Really obvious when reading what the error message. So the line:
var request = new SearchRequest(usersPath, filter, SearchScope.Subtree, new string[] { "tokenGroups" });
Should instead read:
var request = new SearchRequest(usersPath, filter, SearchScope.Base, new string[] { "tokenGroups" });
I had a feeling that there would be an obvious and simple answer due to overlooking something and indeed there was!
I think I found the solution - it's just the first value that is not correct - if that is ignored, everything works fine!

azure management client doesn't return any resource group

I am new to azure. I am trying to create ResourceGroup then trying to deploy a VM. But I am getting exception during accessing resourcegroups.
I am following MSDN example given here: https://learn.microsoft.com/en-us/azure/virtual-machines/windows/csharp-template
I tried different subscription but no luck. Couldn't find any pointers online for this issue or I might have missed. If you could help me please let me know.
Thanks.
//AppId,Key,TenetId are correct
var credentials = SdkContext.AzureCredentialsFactory
.FromServicePrincipal(ApplicationID, Key, TenetID,
new AzureEnvironment()
{
AuthenticationEndpoint = #"https://login.windows.net/",
ManagementEndpoint = #"https://management.core.windows.net/",
ResourceManagerEndpoint = #"https://management.azure.com/",
GraphEndpoint = #"https://graph.windows.net/",
});
var azure = Azure
.Configure()
.WithLogLevel(HttpLoggingDelegatingHandler.Level.Basic)
.Authenticate(credentials)
.WithSubscription(AzureProperties.SubscriptionId);
var groupName = "MyresourceGroup1";
var location = Region.USWest;
//Exception comes at here.
var resourceGroup = azure.ResourceGroups.Define(groupName)
.WithRegion(location)
.Create();
//Exception details.
System.ArgumentNullException
HResult=0x80004003
Message=Value cannot be null.
Parameter name: value
Source=mscorlib
StackTrace:
at System.String.EndsWith(String value, StringComparison comparisonType)
at Microsoft.Azure.Management.ResourceManager.Fluent.Authentication.AzureCredentials.<ProcessHttpRequestAsync>d__24.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Microsoft.Azure.Management.ResourceManager.Fluent.ResourceGroupsOperations.<CreateOrUpdateWithHttpMessagesAsync>d__6.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Management.ResourceManager.Fluent.ResourceGroupImpl.<CreateResourceAsync>d__26.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Management.ResourceManager.Fluent.Core.ResourceActions.Creatable`4.<Microsoft-Azure-Management-ResourceManager-Fluent-Core-ResourceActions-IResourceCreator<IResourceT>-CreateResourceAsync>d__15.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Management.ResourceManager.Fluent.Core.DAG.CreatorTaskItem`1.<ExecuteAsync>d__6.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Management.ResourceManager.Fluent.Core.DAG.TaskGroupBase`1.<ExecuteNodeTaskAsync>d__14.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Management.ResourceManager.Fluent.Core.Extensions.Synchronize[TResult](Func`1 function)
at Microsoft.Azure.Management.ResourceManager.Fluent.Core.ResourceActions.Creatable`4.Create()
at pvt_CreateVM.AzureVMManager.CreateVM()
at pvt_CreateVM.Program.Main(String[] args)
I think code is currently failing because you haven't set any value for KeyVaultSuffix property for AzureEnvrionment that you have initialized.
It's a guess looking at the error info you have shared but I say this after looking at the relevant source code for Azure Management Libraries for .NET
(on a side note it's awesome that anyone can do that.. here is a link)
public async override Task ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var adSettings = new ActiveDirectoryServiceSettings
{
AuthenticationEndpoint = new Uri(Environment.AuthenticationEndpoint),
TokenAudience = new Uri(Environment.ManagementEndpoint),
ValidateAuthority = true
};
string url = request.RequestUri.ToString();
if (url.StartsWith(Environment.GraphEndpoint, StringComparison.OrdinalIgnoreCase))
{
adSettings.TokenAudience = new Uri(Environment.GraphEndpoint);
}
string host = request.RequestUri.Host;
// I guess this is where your code is failing currently.
if (host.EndsWith(Environment.KeyVaultSuffix, StringComparison.OrdinalIgnoreCase))
{
How to fix
Unless there is a good reason, I would not initialize AzureEnvironment object and instead use the values already available, as that would make sure all required properties have correct values.
Example: AzureEnvironment.AzureGlobalCloud. Look here for all possible values
Change this code where you initialize AzureEnvironment
var credentials = SdkContext.AzureCredentialsFactory
.FromServicePrincipal(ApplicationID, Key, TenetID,
new AzureEnvironment()
{
AuthenticationEndpoint = #"https://login.windows.net/",
ManagementEndpoint = #"https://management.core.windows.net/",
ResourceManagerEndpoint = #"https://management.azure.com/",
GraphEndpoint = #"https://graph.windows.net/",
});
To this code
var credentials = SdkContext.AzureCredentialsFactory
.FromServicePrincipal(clientId,
clientSecret,
tenantId,
AzureEnvironment.AzureGlobalCloud);
In case you have some reason that none of the available environment values are good enough, then make sure you initialize all required properties for AzureEnvironment

Azure Service Bus: AMQP object is closing. Operation 'attach' cannot be performed

I'm using Azure Service Bus Topics with the AMQP protocol in the West Europe datacenter.
This is a schematic way of how the solution implented works:
private Microsoft.Azure.ServiceBus.SubscriptionClient CreateClient() {
string serviceBusConnectionString;
strin serviceBusTopicName;
string subscriptionName;
var subscriptionClient = new Microsoft.Azure.ServiceBus.SubscriptionClient(serviceBusConnectionString, serviceBusTopicName, subscriptionName) {
PrefetchCount = 0
};
return subscriptionClient;
}
public async Task<ISubscriptionClient> CreateSubscriptionClientAsync() {
//Some logic on the subscriptionClient, caching, creating a new one if it doesn't exists, etc.
return CreateClient()
}
private async Task CallbackAsync(Message msg, CancellationToken cancellationToken) {
//Do stuff with the Message
//when you're done Completethe message
}
public async Task<string> OpenAsync(CancellationToken cancellationToken) {
subscriptionClient = await CreateSubscriptionClientAsync().ConfigureAwait(false);
var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandlerAsync) {
AutoComplete = false,
MaxAutoRenewDuration = TimeSpan.FromHours(8)
};
subscriptionClient.RegisterMessageHandler(CallbackAsync, messageHandlerOptions);
return string.Empty;
}
But last night I had couple of thousand exception like this one:
Exception: "System.InvalidOperationException: The AMQP object g2b-sessionXXXXXXXX is closing. Operation 'attach' cannot be performed.
at Microsoft.Azure.ServiceBus.Core.MessageReceiver.<OnReceiveAsync>d__86.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.ServiceBus.Core.MessageReceiver.<>c__DisplayClass64_0.<<ReceiveAsync>b__0>d.MoveNext()
I'm using the Microsoft.Azure.ServiceBus v3.1.0.0,
On line I didn't find anything useful about this "Operation 'attach' cannot be performed".
On the message bus exception list page I didn't find any information about this specific problem. And in the status history site there is no reference about any outage involving Service Bus.
Did anyone experience this problem before?
What is causing the exception?
Do I need to implement any retry logic? How?
Any help is apreciated, thanks.

HttpClient SendAsync Cannot access a disposed object ResponseHeadersRead

I am looking into an issue with some legacy code which is relaying a Http Request to another URL. It is an API Controller that reads the request and forwards it to another address asynchronously.
Very rarely, it throws a "Cannot access a disposed object" exception - full stack trace shown later in this question. It seems to be on the line where the HttpClient is calling the SendAsync method. I think it might be the ResponseHeadersRead option - I suspect it is happening when a large packet is being sent and it gets closed because it has just read the header and quit. Just thought I'd sanity check this with you all, for your thoughts. I'll change the option to be ResponseContentsRead option and see how that goes (but it can take a long time for the error to surface).
Here is the code:
using (var client = new HttpClient())
{
var request = BuildRelayHttpRequest(Request);
await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
}
private static HttpRequestMessage BuildRelayHttpRequest(HttpRequestMessage incomingRequest)
{
var forwardToUrl = new Uri(ConfigurationManager.AppSettings["ForwardFeedURL"]);
var relayRequest = new HttpRequestMessage(incomingRequest.Method, forwardToUrl);
if (incomingRequest.Method != HttpMethod.Get && incomingRequest.Content != null)
{
relayRequest.Content = incomingRequest.Content;
}
//Copies contents
relayRequest.Content = incomingRequest.Content;
return relayRequest;
}
And here is the exception:
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Web.Http.WebHost.HttpControllerHandler+LazyStreamContent'.
at System.Net.Http.HttpContent.CheckDisposed()
at System.Net.Http.HttpContent.CopyToAsync(Stream stream, TransportContext context)
at System.Net.Http.HttpClientHandler.GetRequestStreamCallback(IAsyncResult ar)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at CHO.Web.Services.ETrains.Controllers.ETrainsApiController.<CopyandForwardFeedAsyn>d__18.MoveNext() in \Controllers\MyAPIController.cs:line 289
Note, line 289 is the "await client.SendAsync" line of code
Odds are there is an error code being set by the server.
Follow your code with a response.EnsureSuccessStatusCode(); that is wrapped in a Try Catch block:
try
{
var request = BuildRelayHttpRequest(Request);
await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
response.EnsureSuccessStatusCode();
// Handle success
}
catch (HttpRequestException)
{
// Handle failure
}

MSTest tests succeed if run in isolation, fail if run with other tests

I've bumped into this really odd situation where, if I run all my tests together, certain tests will fail (about 7 of them). But if I run just the tests inside the class (they are all part of the same class), then they pass. The test project is a Windows Phone 8.1 MSTest, and I tried running it both with Resharper test runner and MSTest test runner and they both show the same problem. Here's my TestInitialize code:
[TestInitialize]
public void Init()
{
ResolveDependencies();
var adsApiService = ServiceLocator
.Current
.GetInstance<IApiService<ListAdsReply, PublicAdsEndPoint>>();
var navigationService = new NavigationServiceMock();
var mainPageTrackingService = ServiceLocator
.Current
.GetInstance<IMainPageTrackingService>();
var adInsertionTrackingService = ServiceLocator
.Current
.GetInstance<IAdInsertionTrackingService>();
var connectionService = ServiceLocator
.Current
.GetInstance<IConnectionService>();
_windowsApiService = new WindowsApiServiceMock();
var contactAboutTrackingService = ServiceLocator
.Current
.GetInstance<IContactAboutTrackingService>();
var filtersTrackingService = ServiceLocator
.Current
.GetInstance<IFiltersTrackingService>();
var filtersService = ServiceLocator
.Current
.GetInstance<IFiltersService>();
var messageHelperMock = new MessageHelperMock();
_mainPageViewModel = new MainPageViewModel(adsApiService, navigationService, mainPageTrackingService, adInsertionTrackingService, connectionService, _windowsApiService, contactAboutTrackingService,filtersTrackingService, filtersService, messageHelperMock);
}
The ResolveDependencies method doesn't do anything special besides registering dependencies in a Unity container, registering it with ServiceLocator.SetLocatorProvider and doing some Automapper configurations. No async code there.
[TestMethod]
public async Task GivenParameterIsProvidedThenFetchDataShouldReturnValidData()
{
_mainPageViewModel
.SearchParams
.Add(new KeyValuePair<string, string>("lim", "5"));
var searchParams = _mainPageViewModel.SearchParams;
await _mainPageViewModel.FetchData(searchParams);
var list = _mainPageViewModel.AdsList;
Assert.IsNotNull(list);
}
This is one of the failing tests.
public async Task<ListAdsReplyViewModel> FetchData(List<KeyValuePair<string, string>> parameters)
{
_cancellationTokenSource = new CancellationTokenSource();
_cancellationTokenSource
.CancelAfter(Constants.TimeToCancelAsyncOperations);
AddSearchKeywordToSearchParams();
var result = await _listAdsReplyApiService
.GetWithParametersAsync(_cancellationTokenSource, parameters);
var vm = new ListAdsReplyViewModel
{
Ads = new List<AdInfoViewModel>()
};
foreach (var listAd in result.ListAds)
{
var listAdDto = Mapper.Map<ListAdDto>(listAd);
var adInfo = new AdInfoViewModel(_navigationService, _mainPageTrackingService)
{
ListAdDto = listAdDto
};
vm.Ads.Add(adInfo);
}
vm.NextPage = result.NextPage;
vm.ConfigEtag = result.ConfigEtag;
vm.Sorting = result.Sorting;
TotalAds = result.ListAdsCounterMap.AllAds;
return vm;
}
private void AddSearchKeywordToSearchParams()
{
if (!string.IsNullOrEmpty(SearchKeyWord))
{
var searchKeyword = SearchParams
.FirstOrDefault(x => x.Key == "q");
if (!searchKeyword.Equals(null))
SearchParams.Remove(searchKeyword);
SearchParams.Add(new KeyValuePair<string, string>("q", SearchKeyWord));
}
}
And this are the methods under test. The problem seems to happen when foreach((var listAd in result.ListAds) is called. It's like GetWithParametersAsync(_cancellationTokenSource, parameters); is not being awaited, because I get the following error for the failing tests:
Test method App.Tests.Integration.App.Shared.ViewModels.MainPageViewModelTests.GivenParameterIsProvidedThenFetchDataShouldReturnValidData threw exception:
AutoMapper.AutoMapperMappingException:
Mapping types:
ListAd -> ListAdDto
Core.Api.Models.PublicAds.ListAd -> Core.Dto.ListAdDto
Destination path:
ListAdDto
Source value:
Core.Api.Models.PublicAds.ListAd ---> System.NullReferenceException: Object reference not set to an instance of an object.
at Core.Bootstrap.AutoMapperConfiguration.<>c__DisplayClass0_0.<Configure>b__12(ListAd src, ListAdDto dest)
at AutoMapper.Internal.MappingExpression`2.<>c__DisplayClass57_0.<AfterMap>b__0(Object src, Object dest)
at AutoMapper.TypeMap.<get_AfterMap>b__40_0(Object src, Object dest)
at AutoMapper.Mappers.TypeMapObjectMapperRegistry.PropertyMapMappingStrategy.Map(ResolutionContext context, IMappingEngineRunner mapper)
at AutoMapper.Mappers.TypeMapMapper.Map(ResolutionContext context, IMappingEngineRunner mapper)
at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context)
--- End of inner exception stack trace ---
at App.ViewModels.MainPageViewModel.<FetchData>d__34.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at App.Tests.Integration.App.Shared.ViewModels.MainPageViewModelTests.<GivenParameterIsProvidedThenFetchDataShouldReturnValidData>d__7.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Any thoughts?
As this was accepted in the comments, I've reposted as an Answer;
"Have you taken into account that MSTest will run your tests multi-threaded - and that by executing a single test you are forcing a single-thread ? Be very careful that all your tests are UNIT tests and have no dependency on each other, in the sequence of execution, or the possiblity that shared resources might have already been instantiated (or being in the process of instantiation) by another tests running in parallel. "

Categories

Resources