I have created two methods in my BaseViewModel (MVVMLight App) to perform any async code with some logic:
public async Task PerformOperation(Func<Task> action)
{
IsBusy = true;
try
{
await action?.Invoke();
}
catch(Exception ex)
{
// logging is here
}
finally
{
IsBusy = false;
}
}
public async Task PerformOperation(params Operation[] actions)
{
IsBusy = true;
MultipleOperatrions = true;
OperationStatuses = new ObservableCollection<OperationStatus>();
try
{
foreach(var action in actions)
{
var status = new OperationStatus() { StatusText = action.StatusText };
OperationStatuses.Add(status);
try
{
await action?.AsyncAction();
status.Success = true;
}
catch
{
status.Success = false;
}
finally
{
status.IsFinished = true;
}
}
}
catch (Exception ex)
{
// logging is here
}
finally
{
await Task.Delay(1000);
IsBusy = false;
MultipleOperatrions = false;
OperationStatuses = new ObservableCollection<OperationStatus>();
}
}
My models:
public class Operation
{
public Func<Task> AsyncAction { get; private set; }
public string StatusText { get; private set; }
public Operation(Func<Task> action, string statusText)
{
AsyncAction = action;
StatusText = statusText;
}
}
My code of calling the methods in the view model:
...
private IAsyncCommand _buildCommand;
public IAsyncCommand BuildCommand => _buildCommand ?? (_buildCommand = new AsyncCommand(Build));
#endregion
#region Methods
public async Task Build()
{
// IT WORKS
// this method is used for performing only a single operation
// await PerformOperation(async () => { await Task.Delay(3000); });
// IT CRASHES THE APP
// for many tasks
await PerformOperation(new Operation(async () => { await Task.Delay(3000); }, "Preparing..."));
}
...
So, if I call PerformOperation to call just only a single method - it works fine. But it doesn't for the method of performing of several operations - the application just crashes without any exception or messages. I subscribed in App.cs to UnhandledException event to catch it but the app just crashes.
Related
I am trying to add a middleware so that transaction begins at the beginning of the request and commits or rollbacks depending on the situation. This is my middleware:
public class TransactionPerRequestMiddleware
{
private readonly RequestDelegate next_;
public TransactionPerRequestMiddleware(RequestDelegate next)
{
next_ = next;
}
public async Task Invoke(HttpContext context, AppDbContext dbContext)
{
var is_everything_ok = true;
var transaction = dbContext.Database.BeginTransaction(
System.Data.IsolationLevel.ReadCommitted);
if (context.Response.StatusCode != 200 && is_everything_ok)
{
is_everything_ok = false;
}
await next_.Invoke(context);
if ((context.Response.StatusCode == 200 ||
context.Response.StatusCode == 302) && is_everything_ok)
{
transaction.Commit();
}
else
{
transaction.Rollback();
}
}
}
I registered the above middleware in Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseMiddleware<TransactionPerRequestMiddleware>();
}
I have a method in service which performs two database operations one after another.
public void method()
{
databaseOperation1();
databaseOperation2();
}
If exception occurs in databaseOperation2() , databaseOperation1() is not rolling back currently. I am trying to implement Unit Of Work for each web request.
Thanks in advance.
This is my custom middleware class for exception. I want to handle global exceptions.
public class CustomExceptionMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public CustomExceptionMiddleware(RequestDelegate next, ILogger<CustomExceptionMiddleware> logger)
{
_logger = logger;
_next = next;
}
public async Task Invoke(HttpContext httpContext)
{
try
{
await _next(httpContext);
}catch (Exception e)
{
await HandleExceptionAsync(httpContext, e);
}
}
private Task HandleExceptionAsync(HttpContext context, Exception exception)
{
var code = HttpStatusCode.InternalServerError;
if(exception is KeyNotFoundException)
{
code = HttpStatusCode.NotFound;
_logger.LogInformation("Exception happend. Exception type: " + exception.GetType().ToString(), new object[0]);
}
else if (exception is UnauthorizedAccessException)
{
code = HttpStatusCode.Unauthorized;
_logger.LogInformation("Exception happend. Exception type: " + exception.GetType().ToString(), new object[0]);
}
else
{
code = HttpStatusCode.BadRequest;
_logger.LogInformation("Exception happend. Bad request ", new object[0]);
}
var result = JsonConvert.SerializeObject(new { error = exception.Message });
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int) code;
//context.ExceptionHandled = true;
return context.Response.WriteAsync(result);
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class CustomExceptionMiddlewareExtensions
{
public static IApplicationBuilder UseCustomExceptionMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<CustomExceptionMiddleware>();
}
}
I add in my Startup.cs
app.UseCustomExceptionMiddleware();
I don't get logging information that I'm trying to log, and it doesn't throw any exception. What am I missing? Should I throw an exception in a controller class?
I am trying to update the data in my secondary tile using a background task. It gets updated when I select my background task from the lifecycle events dropdown. However it doesn't work automatically. Does it mean that my SystemTrigger is not getting fired? Please help.
Here is my code:
public static void CheckIfBackgroundTaskExist()
{
if (BackgroundTaskRegistration.AllTasks.Count < 1)
{
RegisterBackgroundTask();
}
}
public static void RegisterBackgroundTask()
{
BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
builder.Name = "SecondaryTileUpdate";
builder.TaskEntryPoint = "BackgroundTaskLiveTile.SecondaryTileUpdater";
//IBackgroundTrigger trigger = new MaintenanceTrigger(15, false);
IBackgroundTrigger trigger = new SystemTrigger(SystemTriggerType.TimeZoneChange, false);
builder.SetTrigger(trigger);
IBackgroundTaskRegistration task = builder.Register();
}
public async void Run(IBackgroundTaskInstance taskInstance)
{
//HERE: request a deferral
var deferral = taskInstance.GetDeferral();
var list = await SecondaryTile.FindAllAsync();
foreach (SecondaryTile liveTile in list)
{
HttpClient client = new HttpClient();
var response = await client.GetAsync(url, HttpCompletionOption.ResponseContentRead);
if (!response.IsSuccessStatusCode)
{
//
}
if (response != null)
{
string content = await response.Content.ReadAsStringAsync();
try
{
MyProperty= JsonConvert.DeserializeObject<MyClass>(content);
}
catch
{
//MessageBox.Show("Unable to retrieve data");
}
}
// Update Secondary Tiles
if (liveTile.TileId == "MySecondaryTileId")
{
await UpdateMyTile();
}
}
}
I am developing a windows phone 8 application to access sky drive. I am getting following error when I call LoginAsync() method-
An exception of type 'Microsoft.Live.LiveAuthException' occurred in mscorlib.ni.dll but was not handled in user code
using System;
using System.Windows;
using Microsoft.Phone.Controls;
using Microsoft.Live;
namespace SkyDriveApp
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
LiveConnectClient client;
public MainPage()
{
InitializeComponent();
}
public async void Auth()
{
string clientId = "My_client_id";
LiveAuthClient auth = new LiveAuthClient(clientId);
// var result = await auth.InitializeAsync(new[] { "wl.basic", "wl.signin", "wl.skydrive_update" });
var result = await auth.LoginAsync(new[] { "wl.basic", "wl.signin", "wl.skydrive_update" });
if (result.Status == LiveConnectSessionStatus.Connected)
{
client = new LiveConnectClient(result.Session);
tbMessage.Text = "Connected!";
}
}
private void btnLogin_SessionChanged(object sender, Microsoft.Live.Controls.LiveConnectSessionChangedEventArgs e)
{
Auth();
}
}
}
I see that you are using provided login buton, try this:
In xaml:
<live:SignInButton Name="skyBtn" ClientId="your client ID" Scopes="wl.signin wl.skydrive wl.skydrive_update" Branding="Skydrive" TextType="Login"/>
In code behind:
private void skyBtn_SessionChanged(object sender, Microsoft.Live.Controls.LiveConnectSessionChangedEventArgs e)
{
if (e.Status == LiveConnectSessionStatus.Connected)
{
session = e.Session;
client = new LiveConnectClient(session);
tbMessage.Text = "Connected!";
}
else tbMessage.Text = "Not Connected!";
if (e.Error != null)
{
tbMessage.Text = "Not Connected!";
Dispatcher.BeginInvoke(() =>
{
MessageBox.Show(e.Error.Message);
});
}
}
I am trying to post some data to our webservice(written in c#) and get the response. The response is in JSON format.
I am using the Blackberry Code Sample which is BlockingSenderDestination Sample. When I request a page it returns with no problem. But when I send my data to our webservice it does not return anything.
The code part that I added is :
ByteMessage myMsg = bsd.createByteMessage();
//myMsg.setStringPayload("I love my BlackBerry device!");
myMsg.setMessageProperty("querytpe","myspecialkey");//here is my post data
myMsg.setMessageProperty("uname","myusername");
myMsg.setMessageProperty("pass","password");
((HttpMessage) myMsg).setMethod(HttpMessage.POST);
// Send message and wait for response myMsg
response = bsd.sendReceive(myMsg);
What am i doing wrong? And what is the alternatives or more efficients way to do Post with Blackberry.
Regards.
Here is my whole code:
class BlockingSenderSample extends MainScreen implements FieldChangeListener {
ButtonField _btnBlock = new ButtonField(Field.FIELD_HCENTER);
private static UiApplication _app = UiApplication.getUiApplication();
private String _result;
public BlockingSenderSample()
{
_btnBlock.setChangeListener(this);
_btnBlock.setLabel("Fetch page");
add(_btnBlock);
}
public void fieldChanged(Field button, int unused)
{
if(button == _btnBlock)
{
Thread t = new Thread(new Runnable()
{
public void run()
{
Message response = null;
String uriStr = "http://192.168.1.250/mobileServiceOrjinal.aspx"; //our webservice address
//String uriStr = "http://www.blackberry.com";
BlockingSenderDestination bsd = null;
try
{
bsd = (BlockingSenderDestination)
DestinationFactory.getSenderDestination
("name", URI.create(uriStr));//name for context is name. is it true?
if(bsd == null)
{
bsd =
DestinationFactory.createBlockingSenderDestination
(new Context("ender"),
URI.create(uriStr)
);
}
//Dialog.inform( "1" );
ByteMessage myMsg = bsd.createByteMessage();
//myMsg.setStringPayload("I love my BlackBerry device!");
myMsg.setMessageProperty("querytpe","myspecialkey");//here is my post data
myMsg.setMessageProperty("uname","myusername");
myMsg.setMessageProperty("pass","password");
((HttpMessage) myMsg).setMethod(HttpMessage.POST);
// Send message and wait for response myMsg
response = bsd.sendReceive(myMsg);
if(response != null)
{
BSDResponse(response);
}
}
catch(Exception e)
{
//Dialog.inform( "ex" );
// process the error
}
finally
{
if(bsd != null)
{
bsd.release();
}
}
}
});
t.start();
}
}
private void BSDResponse(Message msg)
{
if (msg instanceof ByteMessage)
{
ByteMessage reply = (ByteMessage) msg;
_result = (String) reply.getStringPayload();
} else if(msg instanceof StreamMessage)
{
StreamMessage reply = (StreamMessage) msg;
InputStream is = reply.getStreamPayload();
byte[] data = null;
try {
data = net.rim.device.api.io.IOUtilities.streamToBytes(is);
} catch (IOException e) {
// process the error
}
if(data != null)
{
_result = new String(data);
}
}
_app.invokeLater(new Runnable() {
public void run() {
_app.pushScreen(new HTTPOutputScreen(_result));
}
});
}
}
..
class HTTPOutputScreen extends MainScreen
{
RichTextField _rtfOutput = new RichTextField();
public HTTPOutputScreen(String message)
{
_rtfOutput.setText("Retrieving data. Please wait...");
add(_rtfOutput);
showContents(message);
}
// After the data has been retrieved, display it
public void showContents(final String result)
{
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
_rtfOutput.setText(result);
}
});
}
}
HttpMessage does not extend ByteMessage so when you do:
((HttpMessage) myMsg).setMethod(HttpMessage.POST);
it throws a ClassCastException. Here's a rough outline of what I would do instead. Note that this is just example code, I'm ignoring exceptions and such.
//Note: the URL will need to be appended with appropriate connection settings
HttpConnection httpConn = (HttpConnection) Connector.open(url);
httpConn.setRequestMethod(HttpConnection.POST);
OutputStream out = httpConn.openOutputStream();
out.write(<YOUR DATA HERE>);
out.flush();
out.close();
InputStream in = httpConn.openInputStream();
//Read in the input stream if you want to get the response from the server
if(httpConn.getResponseCode() != HttpConnection.OK)
{
//Do error handling here.
}