Xamarin.Forms Azure DocumentDb Exception - xamarin.forms

I am using latest version of Microsoft.Azure.DocumentDB.Core (1.3.1.0) but keep getting an exception when trying to connect:
Example:
I create a Client Connection:
if (Client == null)
{
Client = new DocumentClient(new Uri(AppConstants.SUBSCRIPTION_URL),
AppConstants.PRIMARY_KEY);
}
And I try to query some data:
public async Task<List<Config>> GetAll()
{
var configs = new List<Config>();
var queryOptions = new FeedOptions { MaxItemCount = -1 };
var settings = Client.CreateDocumentQuery<Config>(UriFactory.CreateDocumentCollectionUri(AppConstants.COSMOS_DATABASE, COLLECTION_ID), queryOptions).AsDocumentQuery();
if (settings != null)
{
while(settings.HasMoreResults)
{
configs.AddRange(await settings.ExecuteNextAsync<Config>());
}
}
return configs;
}
And I get this error, even tough Settings is not null:
System.NullReferenceException: Object reference not set to an instance
of an object.
At first I thought its todo with the Client not being open so I tried adding:
await Client.OpenAsync();
But this has the same issue. Now running this same code in Asp.Net using the Web Client Nuget, The code runs perfectly.
Any ideas if recent changes to Xamarin or DocumentDB could be the cause or am I missing something else please?
Thanks,

Related

EPPLUS package works fine locally but returns Internal server error when deployed to azure server

I have my web api that uploads and reads an excel file from the client app and then afterwards saves the data into the database, the application works perfect on locally server but the problem comes when the application is deployed to azure server it returns error 500 internal server error therefore i don't understand why this happens and and don't know how i can track to understand what might be the cause below are my code blocks.
My Interface Class
public interface UploadExcelInterface
{
Task UploadMultipleClients(Client obj);
}
My Service Implementation
public class UploadExcelService : UploadExcelInterface
{
private readonly DbContext _connect;
private readonly IHttpContextAccessor httpContextAccessor;
public UploadExcelService(DbContext _connect, IHttpContextAccessor httpContextAccessor)
{
this._connect = _connect;
this.httpContextAccessor = httpContextAccessor;
}
public async Task UploadMultipleClients(Client obj)
{
var file = httpContextAccessor.HttpContext.Request.Form.Files[0];
if (file != null && file.Length > 0)
{
var folderName = Path.Combine("Datas", "ClientUPloads");
var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), folderName);
var fileName = Guid.NewGuid() + ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
var fullPath = Path.Combine(pathToSave, fileName);
var clientsList = new List<Client>();
using (var fileStream = new FileStream(fullPath, FileMode.Create))
{
await file.CopyToAsync(fileStream);
FileInfo excelFile = new FileInfo(Path.Combine(pathToSave, fileName));
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
using (ExcelPackage package = new ExcelPackage(excelFile))
{
ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
var rowcount = worksheet.Dimension.Rows;
for (int row = 2; row <= rowcount; row++)
{
var Names = (worksheet.Cells[row,2].Value ?? string.Empty).ToString().Trim();
var Address = (worksheet.Cells[row,3].Value ?? string.Empty).ToString().Trim();
var Title = (worksheet.Cells[row,4].Value ?? string.Empty).ToString().Trim();
var Product = (worksheet.Cells[row,5].Value ?? string.Empty).ToString().Trim();
var Order = (worksheet.Cells[row,6].Value ?? string.Empty).ToString().Trim();
var Email = (worksheet.Cells[row,7].Value ?? string.Empty).ToString().Trim();
var Price = (worksheet.Cells[row,8].Value ?? string.Empty).ToString().Trim();
clientsList.Add(new Client
{
Names = Names,
Address = Address,
Title = Title,
Product = Product,
Order = Order,
Email = Email,
Price = Price,
}
}
//adding clients into the database
foreach (Client client in clientsList)
{
var exist = _connect.client.Any(x => x.Email == client.Email);
if (!exist)
{
await _connect.client.AddAsync(client);
}
}
await _connect.SaveChangesAsync();
}
}
}
My Controller Class
[HttpPost]
public async Task UploadMultipleClients([FromForm] Client obj)
{
await uploadExcelInterface.UploadMultipleClients(obj);
}
}
Please any help regarding this error that am getting from the server, and addition on that is it possible to get the data from the excel file without uploading it to server if yes how? because i tried adding the file to memory stream an reading it from memory but it appers not work, any suggestions thanks.
My answer may not help you solve the problem directly, but it can locate the error step by step. After we fix the error, we should be able to solve the problem in this thread.
Suggestions
Please make sure you have inclue EPPlus library in your deploy content.
Enabling ASP.NET Core stdout log (Windows Server)
Azure App Service - Configure Detailed Error Logging
Why
After tested, I am sure azure webapp can support EPPlus. For 500 error, as we don't have a more specific error message to refer to, we can't quickly locate the problem. Following the suggested method, you will surely see some useful information.
E.g:
The class library of EPPlus was not found.
Folders such as Datas are not created.
The database connection string, the test environment and the production environment may be different.
...

