async WebRequest troubles - async-await

I am trying to create some regression tests that make async calls to our API. I have been getting a null reference error consistently no matter what I try. I have tried several different ways of calling the request to no avail. I'm at my wit's end. I can put a breakpoint in the code to check the URL and run that URL in Postman and it returns data as expected. I am passing a few headers but nothing out of the ordinary.
Below is the stack trace and my code. Can anyone see what I am missing?
Thanks
<GetApiResponse>d__17`1.MoveNext() in C:\Users\foo\Documents\test.api\Common\Base.cs:line 199
--- 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 Test.API.ResultsTest.<ResultsAPI_SortByLowToHigh>d__1.MoveNext() in C:\Users\voo\Documents\test.api\ResultsTest.cs:line 74
--- 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.GetResult()
Result Message:
Test method Test.API.ResultsAPI_SortByLowToHigh threw exception:
System.NullReferenceException: Object reference not set to an instance of an object.
try
{
var webRequest = WebRequest.Create(url);
webRequest.Method = "GET";
webRequest.ContentType = "application/json";
webRequest.Headers.Add("ApiVersion", "1");
webRequest.Headers.Add("Country-Code", "US");
webRequest.Headers.Add("Currency-Code", "USD");
Task<WebResponse> responseTask = webRequest.GetResponseAsync();
using (var webResponse = await responseTask)
{
using (var sres = webResponse.GetResponseStream())
{
var ms = new MemoryStream();
if (sres != null) await sres.CopyToAsync((ms));
ms.Position = 0;
using (var sr = new StreamReader(ms))
{
JsonResponse = sr.ReadToEnd();
}
}
}
if (!string.IsNullOrEmpty(JsonResponse))
{
response = JsonConvert.DeserializeObject<ServiceResponse>(JsonResponse);
}
else
{
throw new Exception(typeof(ServiceResponse).Name + " API returned null Response");
}
return response;
}
catch (WebException e)
{
ErrorMsg.AppendLine(e.Message);
throw;
}

Related

Background Job Fails with "Current user did not login to the application"

using MVC jQuery .NET Core
using Abp Background Job
I have a background job that get Enqueued correctly and I can see the job in the db.
However the logging shows me I'm getting and authorization error (ee below) despite being logged in. I have the same AbpAuthorize attributes placed on the services and background jobs.
Not sure how to proceed debugging the problem - any suggestions welcome.
SERVICE CODE USING/ENQUEUING THE JOB:
public async Task BulkImportBackground(IList<CreatePracticeDto> inputs)
{
await _backgroundJobManager.EnqueueAsync<ImportBulkPracticesBackgroundJob, ImportBulkPracticesBackgroundJobArgs>(
new ImportBulkPracticesBackgroundJobArgs
{
CreatePracticeDtos = inputs
});
_backgroundJobManager.Start();
}
JOB CLASS CODE:
using Abp.Authorization;
using Abp.BackgroundJobs;
using Abp.Dependency;
using Abp.Modules;
using Gp.Authorization;
using Gp.Ccre.ImportResult;
using Gp.Ccre.ImportResult.Dtos;
using Gp.Ccre.Practice.Dtos;
using System;
using System.Collections.Generic;
using System.Linq;
using Abp.Domain.Uow;
namespace Gp.Ccre.Practice.BackgroundJobs
{
[DependsOn(
typeof(IPracticeAppService),
typeof(IImportResultsAppService))]
[AbpAuthorize(PermissionNames.Pages_Practices, RequireAllPermissions = false)]
public class ImportBulkPracticesBackgroundJob : BackgroundJob<ImportBulkPracticesBackgroundJobArgs>, ITransientDependency
{
private readonly IPracticeAppService _practiceAppService;
private readonly IImportResultsAppService _importResultsAppService;
public ImportBulkPracticesBackgroundJob(IImportResultsAppService importResultsAppService, IPracticeAppService practiceAppService)
{
_practiceAppService = practiceAppService;
_importResultsAppService = importResultsAppService;
}
public override void Execute(ImportBulkPracticesBackgroundJobArgs args)
{
IList<CreateImportResultDto> createResultsDto = new List<CreateImportResultDto>();
var k = 0;
DateTime importedOn = DateTime.Now;
foreach (CreatePracticeDto createDto in args.CreatePracticeDtos)
{
k++;
try
{
//this correctly automatically ignores 'soft' deleted records.
var count = _practiceAppService.GetAllIdName().Result.Count(x => x.Name.Equals(createDto.Name, StringComparison.CurrentCultureIgnoreCase));
if (count > 0)
{
createResultsDto.Add(new CreateImportResultDto
{
Row = k,
Name = createDto.Name,
Message = "Already exists. Skipped.",
MessageType = AppConsts.ImportMessageType.Warning.ToString(),
ImportedOn = importedOn
});
continue;
}
// ** GOOGLE MAP API CALL **
var coordinatesFound = false; //_practiceAppService.TryGetGeoCodeAddress(createDto);
createDto.ImportedOn = importedOn;
// *** SAVE SINGLE ****
_practiceAppService.Create(createDto);
createResultsDto.Add(new CreateImportResultDto
{
Row = k,
Name = createDto.Name,
Message = "Successful.",
MessageType = AppConsts.ImportMessageType.Info.ToString(),
ImportedOn = importedOn,
GoogleMapCoordinatesFound = coordinatesFound
});
}
catch (Exception e)
{
createResultsDto.Add(new CreateImportResultDto
{
Row = k,
Name = createDto.Name,
Message = e.Message,
MessageType = AppConsts.ImportMessageType.Error.ToString(),
ImportedOn = importedOn
});
continue;
}
}
//*** SAVE RESULTS ***
foreach (var resultDto in createResultsDto)
{
_importResultsAppService.Create(resultDto);
}
CurrentUnitOfWork.SaveChanges();
}
}
[Serializable]
public class ImportBulkPracticesBackgroundJobArgs
{
public IList<CreatePracticeDto> CreatePracticeDtos { get; set; }
}
}
STACK TRACE (partial)
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Abp.Authorization.AbpAuthorizationException: Current user did not login to the application!
at Abp.Authorization.AuthorizationHelper.AuthorizeAsync(IEnumerable`1 authorizeAttributes) in D:\Github\aspnetboilerplate\src\Abp\Authorization\AuthorizationHelper.cs:line 43
at Abp.Authorization.AuthorizationHelper.CheckPermissions(MethodInfo methodInfo, Type type) in D:\Github\aspnetboilerplate\src\Abp\Authorization\AuthorizationHelper.cs:line 98
at Abp.Authorization.AuthorizationHelper.AuthorizeAsync(MethodInfo methodInfo, Type type) in D:\Github\aspnetboilerplate\src\Abp\Authorization\AuthorizationHelper.cs:line 57
at Nito.AsyncEx.Synchronous.TaskExtensions.WaitAndUnwrapException(Task task)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
--- End of stack trace from previous location where exception was thrown ---
at Nito.AsyncEx.Synchronous.TaskExtensions.WaitAndUnwrapException(Task task)
at Nito.AsyncEx.AsyncContext.Run(Func`1 action)
at Abp.Authorization.AuthorizationInterceptor.Intercept(IInvocation invocation) in D:\Github\aspnetboilerplate\src\Abp\Authorization\AuthorizationInterceptor.cs:line 20
at Castle.DynamicProxy.AbstractInvocation.Proceed()
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at Abp.BackgroundJobs.BackgroundJobManager.TryProcessJob(BackgroundJobInfo jobInfo) in D:\Github\aspnetboilerplate\src\Abp\BackgroundJobs\BackgroundJobManager.cs:line 119
The problem was caused by trying to inject a service into the background job. stick to IRepository and all good.

Xamarin Forms InAppBillingPlugin PurchaseAsync exeption

I need some support regarding InAppBillingPlugin for Xamarin.Forms. First of all I did configuration according to documnetation: https://jamesmontemagno.github.io/InAppBillingPlugin/
application, Google Console (managed products) and iTunes Connect site.
Here is my application code.
private async Task TryInAppPurchace(string androidProductId, string iOSProductId="")
{
if (!CrossInAppBilling.IsSupported)
return;
//Android
var products = new string[] { androidProductId };
if(Device.RuntimePlatform == Device.iOS)
products = new string[] { iOSProductId };
var billing = CrossInAppBilling.Current;
//billing.InTestingMode = true;
try
{
var connected = await billing.ConnectAsync(ItemType.InAppPurchase);
if (!connected)
{
await Application.Current.MainPage.DisplayAlert("Connectivity Error", "Unable to connect to the internet.", "OK");
return;
}
var items = await billing.GetProductInfoAsync(ItemType.InAppPurchase, products);
var item = items.ToList().First();
//try to purchase item
var purchase = await billing.PurchaseAsync(item.ProductId, ItemType.InAppPurchase, item.ProductId);
//possibility that a null came through.
if (purchase == null)
{
await Application.Current.MainPage.DisplayAlert("Purchase Error", "You are unable to buy this product.", "OK");
return;
}
else
{
await _pageService.DisplayAlert("Purchased", "Consumable product.", "OK");
if (Device.RuntimePlatform == Device.iOS)
return;
var consumedItem = await CrossInAppBilling.Current.ConsumePurchaseAsync(purchase.ProductId, purchase.PurchaseToken);
if (consumedItem != null)
{
await Application.Current.MainPage.DisplayAlert("New Package added", "Successfully added new package", "OK");
}
}
}
catch (InAppBillingPurchaseException purchaseEx)
{
var message = string.Empty;
await Application.Current.MainPage.DisplayAlert("Exeption", purchaseEx.Message, "OK");
switch (purchaseEx.PurchaseError)
{
case PurchaseError.BillingUnavailable:
message = "BillingUnavailable";
break;
case PurchaseError.DeveloperError:
message = "DeveloperError";
break;
case PurchaseError.ItemUnavailable:
message = "ItemUnavailable";
break;
case PurchaseError.GeneralError:
message = "GeneralError";
break;
case PurchaseError.UserCancelled:
message = "UserCancelled.";
break;
case PurchaseError.AppStoreUnavailable:
message = "AppStoreUnavailable.";
break;
case PurchaseError.PaymentNotAllowed:
message = "PaymentNotAllowed.";
break;
case PurchaseError.PaymentInvalid:
message = "PaymentInvalid";
break;
case PurchaseError.InvalidProduct:
message = "InvalidProduct";
break;
case PurchaseError.ProductRequestFailed:
message = "ProductRequestFailed";
break;
case PurchaseError.RestoreFailed:
message = "RestoreFailed";
break;
case PurchaseError.ServiceUnavailable:
message = "ServiceUnavailable";
break;
}
}
catch (Exception ex)
{
//Something else has gone wrong, log it
await Application.Current.MainPage.DisplayAlert("Exeption", ex.Message, "OK");
}
finally
{
await billing.DisconnectAsync();
}
}
My problem is that I am not able to buy the same product again and I am getting exeption from Google Play:
{Plugin.InAppBilling.Abstractions.InAppBillingPurchaseException:
Unable to process purchase. at
Plugin.InAppBilling.InAppBillingImplementation+d__33.MoveNext
() [0x00116] in
C:\projects\inappbillingplugin\src\Plugin.InAppBilling.Android\InAppBillingImplementation.cs:324
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw ()
[0x0000c] in :0 at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess
(System.Threading.Tasks.Task task) [0x0003e] in
:0 at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
(System.Threading.Tasks.Task task) [0x00028] in
:0 at
System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd
(System.Threading.Tasks.Task task) [0x00008] in
:0 at
System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult ()
[0x00000] in :0 at
Plugin.InAppBilling.InAppBillingImplementation+d__32.MoveNext
() [0x00090] in
C:\projects\inappbillingplugin\src\Plugin.InAppBilling.Android\InAppBillingImplementation.cs:264
--- End of stack trace from previous location where exception was thrown --- at
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw ()
[0x0000c] in :0 at
System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess
(System.Threading.Tasks.Task task) [0x0003e] in
:0 at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
(System.Threading.Tasks.Task task) [0x00028] in
:0 at
System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd
(System.Threading.Tasks.Task task) [0x00008] in
:0 at
System.Runtime.CompilerServices.TaskAwaiter`1[TResult].GetResult ()
[0x00000] in :0 at
DrivingCourse_app.ViewModels.AccessPageViewModel+d__18.MoveNext
() [0x0025c] in
C:\Projects\GIT-REPO\DrivingCourse_DE\DrivingCourse_app\DrivingCourse_app\DrivingCourse_app\ViewModels\AccessPageViewModel.cs:136
}
Is something wrong with my code? This code is working for every fist purchase of the product, so configuration itself and the general process works.
Any ideas?

