How can I catch exception from backend server using IMobileServiceSyncTable - InsertAsync? - azure

I'm using IMobileServiceSyncTable from Azure Mobile App. In InsertAsync operation, on the backend server side, I had some validations for the data and, if that validations failure, I want throw Exception from the server side. I tried return InternalServerError(), throw HttpResponseException, but never worked on the client side. I debbuged the Post method in server side, the server throws the exception or return InternalServerError, but in the mobile client, don't occurs error.
Can anyone help me?
Here is my code on the client side:
public async Task<bool> AddPaciente(Paciente novoPaciente)
{
//other things
try
{
await _pacienteTable.InsertAsync(novoPaciente);
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
Debug.WriteLine(e.StackTrace);
throw new WebException(AppResources.MensagemFalhaConexaoServidorAzure);
}
await SyncPaciente();
return true;
}
Here is my post method on the backend server side
// POST tables/Paciente
public async Task<IHttpActionResult> PostPaciente(Paciente novoPaciente)
{
//other things
if (paciente != null)
{
var responseMessage = new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent("Já existe um paciente com esse token cadastrado.")
};
//throw new HttpResponseException(responseMessage);
return InternalServerError(new Exception("Já existe um paciente com esse token cadastrado."));
}
}

You should listen to the response status code.
var response = await _pacienteTable.InsertAsync(novoPaciente);
if (response.IsSuccessStatusCode) {
var content = await response.Content.ReadAsStringAsync ();
}
else
{
//Here handle the error code
throw new WebException(AppResources.MensagemFalhaConexaoServidorAzure);
}

I'm using IMobileServiceSyncTable from Azure Mobile App. In InsertAsync operation, on the backend server side, I had some validations for the data and, if that validations failure, I want throw Exception from the server side.
For IMobileServiceSyncTable, you are dealing with An Offline Client which means that IMobileServiceSyncTable<T>.InsertAsync would directly insert data into the local SQLite store on your mobile client-side. Until you manually call MobileServiceClient.SyncContext.PushAsync(), then your local data store would be pushed to your mobile backend. For this approach, I would recommend you make sure that you need to validate the inputs before you saving them into the local data store, otherwise your push operations would fail, then you need to force your client user to adjust the existing inputs even after it has been successfully added before.
If you use An Online Client as follows, then both your approaches for throwing the exception would be immediately returned to your client.
var mobileClient= new MobileServiceClient("https://{your-mobile-app-name}.azurewebsites.net");
var _pacienteTable= mobileClient.GetTable<Paciente>();
await _pacienteTable.InsertAsync(novoPaciente);
Moreover, I used the following code line for catching the exception:
try
{
await table.InsertAsync(item);
}
catch (MobileServiceInvalidOperationException ex)
{
//TODO:
//await ex.Response.Content.ReadAsStringAsync(); //get detailed response content
}
catch (Exception e)
{
//TODO: other uncaught exception
}
Also, for the similar issue, you could leverage Fiddler to capture the network traces to narrow down this issue, make sure your client-side could correctly receive the relevant response.

Related

Solace can't SEND while in WaitingForDNS

I'm trying send a message on a topic queue but the API returns
OperationError: Cannot perform operation SEND while in state WaitingForDNS
The URL can be pinged and it resolves to an IP address. I feel this message is misleading.
FWIW, I'm using Solace's Javascript API calling it from my Typescript code.
Below is code snippet. I've tried to remove irrelevant items such as the console logging. In short, it tests for a session already having been created, and if not, creates it using the Solace factory, then sets some event handlers which I think are irrelevant to this item
so I didn't include them. Because I don't catch any errors at connect() time, I presume it connected. Then when I try to send(), it suddenly is still waiting on the DNS. Or, at least, the error implies this.
class TopicPublisher {
private getSession() {
if (this.session == null) {
try {
this.log('Creating session for url=' + this.hosturl+' vpn='+this.vpn+' username='+this.username);
this.session = this.solace.SolclientFactory.createSession({
// solace.SessionProperties
url: this.hosturl,
vpnName: this.vpn,
userName: this.username,
password: this.pass,
});
// Set session event handlers
try {
this.session.connect();
} catch(error : any) {
this.log('Could not make connection to existing session. Error: '+error.toString());
this.session = null;
}
} catch (error: any) {
this.log(error.toString());
}
}
return this.session;
}
public publish(messageContent: any) {
var solaceMessage = this.getSolaceMessage(messageContent);
this.log('Publishing message "' + messageContent + '" to topic "' + this.topicName + '"...');
try {
// *************************
// This is where SEND fails
// *************************
this.getSession().send(solaceMessage);
this.log('Message published.');
} catch (error: any) {
this.log(error.toString());
}
};
}
An OperationError is thrown when you are attempting to execute a command on the session before it's actually up. What you can do here is only return this.session on session.on(solace.SessionEventCode.UP_NOTICE)
You can also see more info on this in the API docs and check out the note in the docs
Note: Before the session's state transitions to 'connected', a client
application cannot use the session; any attempt to call functions will
throw solace.OperationError.