Delta Query with delta token: Microsoft Graph SDK

I am working on change notifications for users using Microsoft Graph SDK in a .netcore application.
I am using delta query to get the latest changes.
private static IUserDeltaCollectionPage? lastPage = null;
private async Task<IUserDeltaCollectionPage> GetUsers(GraphServiceClient graphClient, object? deltaLink)
{
IUserDeltaCollectionPage page;
if (lastPage == null || deltaLink == null)
{
page = await graphClient.Users
.Delta()
.Request()
.GetAsync();
}
else
{
lastPage.InitializeNextPageRequest(graphClient, deltaLink.ToString());
page = await lastPage.NextPageRequest.GetAsync();
}
lastPage = page;
return page;
}
The problem I am facing with this approach is that, if the application restarts for what ever reason the lastPage will be null. In which case the next time the application runs it will bring back all the users. I don't want to get all the users, I just want to get the changed users.
Is there a way to make a delta query with the latest delta link?
I tried the below but I am getting badly formed query error.
var queryOptions = new List<QueryOption>()
{
new QueryOption("$deltatoken", deltaLink?.ToString())
};
await graphClient.Users.Delta().Request(options).GetAsync();
You can ask for the latest deltaLink by adding $deltaToken=latest to the delta function and the response will contain a deltaLink and no resource data.
Then you need to use received deltaLink
var queryOptions = new List<QueryOption>()
{
new QueryOption("$deltatoken", "latest")
};
var page = await graphClient.Groups.Delta().Request(options).GetAsync();
var users = page.CurrentPage.ToList();
if (page.NextPageRequest!=null)
{
// get latest data
page = await page.NextPageRequest.GetAsync();
}
Resources:
delta query

MoveNext error using async with Xamarin forms

I have a Xamarin Android forms project using a CodeIgniter back end, with NuSoap.
I visual studio I created a .NET core project for testing, added a connected service to the server. Created a async task to pull the data from the server, this all worked correctly.
var client = new TbqService.ServicePortTypeClient();
var loginTask = Task.Run(() => client.logInAsync("user", "password"));
echoTask.Wait();
Console.WriteLine($"Login result {loginTask.Result}");
I then followed the same sequence for the Xamarin forms application but am getting the following error. I have seen comments about setting the SSL to TLS 1.2 and removing the bin/obj folder and rebuilding. Neither helped.
{System.NullReferenceException: Object reference not set to an instance of an object.
at MyThingApp.Models.DataConnect+<Login>d__13.MoveNext () [0x00023] in
D:\WebSites\TheMyThing_Projects\MyThingApp\MyThingApp\MyThingApp\Models\DataConnect.cs:31 }
Is there a different in the way the two work, should I be handling them differently?
public async Task<bool> Login(string email, string password)
{
try
{
var c = new TbqService.ServicePortTypeClient();
var result = await c.logInAsync(email, password); // line 31 in error
return result.Contains("true");
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
}
return false;
}
It seems like result might be returning null. And so it crashes when you are trying to access contents inside result. Add a null check, and that should remove you error.
if (result != null)
return result.Contains("true");