SignalR: Caller is not authorized to invoke the method

getting the error while calling the "SignalR: Caller is not authorized to invoke the LoadPvtChatHistory_Hub method" also IsAuthenticated always gets false.
public class QueryStringBearerAuthorizeAttribute : AuthorizeAttribute
{
public override bool AuthorizeHubConnection(Microsoft.AspNet.SignalR.Hubs.HubDescriptor hubDescriptor, IRequest request)
{
var dataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider();
var secureDataFormat = new Microsoft.Owin.Security.DataHandler.TicketDataFormat(dataProtectionProvider.Create());
//var secureDataFormat = new Microsoft.Owin.Security.DataHandler.TicketDataFormat(new MachineKeyProtector());
var token = request.QueryString.Get("Bearer");
if (string.IsNullOrEmpty(token))
return false;
// var token = request.QueryString.Get(WebApiConfig.AuthenticationType);
var authenticationTicket = secureDataFormat.Unprotect(token);
if (authenticationTicket == null || authenticationTicket.Identity == null || !authenticationTicket.Identity.IsAuthenticated)
{
return false;
}
request.Environment["server.User"] = new ClaimsPrincipal(authenticationTicket.Identity);
request.Environment["server.Username"] = authenticationTicket.Identity.Name;
request.GetHttpContext().User = new ClaimsPrincipal(authenticationTicket.Identity);
return true;
}
public override bool AuthorizeHubMethodInvocation(Microsoft.AspNet.SignalR.Hubs.IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
{
var connectionId = hubIncomingInvokerContext.Hub.Context.ConnectionId;
// check the authenticated user principal from environment
var environment = hubIncomingInvokerContext.Hub.Context.Request.Environment;
var principal = environment["server.User"] as System.Security.Claims.ClaimsPrincipal;
if (principal != null && principal.Identity != null && principal.Identity.IsAuthenticated) // IsAuthenticated always gets false
{
// create a new HubCallerContext instance with the principal generated from token
// and replace the current context so that in hubs we can retrieve current user identity
hubIncomingInvokerContext.Hub.Context = new Microsoft.AspNet.SignalR.Hubs.HubCallerContext(new Microsoft.AspNet.SignalR.Owin.ServerRequest(environment), connectionId);
return true;
}
else
{
return false;
}
}
}
when click on send button I am calling this Invoke method of AppHub but while calling it gives me an error like not authorized.
AppHub.invoke('LoadPvtChatHistory_Hub', curVM, GENERAL_CONFIG.APP_messageExpiryTimeLimit);
AppHub.cs
[QueryStringBearerAuthorize]
public class AppHub : Hub
{
public void LoadPvtChatHistory_Hub(string xiSelectedUserID, int xiMessageExpiryTimeLimit)
{
///code....
}
}
[16:36:33 GMT+0530 (India Standard Time)] SignalR: Caller is not authorized to invoke the LoadPvtChatHistory_Hub method on AppHub.
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.SignalR.Hubs.HubPipelineModule.<>c__DisplayClass0_0.<<BuildIncoming>b__0>d.MoveNext().
jquery.signalR.js:82 [16:36:33 GMT+0530 (India Standard Time)] SignalR: apphub.loadPvtChatHistory_Hub failed to execute. Error: Caller is not authorized to invoke the LoadPvtChatHistory_Hub method on AppHub.
jquery.signalR.js:82 [16:37:00 GMT+0530 (India Standard Time)] SignalR: Invoking apphub.sendPrivateMessage_Hub
jquery.signalR.js:82 [16:37:04 GMT+0530 (India Standard Time)] SignalR: Caller is not authorized to invoke the SendPrivateMessage_Hub method on AppHub.
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.AspNet.SignalR.Hubs.HubPipelineModule.<>c__DisplayClass0_0.<<BuildIncoming>b__0>d.MoveNext().
jquery.signalR.js:82 [16:37:04 GMT+0530 (India Standard Time)] SignalR: apphub.sendPrivateMessage_Hub failed to execute. Error: Caller is not authorized to invoke the SendPrivateMessage_Hub method on AppHub.
Here is my the solution, WORK on Azure and local. AngularJS, Web API and SignalR request.Environment["server.User"] this code doesn't work on Azure. First i create my Custom Filter Class.
public override bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubIncomingInvokerContext, bool appliesToMethod)
{
var connectionId = hubIncomingInvokerContext.Hub.Context.ConnectionId;
var request=hubIncomingInvokerContext.Hub.Context.Request;
var _Authorization = request.QueryString.Get("Bearer");
if (!string.IsNullOrEmpty(_Authorization))
{
//var token = _Authorization.Replace("Bearer ", "");
var ticket = Startup.OAuthOptions.AccessTokenFormat.Unprotect(_Authorization);
if (ticket != null && ticket.Identity != null && ticket.Identity.IsAuthenticated)
{
Dictionary<string, object> _DCI = new Dictionary<string, object>();
_DCI.Add("server.User", new ClaimsPrincipal(ticket.Identity));
hubIncomingInvokerContext.Hub.Context = new HubCallerContext(new ServerRequest(_DCI), connectionId);
return true;
}
}
return false;
}
Refer this article.

