In a windows 8.1 app, I am trying to make a toast notification using the code:
public class ToastController
{
#region Public Methods and Operators
/// <summary>
/// The show.
/// </summary>
/// <param name="message">
/// The message.
/// </param>
public void Show(string message)
{
// A single string wrapped across three lines of text.
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText01);
toastXml.GetElementsByTagName("text").First().InnerText = message;
var toast = new ToastNotification(toastXml);
ToastNotifier notifier = ToastNotificationManager.CreateToastNotifier();
notifier.Show(toast);
}
#endregion
}
But I cannot see any toast messages at all when the Show() method is invoked. Am I missing anything?
Update: I have been able to get the toast message to show when debugging the windows app using Local Machine. However, the toast message is still not shown when launch in Simulator. Help please.
It turns out that I need to set up my app to enable toast notification:
<VisualElements
...
ToastCapable="true">
</VisualElements>
https://msdn.microsoft.com/en-us/library/windows/apps/hh781238.aspx
Related
I am using Serilog HTTP sink for logging to Logstash in my .Net Core Project. In startup.cs I have following code to enable serilog.
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.WriteTo.Http("http://mylogstashhost.com:5000").Enrich.WithProperty("user", "xxx").Enrich.WithProperty("serviceName", "yyy")
.MinimumLevel.Warning()
.CreateLogger();
And this code sends logs to the given http address. I can see on fiddler that following json is being posted to the logstash and logstash returns "ok" message.
{"events":[{"Timestamp":"2018-10-19T18:16:27.6561159+01:00","Level":"Warning","MessageTemplate":"abc","RenderedMessage":"abc","user":"xxx","serviceName":"yyy","Properties":{"ActionId":"b313b8ed-0baf-4d75-a6e2-f0dbcb941f67","ActionName":"MyProject.Controllers.HomeController.Index","RequestId":"0HLHLQMV1EBCJ:00000003","RequestPath":"/"}}]}
But when I checked on Kibana, I can not see this log. I tried to figure out what causes it and i realized that if I send the json as following format I can see the Log.
{"Timestamp":"2018-10-19T18:16:27.6561159+01:00","Level":"Warning","MessageTemplate":"abc","RenderedMessage":"abc","user":"xxx","serviceName":"yyy","Properties":{"ActionId":"b313b8ed-0baf-4d75-a6e2-f0dbcb941f67","ActionName":"MyProject.Controllers.HomeController.Index" ,"RequestId":"0HLHLQMV1EBCJ:00000003","RequestPath":"/"}}
So Logstash doesnt like the event to be in Events{} and also it wants "user" and "ServiceName" tags out of "Properties". Is there a way to format my Json like this?
Ok after some research and help, basically to achieve custom formats, one should implement interfaces like ITextFormatter, BatchFormatter etc.
I could achieve the format i need, by modifying ArrayBatchFormatter a little:
public class MyFormat : BatchFormatter
{
/// <summary>
/// Initializes a new instance of the <see cref="ArrayBatchFormatter"/> class.
/// </summary>
/// <param name="eventBodyLimitBytes">
/// The maximum size, in bytes, that the JSON representation of an event may take before it
/// is dropped rather than being sent to the server. Specify null for no limit. Default
/// value is 256 KB.
/// </param>
public MyFormat(long? eventBodyLimitBytes = 256 * 1024): base(eventBodyLimitBytes)
{
}
/// <summary>
/// Format the log events into a payload.
/// </summary>
/// <param name="logEvents">
/// The events to format.
/// </param>
/// <param name="output">
/// The payload to send over the network.
/// </param>
public override void Format(IEnumerable<string> logEvents, TextWriter output)
{
if (logEvents == null) throw new ArgumentNullException(nameof(logEvents));
if (output == null) throw new ArgumentNullException(nameof(output));
// Abort if sequence of log events is empty
if (!logEvents.Any())
{
return;
}
output.Write("[");
var delimStart = string.Empty;
foreach (var logEvent in logEvents)
{
if (string.IsNullOrWhiteSpace(logEvent))
{
continue;
}
int index = logEvent.IndexOf("{");
string adjustedString = "{\"user\":\"xxx\",\"serviceName\" : \"yyy\"," + logEvent.Substring(1);
if (CheckEventBodySize(adjustedString))
{
output.Write(delimStart);
output.Write(adjustedString);
delimStart = ",";
}
}
output.Write("]");
}
}
I would like to extend #nooaa answer with this variation. Instead of manipulating the string to add new objects, I would suggest using Newtonsoft.Json.Linq. This way you can append, add or remove existing properties of the object itself.
Also, instead of doing output.write after each event, you can combine all the output from the events and do output.write once at the end (a bit of performance)
public override void Format(IEnumerable<string> logEvents, TextWriter output)
{
if (logEvents == null) throw new ArgumentNullException(nameof(logEvents));
if (output == null) throw new ArgumentNullException(nameof(output));
// Abort if sequence of log events is empty
if (!logEvents.Any())
{
return;
}
List<object> updatedEvents = new List<object>();
foreach (string logEvent in logEvents)
{
if (string.IsNullOrWhiteSpace(logEvent))
{
continue;
}
// Parse the log event
var obj = JObject.Parse(logEvent);
// Add New entries
obj["#source_host"] = obj["fields"]["MachineName"].Value<string>().ToLower();
// Remove any entries you are not interested in
((JObject)obj["fields"]).Remove("MachineName");
// Default tags for any log that goes out of your app.
obj["#tags"] = new JArray() { "appName", "api" };
// Additional tags from end points (custom based on routes)
if (obj["fields"]["tags"] != null)
{
((JArray)obj["#tags"]).Merge((JArray)obj["fields"]["tags"]);
((JObject)obj["fields"]).Remove("tags");
}
updatedEvents.Add(obj);
}
output.Write(JsonConvert.SerializeObject(updatedEvents));
}
Update
Release Notes v8.0.0
With latest release, you dont override the method anymore.
namespace Serilog.Sinks.Http.BatchFormatters {
public class MyCustomFormatter: IBatchFormatter {
public void Format(IEnumerable<string> logEvents, TextWriter output) {
...
}
}
}
you don't provide any Contructors for it either.
Add queueLimitBytes along with batchFormatter and textFormatter
WriteTo.Http(new Uri(),
batchFormatter: new MyCustomFormatter(),
queueLimitBytes: 50 * ByteSize.MB,
textFormatter: new ElasticsearchJsonFormatter());
I am using the project from https://github.com/microsoft/cognitive-vision-windows, I am able to upload image but the OCR is unable to be processed. It just stays on "Performing OCR..." Same for other functions except "Recognize Handwriting Text"
//
// Perform OCR on the given url
//
Log("Calling VisionServiceClient.RecognizeTextAsync()...");
OcrResults ocrResult = await VisionServiceClient.RecognizeTextAsync(imageUrl, language);
return ocrResult;
// -----------------------------------------------------------------------
// KEY SAMPLE CODE ENDS HERE
// -----------------------------------------------------------------------
}
/// <summary>
/// Perform the work for this scenario
/// </summary>
/// <param name="imageUri">The URI of the image to run against the scenario</param>
/// <param name="upload">Upload the image to Project Oxford if [true]; submit the Uri as a remote url if [false];</param>
/// <returns></returns>
protected override async Task DoWork(Uri imageUri, bool upload)
{
_status.Text = "Performing OCR...";
string languageCode = (languageComboBox.SelectedItem as RecognizeLanguage).ShortCode;
//
// Either upload an image, or supply a url
//
OcrResults ocrResult;
if (upload)
{
ocrResult = await UploadAndRecognizeImage(imageUri.LocalPath, languageCode);
}
else
{
ocrResult = await RecognizeUrl(imageUri.AbsoluteUri, languageCode);
}
_status.Text = "OCR Done";
//
// Log analysis result in the log window
//
Log("");
Log("OCR Result:");
LogOcrResults(ocrResult);
}
I am working on a Windows Phone 8.1 application which registers a background task timer trigger for hourly operation. So essentially, the background task wake up every 60 minutes and does some operation.
My question is that, when the background task is in progress, if the user wakes up the application, is there a way that we can show the user what is happening in the background task process?
I understand that they are two different processes. I am using a Silverlight 8.1 project for the foreground application and a managed windows runtime project for the background task. I am registering the background task using the silverlight application but i am in a dark now thinking about how to create a communication bridge between these two processes.
Any clues ? Is this even possible ?
Here are some ideas (or info) about communication between the app and its background tasks.
You could use the Progress and Completed events of the IBackgroundTaskRegistration object. You can get that object using BackgroundTaskRegistration.AllTasks - this property returns the list of background tasks registered by the app. Each time the app runs, you'll have to subscribe to these events.
From the background task you can set the Progress property of the IBackgroundTaskInstance object to some UInt32 value, and the app will receive the event. Maybe you can encode what you need in that number. For example: 1 means that the task is initializing, 2 - the task is doing WorkA, and so on...
Both processess have access to the same files, so maybe you can use that for something.
Use Mutex to sync the execution of code between the two processes.
That's all I can think of right now. I hope it helps.
P.S. I haven't really tried those events, but they seem like they might be useful.
I have already did some POC on commnication b/w Background Task and the app it self. I was using windows universal app but it will work in silverlight phone app too.
private IBackgroundTaskRegistration timeZoonChangeTask;
public MainPage()
{
this.InitializeComponent();
NavigationHelper nvHelper = new NavigationHelper(this);
IReadOnlyDictionary<Guid, IBackgroundTaskRegistration> allTasks = BackgroundTaskRegistration.AllTasks;
if (allTasks.Count() == 0)
{
lblMessage.Text = "No Task is registered at the moment";
}
else//Task already registered
{
lblMessage.Text = "Timezoon Task is registered";
this.GetTask();
}
}
/// <summary>
/// Time zoon task registration.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private async void Button_Click(object sender, RoutedEventArgs e)
{
await BackgroundExecutionManager.RequestAccessAsync();
BackgroundTaskBuilder taskBuilder = new BackgroundTaskBuilder();
taskBuilder.Name = "MyBackgroundTask";
SystemTrigger systemTrigger = new SystemTrigger(SystemTriggerType.TimeZoneChange, false);
taskBuilder.SetTrigger(systemTrigger);
taskBuilder.TaskEntryPoint = typeof(MyBackgroundTask.TheTask).FullName;
taskBuilder.Register();
lblMessage.Text = "Timezoon Task is registered";
this.GetTask();
}
/// Get registered task and handel completed and progress changed events.
/// </summary>
private void GetTask()
{
var timeZoonChangeTask = BackgroundTaskRegistration.AllTasks.Values.FirstOrDefault();
timeZoonChangeTask.Completed += timeZoonChangeTask_Completed;
timeZoonChangeTask.Progress += timeZoonChangeTask_Progress;
}
/// <summary>
/// raised when task progress is changed app is active
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
void timeZoonChangeTask_Progress(BackgroundTaskRegistration sender, BackgroundTaskProgressEventArgs args)
{
this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
lblTaskProgress.Text = args.Progress.ToString() + "%";
recProgress.Width = 400 * (double.Parse(args.Progress.ToString()) / 100);
});
//this.Dispatcher.BeginInvoke(() =>
// {
// });
}
/// <summary>
/// Raised when task is completed and app is forground
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
void timeZoonChangeTask_Completed(BackgroundTaskRegistration sender, BackgroundTaskCompletedEventArgs args)
{
this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
lblMessage.Text = "Task Excecution is completed";
});
}
and below is the task class
public sealed class TheTask:IBackgroundTask
{
public async void Run(IBackgroundTaskInstance taskInstance)
{
///Get Deferral if we are doing aysnc work. otherwise it will not work.
//Always get deferral it will not harm.
var deferral = taskInstance.GetDeferral();
taskInstance.Canceled += taskInstance_Canceled;
for (uint i = 0; i < 10; i++)
{
taskInstance.Progress = i + 10;
await Task.Delay(2000);
}
//Write last run time somewhere so the gorground app know that at when last time this backgournd app ran.
///Set this progress to show the progesss on the forground app if it is running and you want to show it.
taskInstance.Progress = 0;
deferral.Complete();
}
void taskInstance_Canceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
}
}
i use RequestFactory for communicating with server and RequestFactoryEditorDriver on the client side. So editing workflow looks like such way. Create new proxy for editing:
RequestContext reqCtx = clientFactory.getRequestFactory().Request();
UserAndAccountProxy userAndAccountProxy = reqCtx.create(UserAndAccountProxy.class);
reqCtx.saveAndReturnProfileAndAccount(userAndAccountProxy).to(
new Receiver<UserAndAccountProxy>() {
#Override
public void onSuccess(UserAndAccountProxy response) {
...
}
#Override
public void onFailure(ServerFailure error) {
...
}}
And Save button click handling:
RequestContext reqCtx = view.getEditorDriver().flush();
reqCtx.fire();
On server side saveAndReturnProfileAndAccount method can throw exceptions on persisting, which i can handle in onFailure method. After that if I create new proxy with new request context and pass it to my editor all fields will be blanked.
So what is proper way to execute request and if something goes wrong use data that user allready fill or maybe I made mistake in my editing worklow?
So, I think, I found solution. I made changes to function, which create RequestContext:
private void edit(MyProxy proxy) {
RequestContext reqCtx = clientFactory.getRequestFactory().Request();
if (proxy == null) {
// create proxy first time
proxy = reqCtx.create(UserAndAccountProxy.class);
} else {
// create immutable copy
proxy = reqCtx.edit(proxy);
}
final UserAndAccountProxy tmp = proxy;
reqCtx.saveAndReturnMyProxy(proxy).to(new Receiver<MyProxy>() {
#Override
public void onFailure(ServerFailure error) {
eventBus.showErrorInformation(error.getMessage());
//recursive call with already filled proxy
edit(tmp);
}
#Override
public void onSuccess(UserAndAccountProxy response) {
eventBus.showInformation("It`s ok!");
eventBus.goToMainPage(null);
}
});
// start editing with editor
getView().onEdit(tmp, reqCtx);
}
When we start editing proxy function edit need to bee called with null argument and new clean proxy will be created. After that we start edit it with Editor. On Save button click we execute request to server. If it ends with success - we open another page. If request ends with error, we create new immutable copy ant push it to editor.
I'm nearly done with a big NHibernate upgrade that ended up also being a Castle upgrade. I'm nearly there except the ASP.NET website won't run, because I'm getting an error where ServiceSecurityContext.Current is null. I could be wrong (I'm still new to Castle) but I think it has something to do with the change I made to registering the WCF facility.
Previously (in a class called ServiceLocator.cs) there was code like this:
/// <summary>
/// Register the WindsorServiceHostFactory with the container
/// </summary>
public static void RegisterWcfServer()
{
RegisterWcfFacility();
DefaultServiceHostFactory.RegisterContainer(Container.Kernel);
}
where the RegisterWcfFacility() method looked like this:
private static void RegisterWcfFacility()
{
IFacility[] facilities = Container.Kernel.GetFacilities();
bool hasWcfFacility = false;
foreach (IFacility facility in facilities)
{
if (facility.GetType() != typeof (WcfFacility))
continue;
hasWcfFacility = true;
break;
}
if (!hasWcfFacility)
Container.AddFacility<WcfFacility>();
}
Subsequently I've changed it to this (because I was trying to get it to compile obviously, and the DefaultServiceHostFactory no longer has a "RegisterContainer" method):
/// <summary>
/// Register the WindsorServiceHostFactory with the container
/// </summary>
public static void RegisterWcfServer()
{
RegisterWcfFacility();
// see: http://stackoverflow.com/questions/9729395/castlewindsor-3-0-and-defaultservicehostfactory-registercontainer
// obsolete:
//DefaultServiceHostFactory.RegisterContainer(Container.Kernel);
Container.Register(Component.For<DefaultServiceHostFactory>());
}
And my new version of "RegisterWcfFacility()" looks like this:
private static void RegisterWcfFacility()
{
var facilities = Container.Kernel.GetFacilities();
var hasWcfFacility = facilities.Any(facility => facility.GetType() == typeof (WcfFacility));
if (!hasWcfFacility)
Container.AddFacility<WcfFacility>();
}
I'm just posting this mainly to ask things like: am I completely barking up the wrong tree? Is the way I'm registering this facility legitimate? Could any of this explain why my ServiceSecurityContext.Current is null? (and yes I have seen this):
https://groups.google.com/forum/#!topic/castle-project-devel/VOQKW4XlvLM%5B1-25%5D
thanks for any advice. Cheers, -Dave
I just had the same problem and found the answer here. Turns out you just an initialise class in the folder App_Code that looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Castle.Windsor;
using Castle.Facilities.WcfIntegration;
namespace YourNamespace
{
public static class InitialiseService
{
public static void AppInitialize()
{
var container = new WindsorContainer();
container.AddFacility<WcfFacility>();
}
}
}
Of course this relies on the WCF Castle Facility being installed from the package manager via:
install-package Castle.WcfIntegrationFacility
Hope this helps :)