Assembly.UnsafeLoadFrom causes web app crash

I am trying to load a DLL from internet, more specifically it is Azure storage (Blob), so I used "Assembly.UnsafeLoadFrom" like this:
Assembly.UnsafeLoadFrom(#"https://accountname.blob.core.windows.net/test/calculator.dll");
But becuaset this specific call, my web app (published) returns:
"The specified CGI application encountered an error and the server
terminated the process."
The weird part is if I am using my local build, it is fine. there is no crash and the return result is correct.
I am using Visual Studio 2015 and .net 5.
Please let me know how to resolve this issue or how to debug it.
Thanks
For a simple way, you could achieve your purpose by the following code:
calculator.dll
public class Calculator
{
public string HelloWorld(string userName)
{
return string.Format("Hello world, {0}!", userName);
}
}
HomeController.cs
public async Task<ActionResult> Index()
{
string url = "https://brucechen.blob.core.windows.net/dll/calculator.dll";
HttpClient client = new HttpClient();
var bytes = await client.GetByteArrayAsync(url);
//load assembly from bytes
Assembly assembly = Assembly.Load(bytes);
var calc = assembly.CreateInstance("calculator.Calculator");
//invoke the method and get result
var result = calc.GetType().InvokeMember("HelloWorld", BindingFlags.InvokeMethod, null, calc, new[] { "Bruce" });
ViewData["result"] = result;
return View();
}
Result

Office 365 Rest Api Having issues getting access token

So far i have this.
public static async Task<OutlookServicesClient> CreateOutlookClientAsync(string capability)
{
try
{
string authority = CommonAuthority;
// Create an AuthenticationContext using this authority.
_authenticationContext = new AuthenticationContext(authority);
//See the Discovery Service Sample (https://github.com/OfficeDev/Office365-Discovery-Service-Sample)
//for an approach that improves performance by storing the discovery service information in a cache.
DiscoveryClient discoveryClient = new DiscoveryClient(
async () => await GetTokenHelperAsync(_authenticationContext, DiscoveryResourceId));
// Get the specified capability ("Contacts").
CapabilityDiscoveryResult result =
await discoveryClient.DiscoverCapabilityAsync(capability);
var client = new OutlookServicesClient(
result.ServiceEndpointUri,
async () =>
await GetTokenHelperAsync(_authenticationContext, result.ServiceResourceId));
return client;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
if (_authenticationContext != null && _authenticationContext.TokenCache != null)
_authenticationContext.TokenCache.Clear();
return null;
}
}
}
private static async Task<string> GetTokenHelperAsync(AuthenticationContext context, string resourceId)
{
string accessToken = null;
AuthenticationResult result = null;
string myId = WebConfigurationManager.AppSettings["ida:ClientID"];
string myKey = WebConfigurationManager.AppSettings["ida:Password"];
ClientCredential client = new ClientCredential(myId,myKey);
result = await context.AcquireTokenAsync(resourceId, client);
//result =context.AcquireToken(resourceId, ClientID,_returnUri);
accessToken = result.AccessToken;
return accessToken;
}
When i get to result one of two things happen if i user AcquireTokenAsync i get an error stating Application with identifier XXXX was not found in directory api.office.com otherwise if i run AcquireToken i get the login modal to pop but an error occurs indicating the request must contain client_secret .
I have no idea how to resolve this issue i suspect it may have something to do with the actual app configuration i have tried both creating my own app in Azure AD and using VS Connected Service, Has Anyone Else ran into a similar issues?
Based on the errors you're seeing, there seems to be an issue with how your app is registered. The first error usually happens when the app is not marked as multi-tenant, and you login to the app with a tenant other than the one where the app is registered.
The second error is odd. Client secret is what you're reading out of the ida:Password element and passing in the ClientCredential object.
I just put a .NET tutorial up yesterday that walks through setting this stuff up. Take a look and see if that helps get you unblocked.

Resources