WebApi: Reading errors

I've got a simple web api which is consumed from a mvc project, I keep on getting the 'Response status code does not indicate success' and was wondering how would I get the response body from the error, I can see the error within a rest viewer but can't navigate through to the error. This is the following code within the MVC app
public ActionResult Index()
{
try
{
var uri = "http://localhost:57089/api/values";
using (var client = new HttpClient())
{
Task<string> response = client.GetStringAsync(uri);
object result = JsonConvert.DeserializeObject(response.Result);
return (ActionResult) result;
}
}
catch (Exception ex)
{
return Content(ex.ToString());
}
return View();
}
Within the API controller I'm sending a bad request, here's the code
public IHttpActionResult Get()
{
return BadRequest("this is a very bad request " + System.DateTime.Now.ToUniversalTime());
}
I've tried to use WebException, HttpRequestException as exceptions to catch the error with no luck.
I can see the response body within the rest viewer
I want to be able to navigate to the Error Message so I can pass that to the client (which later will be changed to a guid).
[EDITED]
I've got a solution without using GetStringAsync, but wanted to use that if possible.
Here's the solution
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(url);
HttpResponseMessage responseMessage = httpClient.GetAsync("").Result;
if (responseMessage.IsSuccessStatusCode) return Content(responseMessage.ToString());
var a = responseMessage.Content.ReadAsStringAsync().Result;
var result = JsonConvert.DeserializeObject<HttpError>(a);
object value = "";
return Content(result.TryGetValue("ErrorMessage", out value) ? value.ToString() : responseMessage.ToString());
Is there a better way?
Using WebException you should be able to get to the ResponseStream and the custom error message like this:
catch (WebException e)
{
var message = e.Message;
using (var reader = new StreamReader(e.Response.GetResponseStream()))
{
var content = reader.ReadToEnd();
}
}
Hope that helps.

Unable to see response body from HTTPWebRequest when status is 400

In the following, ar.GetResponseAsString() just throws an exception.
Here is my code:
AsyncCallback GetTheResponse = ar =>
{
try
{
var result = ar.GetResponseAsString();
Debug.WriteLine(string.Format("ResponseStream:::{0}", result));
callback(result, null);
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
}
What am I doing wrong?
Catch the WebException that the 400 is throwing then grab the response from the exception message. That's where your error response is hiding

Resources