Filter data from azure database using Mobile Service client - forms

I am trying to restrict the data returned by the Mobile App service hosted on Azure portal. Unfortunately I am unable to restrict the data before it's returned (at the createQuery() stage). The filter works only when applied after the data is returned. Here is a sample code. The app is written in Xamarin forms on iOS platform.
public async Task<IEnumerable<Company>> GetCompanies(string
cityId)
{
await App.MobileService.SyncContext.InitializeAsync(store,
handler);
this.companies = App.MobileService.GetSyncTable<Company>();
try
{
await App.MobileService.SyncContext.PushAsync();
// Filter is unsuccessful here
await this.companies.PullAsync("all_companies",
this.companies.CreateQuery().Where(x => x.City_Id ==
cityId)).ConfigureAwait(false);
}
catch (MobileServicePushFailedException ex)
{
string ErrorString = string.Format("Push failed because
of Company sync errors: {0} errors, message:
{1}",ex.PushResult.Errors.Count, ex.Message);
}
catch (Exception ex)
{
Debug.WriteLine("Exception Sync companies: " + ex);
}
// Filter works here. But its too late as it has already
// pulled all the unnecessary data
return await companies.Where(x => x.City_Id ==
cityId).OrderBy(c => c.Id).ToEnumerableAsync();
}

Related

WSDL FaultExceptions not caught

I'm attempting to get FaultExceptions to hit for a WSDL service.
I have attempted the following:
Created a new .Net 7.0 project in Visual studio
Added the WSDL service reference for https://wsaimport.uni-login.dk/wsaimport-v7/ws?WSDL
Called the generated WSDL method hentDataAftalerAsync
Added below code to Program.cs
var binding = new CustomBinding(new TextMessageEncodingBindingElement(MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None), Encoding.UTF8), new HttpsTransportBindingElement { MaxReceivedMessageSize = 104857600 });
var ws10Client = new ServiceReference2.WsaImportPortTypeClient(binding, new EndpointAddress("https://wsaimport.uni-login.dk/wsaimport-v7/ws"));
try
{
var res = await ws10Client.hentDataAftalerAsync(new Credentials() {
wsBrugerid = "randomusername",
wsPassword = "randompassword"
});
// this is reached if credentials are correct
foreach (var item in res.hentDataAftalerResponse1.ToList())
{
Console.WriteLine(item);
}
}
catch(FaultException<AuthentificationError> ex)
{
// Neven hit (I expect this exception on wrong credentials)
Console.WriteLine(ex.Message);
}
catch (FaultException ex)
{
// Never hit
Console.WriteLine(ex.Message);
}
catch (ProtocolException ex)
{
// this exception is hit (but no info about the actual soap fault)
}
catch (Exception ex)
{
// Never hit
Console.WriteLine(ex.Message);
}
I have tested the hentDataAftaler operation in SoapUI, and when the credentials are wrong it does generate a SOAP response with a Fault of authentificationError.
So my question is, why is it not working for me in C#?

AADSTS70002: Error validating credentials. AADSTS50013: Assertion is not within its valid time range. error in memory dump using WinDbg

Recently we had a production deployment of normal windows store app. It was working fine for few days and after some days performance is very very slow. Our application follows Gate keeper pattern where store app hits gate keeper and gate keeper to rest service and rest service to database (everything is hosted in cloud).
After analyzing we found that Gatekeeper web app is taking more time to respond. We have taken memory dump for the web app and analyzed using WinDbg and found an issue with AAD access token where lock count is measured as 2. And attached is the result taken from memory dump.
Here is the actual code to get access token (we are using cert based authentication)
public static void GetCert()
{
try
{
var clientAssertionCertPfx = Helper.FindCertificateByThumbprint(WebConfigurationManager.AppSettings["CertificateThumbPrint"]);
AssertionCert = new ClientAssertionCertificate(WebConfigurationManager.AppSettings["ida:ClientID"], clientAssertionCertPfx);
}
catch (Exception ex)
{
throw ex;
}
}
public static async Task<string> GetAccessToken(string authority, string resource, string scope)
{
try
{
string userName = "";
GetCert();
var context = new AuthenticationContext(authority, TokenCache.DefaultShared);
AuthenticationResult result = null;
var bootstrapContext = ClaimsPrincipal.Current.Identities.First().BootstrapContext as System.IdentityModel.Tokens.BootstrapContext;
if (bootstrapContext != null)
{
userName = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn) != null ? ClaimsPrincipal.Current.FindFirst(ClaimTypes.Upn).Value : ClaimsPrincipal.Current.FindFirst(ClaimTypes.Email).Value;
if (!string.IsNullOrEmpty(bootstrapContext.Token))
{
UserAssertion userAssertion = new UserAssertion(bootstrapContext.Token, "urn:ietf:params:oauth:grant-type:jwt-bearer", userName);
AuthenticationContext authContext = new AuthenticationContext(authority);
result = await authContext.AcquireTokenAsync(resource, AssertionCert, userAssertion);
return result != null ? result.AccessToken : null;
}
return null;
}
else
{
return null;
}
}
catch (Exception ex)
{
LogErrorDetails objLogDetails = new LogErrorDetails();
ErrorLog objErrorLog = new ErrorLog();
objLogDetails.ErrorDescription = ex.Message;
objLogDetails.ErrorNumber = ex.HResult;
objLogDetails.strErrorContext = "Helper";
objLogDetails.strErrorContextArea = "GetAccessToken";
objLogDetails.strTrace = ex.StackTrace;
await objErrorLog.InsertErrorLog(objLogDetails);
return null;
}
}
While running this code locally we are not getting any issue with the access token and it is fast. Only in production environment performance is very slow and not sure it is with the access token or any other parameter.
Could you please help us in analyzing what went wrong with our code.