Unable to catch CosmosException when token expired in Blazor WebAssembly

I am using Azure CosmosDB with Blazor WebAssembly (client-side).
I want to catch CosmosException When connection token expires, But not getting cosmos exception for that, (Null exception found)
I have also tried same code in console application, In that I am able to catch cosmos exception that showing token expired.
Code sample :
using (CosmosClient client = new CosmosClient(account, token))
{
Database db = null;
db = client.GetDatabase("databaseName");
Container orgContainer = client.GetContainer("databaseName","containerName");
try
{
ItemResponse<CosmosException> response = await orgContainer.ReadItemAsync<CosmosException>("test", new PartitionKey("test"));
var data = response.Resource;
}
catch(CosmosException ex)
{
}
catch(Exception ex)
{
}
}
Exception Details of Console Application
This is probably because the exception occurs outside the try block. Also, make sure you do not instantiate a new cosmos client on each request. This does not perform well. Use singleton and keep alive between requests.

Azure App Service Error 405 - The request could not be completed. (Method Not Allowed)

I'm working with Azure App Service .NET backend with a Xamarin.iOS app. I am able to successfully register a new user and I can see the user's details in the database. I have a custom ApiController, which handles the registration and the I'm able to save the details with a successful POST call.
However, when I try to log into the app, I get the following error:
{Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException: The request could not be completed. (Method Not Allowed)
Below is my code:
The RegistrationController in the backend which successfully makes a POST call
[MobileAppController]
[RoutePrefix("api/register")]
[AllowAnonymous]
public class RegisterController : ApiController
{
[HttpPost]
[Route("newuser")]
public HttpResponseMessage NewUser(RegistrationRequest request)
{
// Registration code in here
}
}
This is how I call this function on the client side:
public async Task<Result<UserProfile>> RegisterUser(RegistrationWrapper registrationrequest)
{
try
{
var registrationRequest = new JObject();
registrationRequest.Add("username", registrationrequest.username);
registrationRequest.Add("password", registrationrequest.password);
registrationRequest.Add("email", registrationrequest.email);
registrationRequest.Add("phone", registrationrequest.phone);
registrationRequest.Add("firstname", registrationrequest.firstname);
registrationRequest.Add("lastname", registrationrequest.lastname);
var result = await client.InvokeApiAsync("register/newuser", registrationRequest);
// Handle result here
}
catch (Exception ex)
{
return Result<UserProfile>.Failure(ex.Message + ex.StackTrace + ex.InnerException);
}
}
Custom AuthController which handles the login
This POST call fails with the error described above.
[MobileAppController]
[RoutePrefix("api/auth")]
public class AuthController : ApiController
{
public HttpResponseMessage Post(AuthenticationRequest credentials)
{
try
{
//Authentication code goes here
catch (Exception e)
{
Console.WriteLine("Ërror :" + e.Message);
Console.WriteLine(e.StackTrace);
return Request.CreateResponse(HttpStatusCode.InternalServerError, new
{
Stacktrace = e.StackTrace,
ErrorMessage = e.Message,
Credentials = credentials
});
}
}
How I invoke this function from the client side
async Task<Result<Account>> Login(string username, string password)
{
try
{
var credentials = new JObject();
credentials.Add("username", username);
credentials.Add("password", password);
var result = await client.InvokeApiAsync("auth", credentials);
//Handle result here
}
catch (Exception ex)
{
return Result<Account>.Failure(ex, ex.Message + ex.StackTrace);
}
}
}
I'm not sure why it's failing during the log in. Any ideas?
After trying tons of solutions found here on StackOverflow, the one that finally worked for me was this first answer found on a similar question.
It seems that the http POST call is redirected to https.
After enabling authentication on your App Service in the Azure portal, you need to change the url to https.
So I changed mine from this:
http//{my_site}.azurewebsites.net
To this:
https//{my_site}.azurewebsites.net
On the client side, and now used this new one to create my local sync tables.
Everything works as expected now.
The HTTP status code 405 is returned when an API endpoint is called with a wrong (Not Allowed) HTTP method. For example, if instead of a POST request the endpoint is called with a GET request.

IBM Connections Atom Profile Service

I am trying to get back a profile for myself but I only get back a successful http response...no data. This is the code I am using.
try {
RestClient restClient = new RestClient("https://apps.na.collabserv.com","my.email","my.password");
Response<AtomFeed> responseFeed = restClient.doGet("/profiles/atom/profileService.do").asAtomFeed();
System.out.println(responseFeed.getData().toXmlString());
} catch(Exception e) {
e.printStackTrace();
}
If I try to add a email= to the url I get a 403 forbidden return.
Not really sure what the issue is,
Thanks!

ServiceStack keep a long-live connection and send response asynchronously

I have a client app which monitors the changes in real-time by establishing a long-live HTTP connection to server.
In ASP.NET WebAPI, the server can take use PushStreamContent to keep the connection for a long time and send response once there is an update.
But in ServiceStack, seems there is no similar stuff.
I looked at the sample code of Different ways of returning an ImageStream
IStreamWriter.WriteTo method is only called once, and I can't use async IO operation to avoid blocking server thread.
Is there a way to send progressive response to client asynchronously?
here is sample code in WebAPI which does the job
public static async Task Monitor(Stream stream, HttpContent httpContent, TransportContext transportContext)
{
ConcurrentQueue<SessionChangeEvent> queue = new ConcurrentQueue<SessionChangeEvent>();
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
Action<SessionChangeEvent> callback = (evt) =>
{
queue.Enqueue(evt);
tcs.TrySetResult(null);
};
OnSessionChanged += callback;
try
{
using (StreamWriter sw = new StreamWriter(stream, new UTF8Encoding(false)))
{
await sw.WriteLineAsync(string.Empty);
await sw.FlushAsync();
await stream.FlushAsync();
for (; ; )
{
Task task = tcs.Task;
await Task.WhenAny(task, Task.Delay(15000));
if (task.Status == TaskStatus.RanToCompletion)
{
tcs = new TaskCompletionSource<object>();
SessionChangeEvent e;
while (queue.TryDequeue(out e))
{
string json = JsonConvert.SerializeObject(e);
await sw.WriteLineAsync(json);
}
task.Dispose();
}
else
{
// write an empty line to keep the connection alive
await sw.WriteLineAsync(string.Empty);
}
await sw.FlushAsync();
await stream.FlushAsync();
}
}
}
catch (CommunicationException ce)
{
}
finally
{
OnSessionChanged -= callback;
}
}
Writing to a long-running connection is exactly what Server Events does. You can look at the implementation for ServerEventsHandler or ServerEventsHeartbeatHandler to see it's implemented in ServiceStack.
Basically it just uses a custom ASP.NET IHttpAsyncHandler which can be registered at the start of ServiceStack's Request Pipeline with:
appHost.RawHttpHandlers.Add(req => req.PathInfo.EndsWith("/my-stream")
? new MyStreamHttpHandler()
: null);
Where MyStreamHttpHandler is a custom HttpAsyncTaskHandler, e.g:
public class MyStreamHttpHandler : HttpAsyncTaskHandler
{
public override bool RunAsAsync() { return true; }
public override Task ProcessRequestAsync(
IRequest req, IResponse res, string operationName)
{
//Write any custom request filters and registered headers
if (HostContext.ApplyCustomHandlerRequestFilters(req, res))
return EmptyTask;
res.ApplyGlobalResponseHeaders();
//Write to response output stream here, either by:
res.OuputStream.Write(...);
//or if need access to write to underlying ASP.NET Response
var aspRes = (HttpResponseBase)res.OriginalResponse;
aspRes.OutputStream...
//After you've finished end the request with
res.EndHttpHandlerRequest(skipHeaders: true);
return EmptyTask;
}
}
The ApplyCustomHandlerRequestFilters() and ApplyGlobalResponseHeaders() at the start gives other plugins a chance to validate/terminate the request or add any HTTP Headers (e.g. CorsFeature).
Have a look at ServerEvents. If I understood you right, this is what you are looking for.

Resources