Azure Mobile Apps Offline Client Throws NotSupportedException on Query

I have a Azure Mobile Apps Xamarin.Forms PCL client and have Offline Sync enabled. I tried to Pull data from my backend and afterwards query data from the offline storage with a Where clause. That throws the following exception and I don't know why.
Sync error: 'fahrerinfo.Imei.Equals("02032032030232")' is not supported in a 'Where' Mobile Services query expression.
public async Task SyncAsync()
{
ReadOnlyCollection<MobileServiceTableOperationError> syncErrors = null;
try
{
await OfflineSyncStoreManager.Instance.TruckFahrerTable.PullAsync("allTruckFahrerItems",
OfflineSyncStoreManager.Instance.TruckFahrerTable.CreateQuery());
Debug.WriteLine("SyncAsync: PUSH/PULL completed.");
}
catch (MobileServicePushFailedException e)
{
Debug.WriteLine("SyncAsync: PUSH failed.");
Debug.WriteLine(e.Message);
}
catch (Exception e)
{
Debug.WriteLine("SyncAsync: PUSH/PULL failed.");
Debug.WriteLine(e.Message);
//Debugger.Break();
}
}
public async Task<ObservableCollection<TruckFahrer>> GetTruckFaherAsync(bool syncItems)
{
try
{
if (syncItems)
{
await OfflineSyncStoreManager.Instance.SyncAsync().ConfigureAwait(false);
}
var deviceInfo = DependencyService.Get<IDeviceInfo>().GetPhoneInfo();
var imeiString = deviceInfo[trucker_rolsped.PhoneInfo.PhoneInfo.ImeiKey];
var imei = imeiString.Equals("000000000000000") ? deviceInfo[trucker_rolsped.PhoneInfo.PhoneInfo.IdKey] : imeiString;
IEnumerable<TruckFahrer> items =
await OfflineSyncStoreManager.Instance.TruckFahrerTable
//.Where(fahrerinfo => fahrerinfo.Imei.Equals(imei)) TODO: Why does that throw an exception???
.ToEnumerableAsync();
// TODO: Because above does not work
items = items.Where(fahrer => fahrer.Imei.Equals(imei));
return new ObservableCollection<TruckFahrer>(items);
}
catch (MobileServiceInvalidOperationException msioe)
{
Debug.WriteLine(#"Invalid sync operation: {0}", msioe.Message);
Debugger.Break();
}
catch (Exception e)
{
Debug.WriteLine(#"Sync error: {0}", e.Message);
Debugger.Break();
}
return null;
}
Thanks for any hint,
Eric
Are you a Java developer too? I'm and had this issue because in Java we need to compare strings with String#equals method, haha.
For some reason MobileServices doesn't allow us to use Equals in this situation.
To fix your problem, use == instead. As you can see here C# difference between == and Equals() both have the same effect in this case.
Where(fahrerinfo => fahrerinfo.Imei == imei)

.Net HttpClient not able to deserialize exceptions

I'm creating an "SDK/Proxy" class using HttpClient and would like to pass exceptions thrown by the service the SDK is consuming to the application that is using this SDK. The original exception needs to be preserved unaltered and not wrapped. I've tried EnsureSuccessStatusCode() but it is no good because the original exception is lost to the consumer.
Below is SDK code that is attempting to catch exceptions from base service and pass it on to the consumer;
public async Task<string> GetValue(string effect)
{
using (var client = GetHttpClient())
{
HttpResponseMessage resp = await client.GetAsync("api/values?effect=" + effect).ConfigureAwait(false);
if (resp.IsSuccessStatusCode)
{
return await resp.Content.ReadAsStringAsync();
}
throw await resp.Content.ReadAsAsync<Exception>();
}
}
The "consumer" service is using the SDK like so;
public async Task<string> Get(string effect)
{
return await baseSvc.GetValue(effect);
}
When testing this I am getting the following response;
{
Message: "An error has occurred."
ExceptionMessage: "Member 'ClassName' was not found."
ExceptionType: "System.Runtime.Serialization.SerializationException"...
the base service code throwing the exception is this;
public async Task<string> Get(string effect)
{
switch (effect.ToLower())
{
case "string":
return "this is a string";
case "exception":
throw new ApplicationException("this is an application exception.");
default:
return "effect requested does not exist.";
}
}
Is it possible to "flow" the original unaltered exception from the consumed service through the SDK to the consumer?
You can use following.
string responseBody = response.Content.ReadAsStringAync().Result;
throw new HttpException((int)response.StatusCode, responseBody);
I have referred this - web API and MVC exception handling

HttpWebRequest maintenance and http web errors causing it to return "HRESULT E_FAIL" and "server not found"

I am iterating through a large list of objects (1503) and calling a save method on a ServiceProxy I have written. The service proxy uses the new networking stack in Silverlight 4 to call BeginGetRequestStream to start the process of asynchronously sending my objects to an azure REST service I have written for saving off the objects. The Http method I am using is POST. I know HttpWebClient is smart enough to reuse the Http connection so I am not concurrently opening 1503 connections to the server. Saving works fine and all 1503 objects are saved very quickly. However, when I try to save the same objects again, I expect to recieve an HttpStatus code of forbidden because the objects already exist and that is the code I set my azure web service to return. On small groups of objects, it works as expected. However, when I try saving the entire list of 1503 objects, I receive only 455 correct responses and 1048 errors such as "server not found" and
System.Exception ---> System.Exception:Error HRESULT E_FAIL has been returned from a call to a COM component.
at
System.Net.Browser.ClientHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)...
I wonder if there is some sort of book keeping or maintenance I am supposed to be performing on my HttpWebClient instances that I am neglecting and that is what is causing the http errors to throw exceptions but the new saves to work perfectly. Here is my code for handling the error cases:
private static void SendAncestorResponseCallback(IAsyncResult result)
{
var info = (SendAncestorInfo)result.AsyncState;
try
{
var response = info.Request.EndGetResponse(result);
info.Response = response;
}
catch ( Exception ex)
{
info.Error = ex;
}
info.MainThreadContext.Post(SendAncestorMainThreadCallback, info);
}
private static void SendAncestorMainThreadCallback(object state)
{
var info = (SendAncestorInfo)state;
IAncestor origAncestor = info.Content;
HttpWebResponse response = null;
if (info.Error != null)
{
if ((info.Error as WebException) == null)
{
info.Callback(false, origAncestor, null, info.Error);
return;
}
else //get response from WebException
{
response = (HttpWebResponse)(info.Error as WebException).Response;
}
}
else //get response from info.Response
{
response = info.Response as HttpWebResponse;
}
if (response.StatusCode == HttpStatusCode.Created || response.StatusCode == HttpStatusCode.Forbidden)
{
var stream = response.GetResponseStream();
using (var reader = new StreamReader(stream))
{
IAncestor retAncestor = XMLSerializerHelper.DeserializeObject<Ancestor>(reader.ReadToEnd());
info.Callback(response.StatusCode == HttpStatusCode.Created, origAncestor, retAncestor, null);
}
}
else info.Callback(false, origAncestor, null, info.Error);
}
considering how the web service is written I should only expect http status codes of created or forbidden and like I said with small groups this is the case. The fact that I only start getting the errors mentioned earlier makes me feel like I am doing something wrong with the HttpWebRequest objects etc. Any assistance would be greatly appreciated. Thanks.
--update here is the code that generates the HttpWebRequest:
foreach (IAncestor ancestor in ancestors)
{
AncestorViewModel ancestorVM = new AncestorViewModel(ancestor);
ancestorVM.Status = SaveStatus.Undefined;
ParsedAncestors.Add(ancestorVM);
_service.CreateAncestor(UserSrc, ancestor, (success, origAncestor, retAncestor, exception) =>
{
AncestorViewModel result = ParsedAncestors.First(a => a.Model.IdNo == origAncestor.IdNo);
if (exception == null)//web response was either Created or Forbidden
{
if (success)//Ancestor successfully created
{
savedAncestors++;
SuccessMessage = string.Format("{0} Saved\n", savedAncestors);
result.Status = SaveStatus.Saved;
}
else //Ancestor already existed
{
conflictAncestors.Add(origAncestor, retAncestor);
ConflictMessage = string.Format("{0} Conflicts\n", conflictAncestors.Count);
result.Status = SaveStatus.Conflicted;
}
}
else //Show exception recieved from remote web service
{
//if (exception as WebException != null)
//{
// //if exception is WebException get status code and description
// HttpWebResponse rs = (HttpWebResponse)(exception as WebException).Response;
// Message += string.Format("WebServer returned status code {0}: '{1}'\n", (int)rs.StatusCode, rs.StatusDescription);
//}
errors.Add(origAncestor, exception);
ErrorMessage = string.Format("{0} Errors\n", errors.Count);
result.Status = SaveStatus.Error;
}
});
}
public void CreateAncestor(string userSrc, IAncestor ancestor, Action<bool, IAncestor, IAncestor, Exception> callback)
{
WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);
var request = (HttpWebRequest)WebRequest.Create(
new Uri(string.Format("{0}/{1}/{2}", rootUri, AncestorsRestPoint, userSrc)));
request.Method = "POST";
request.ContentType = "application/xml";
var info = new SendAncestorInfo
{
Request = request,
Callback = callback,
Content = ancestor,
MainThreadContext = SynchronizationContext.Current
};
request.BeginGetRequestStream(SendAncestorRequestCallback, info);
}