Creare App per Windows Phone 8


Oggi è stato pubblicato il libro di Enrico Rossini Creare App per Windows Phone 8 Concetti di base.

Nel mercato degli smartphone è arrivato da qualche tempo il nuovo sistema operativo di Microsoft, Windows Phone, che rappresenta un taglio netto con il passato: nuova architettura, nuova user experience, nuova grafica e anche nuovi strumenti di sviluppo. Con questo libro, partendo dalle basi fino ad arrivare agli aspetti più avanzati, scopriamo tutte le caratteristiche della piattaforma e quali sono gli strumenti che abbiamo a disposizione per creare applicazioni originali e innovative. Dai sensori (accelerometro, GPS, NFC ecc.) alla rete, passando per notifiche, tile e accesso ai dati. Il libro è basato sulla versione più recente della piattaforma, Windows Phone 8 che, rispetto alla release originale, ha portato a un profondo rinnovamento dell’architettura e ha introdotto moltissime novità sia per gli utenti sia per gli sviluppatori.

In questo primo volume si affrontano tutti i più importanti aspetti della programmazione con Visual Studio nella versione 2012 o 2013 fino ad utilizzare tutti i componenti base messi a disposizione e l'utilizzo del Windows Phone Toolkit. I concetti qui illustrati possono essere utilizzati per Windows Phone 8, Windows Phone 8.1 e Windows 8.

Creare App per Windows Phone 8

Oggi è stato pubblicato il libro di Enrico Rossini Creare App per Windows Phone 8 Concetti di base.

Nel mercato degli smartphone è arrivato da qualche tempo il nuovo sistema operativo di Microsoft, Windows Phone, che rappresenta un taglio netto con il passato: nuova architettura, nuova user experience, nuova grafica e anche nuovi strumenti di sviluppo. Con questo libro, partendo dalle basi fino ad arrivare agli aspetti più avanzati, scopriamo tutte le caratteristiche della piattaforma e quali sono gli strumenti che abbiamo a disposizione per creare applicazioni originali e innovative. Dai sensori (accelerometro, GPS, NFC ecc.) alla rete, passando per notifiche, tile e accesso ai dati. Il libro è basato sulla versione più recente della piattaforma, Windows Phone 8 che, rispetto alla release originale, ha portato a un profondo rinnovamento dell’architettura e ha introdotto moltissime novità sia per gli utenti sia per gli sviluppatori.

In questo primo volume si affrontano tutti i più importanti aspetti della programmazione con Visual Studio nella versione 2012 o 2013 fino ad utilizzare tutti i componenti base messi a disposizione e l'utilizzo del Windows Phone Toolkit. I concetti qui illustrati possono essere utilizzati per Windows Phone 8, Windows Phone 8.1 e Windows 8.

Serving WebP images with ASP.NET MVC

Speed is a feature and one thing that can slow down web apps is clients waiting to download images. To speed up image downloads and conserve bandwidth, the good folks of Google have come up with a new image format called WebP (“weppy”). WebP images are around 25% smaller in size than equivalent images encoded with JPEG and PNG (WebP supports both lossy and lossless compression) with no worse perceived quality.

This blog post shows how to dynamically serve WebP-encoded images from ASP.NET to clients that support the new format.

One not-so-great way of doing this is to serve different HTML depending on whether clients supports WebP or not, as described in this blog post. As an example, clients supporting WebP would get HTML with <img src="image.webp"/> while other clients would get <img src="image.jpeg"/>. The reason this sucks is that the same HTML cannot be served to all clients, making caching harder. It will also tend to pollute your view code with concerns about what image formats are supported by browser we’re rendering for right now.

Instead, images in our solution will only ever have one url and the content-type of responses depend on the capabilities of the client sending the request: Browsers that support WebP get image/webp and the rest get image/jpeg.

I’ll first go through creating WebP-encoded images in C#, then tackle the challenge of detecting browser image support and round out the post by discussing implications for CDN use.

Serving WebP with ASP.NET MVC

For the purposes of this article, we’ll assume that we want to serve images from an URI like /images/:id where :id is some unique id of the image requested. The id can be used to fetch a canonical encoding of the image, either from a file system, a database or some other backing store. In the code I wrote to use this, the images are stored in a database. Once fetched from the backing store, the image is re-sized as desired, re-encoded and served to the client.

At this point, some readers are probably in uproar: “Doing on-the-fly image fetching and manipulation is wasteful and slow” they scream. That’s not really the case though, and even if it were, the results can be cached on first request and then served quickly.

Assume we have an Image class and method GetImage(int id) to retrieve images:

private class Image
{
public int Id { get; set; }
public DateTime UpdateAt { get; set; }
public byte[] ImageBytes { get; set; }
}

We’ll now use the managed API from ImageResizer to resize the image to the desired size and then re-encode the result to WebP using Noesis.Drawing.Imaging.WebP.dll (no NuGet package, unfortunately).

public ActionResult Show(int imageId)
{
var image = GetImage(imageId);

var resizedImageStream = new MemoryStream();
ImageBuilder.Current.Build(image.ImageBytes, resizedImageStream, new ResizeSettings
{
Width = 500,
Height = 500,
Mode = FitMode.Crop,
Anchor = System.Drawing.ContentAlignment.MiddleCenter,
Scale = ScaleMode.Both,
});

var resultStream = new MemoryStream();
WebPFormat.SaveToStream(resultStream, new SD.Bitmap(resizedImageStream));
resultStream.Seek(0, SeekOrigin.Begin);

return new FileContentResult(resultStream.ToArray(), "image/webp");
}

System.Drawing is referenced using using SD = System.Drawing;. The controller action above is fully functional and can serve up sparkling new WebP-formatted images.


Browser support


Next up is figuring out whether the browser requesting an image actually supports WebP, and if it doesn’t, respond with JPEG. Luckily, this doesn’t involve going back to the bad old days of user-agent sniffing. Modern browsers that support WebP (such as Chrome and Opera) send image/webp in the accept header to indicate support. Ironically given that Google came up with WebP, the Chrome developers took a lot of convincing to set that header in requests, fearing request size bloat. Even now, Chrome only advertises webp support for requests that it thinks is for images. In fact, this is another reason the “different-HTML” approach mentioned in the intro won’t work: Chrome doesn’t advertise WebP support for requests for HTML.


To determine what content encoding to use, we inspect Request.AcceptTypes. The resizing code is unchanged, while the response is generated like this:

	var resultStream = new MemoryStream();
var webPSupported = Request.AcceptTypes.Contains("image/webp");
if (webPSupported)
{
WebPFormat.SaveToStream(resultStream, new SD.Bitmap(resizedImageStream));
}
else
{
new SD.Bitmap(resizedImageStream).Save(resultStream, ImageFormat.Jpeg);
}

resultStream.Seek(0, SeekOrigin.Begin);
return new FileContentResult(resultStream.ToArray(), webPSupported ? "image/webp" : "image/jpeg");

That’s it! We now have a functional controller action that responds correctly depending on request accept headers. You gotta love HTTP. You can read more about content negotiation and WebP on lya Grigorik’s blog.


Client Caching and CDNs


Since it does take a little while to perform the resizing and encoding, I recommend storing the output of the transformation in HttpRuntime.Cache and fetching from there in subsequent requests. The details are trivial and omitted from this post.


There is also a bunch of ASP.NET cache configuration we should do to let clients cache images locally:

	Response.Cache.SetExpires(DateTime.Now.AddDays(365));
Response.Cache.SetCacheability(HttpCacheability.Public);
Response.Cache.SetMaxAge(TimeSpan.FromDays(365));
Response.Cache.SetSlidingExpiration(true);
Response.Cache.SetOmitVaryStar(true);
Response.Headers.Set("Vary",
string.Join(",", new string[] { "Accept", "Accept-Encoding" } ));
Response.Cache.SetLastModified(image.UpdatedAt.ToLocalTime());

Notice that we set the Vary header value to include “Accept” (as well as “Accept-Encoding”). This tells CDNs and other intermediary caching proxies that if they try to cache this response, they must vary the cached value based on value of the “Accept” header of the request. This works for “Accept-Encoding”, so that different values can cached based on whether the response is compressed with gzip, deflate or not at all, and all major CDNs support it. Unfortunately, the mainstream CDNs I experimented with (CloudFront and Azure CDN) don’t support other Vary values than “Accept-Encoding”. This is really frustrating, but also somewhat understandable from the standpoint of the CDN folks: If all Vary values are honored, the number of artifacts they have to cache would increase at a combinatorial rate as browsers and servers make use of cleverer caching. Unless you find a CDN that specifically support non-Accept-Encoding Vary values, don’t use a CDN when doing this kind of content negotiation.


That’s it! I hope this post will help you build ASP.NET web apps that serve up WebP images really quickly.


Ottimizzare i fumetti per Kindle e altri ebook reader

Kindle Comic Converter (qui puoi scaricare l'applicazione) è un'applicazione che consente di ottimizzare i fumetti per la lettura su Kindle (e non solo) convertendoli dal formato CBR/CBZ a quello Mobi per il lettore di Amazon o ePub per gli altri ebook reader. Ma non si tratta di un semplice converter.

Kindle Comic Converter

Oltre a rendere i fumetti digitali “digeribili” da qualsiasi dispositivo e-ink, l’applicazione provvede, infatti, ad ottimizzare le immagini in modo da renderne la fruizione più comoda anche sugli schermi di dimensioni compatte. Ci sono molte funzioni che si possono applicare in tal senso e per gli appassionati di manga c’è una modalità di conversione speciale che attiva la lettura delle pagine da destra verso sinistra.

Per capire come funziona Kindle Comic Converter basta guardare la sua schermata principale: cliccando su Add file o Add directory si aggiungono i file da convertire (possono essere CBR, CBZ, PDF o semplici immagini in sequenza), dal menu a tendina posto in basso a sinistra si sceglie il dispositivo di destinazione del fumetto e cliccando su Convert si avvia il processo di elaborazione del file di output.

Come accennato in precedenza, per i manga bisogna spuntare anche l’opzione Manga mode che dà la possibilità di sfogliare le pagine da destra verso sinistra sugli ebook reader e cliccando sul pulsante Advanced si può accedere alla lista completa delle funzioni del programma (colorazione dei margini delle pagine, modalità webtoon e molto altro ancora).

Il software è disponibile non solo su Windows ma anche su Mac e Linux. Qui sotto trovate il link al sito ufficiale dal quale potete scaricarlo con un semplice click.

Display list of files from Server folder in ASP.Net GridView

In this article I will explain how we can save and retrieve files from Windows Folder and Directory and display them in ASP.Net GridView control with download and delete option.

 

HTML Markup

Below is the HTML Markup of the page, where I have an ASP.Net control FileUpload to upload files, a Buttoncontrol to trigger file uploads and an ASP.Net GridViewcontrol to display the files from folder.

    <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" EmptyDataText="No files uploaded">
<Columns>
<asp:BoundField DataField="Text" HeaderText="File Name" />
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="lnkDownload" Text="Download" CommandArgument='<%# Eval("Value") %>' runat="server" OnClick="DownloadFile"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="lnkDelete" Text="Delete" CommandArgument='<%# Eval("Value") %>' runat="server" OnClick="DeleteFile" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>




You will need to import the following namespaces for C# and VB.NET

using System.IO;
or
Imports System.IO



Uploading the File and saving in directory or folder


When the file is selected in APS.Net FileUpload control and the Upload button is clicked the following event handler is triggered. Below I have folder Uploads in the root directory of my ASP.Net Website where I am saving the uploaded file.

C#

protected void UploadFile(object sender, EventArgs e)
{
string fileName = Path.GetFileName(FileUpload1.PostedFile.FileName);
FileUpload1.PostedFile.SaveAs(Server.MapPath("~/Uploads/") + fileName);
Response.Redirect(Request.Url.AbsoluteUri);
}

VB.NET

Protected Sub UploadFile(ByVal sender As Object, ByVal e As EventArgs)
Dim fileName As String = Path.GetFileName(FileUpload1.PostedFile.FileName)
FileUpload1.PostedFile.SaveAs((Server.MapPath("~/Uploads/") + fileName))
Response.Redirect(Request.Url.AbsoluteUri)
End Sub



 




Displaying the files from folder or directory in ASP.Net GridView


Here I am reading all the files from the Uploads directory which I have created and then binding the fetched files to the ASP.Net GridView control.

C#

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
string[] filePaths = Directory.GetFiles(Server.MapPath("~/Uploads/"));
List<ListItem> files = new List<ListItem>();
foreach (string filePath in filePaths)
{
files.Add(new ListItem(Path.GetFileName(filePath), filePath));
}
GridView1.DataSource = files;
GridView1.DataBind();
}
}



VB.NET

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
If Not IsPostBack Then
Dim filePaths() As String = Directory.GetFiles(Server.MapPath("~/Uploads/"))
Dim files As List(Of ListItem) = New List(Of ListItem)
For Each filePath As String In filePaths
files.Add(New ListItem(Path.GetFileName(filePath), filePath))
Next
GridView1.DataSource = files
GridView1.DataBind()
End If
End Sub



Downloading the Uploaded File from ASP.Net GridView


The following event handler is executed when the lnkDownload LinkButton is clicked in the ASP.Net GridView Row. Using the CommandArgument property of the ASP.Net LinkButton, I get the path of the file using which I am downloading the file.

C#

protected void DownloadFile(object sender, EventArgs e)
{
string filePath = (sender as LinkButton).CommandArgument;
Response.ContentType = ContentType;
Response.AppendHeader("Content-Disposition", "attachment; filename=" + Path.GetFileName(filePath));
Response.WriteFile(filePath);
Response.End();
}



VB.NET

Protected Sub DownloadFile(ByVal sender As Object, ByVal e As EventArgs)
Dim filePath As String = CType(sender, LinkButton).CommandArgument
Response.ContentType = ContentType
Response.AppendHeader("Content-Disposition", ("attachment; filename=" + Path.GetFileName(filePath)))
Response.WriteFile(filePath)
Response.End()
End Sub



Deleting the Uploaded File from ASP.Net GridView


The following event handler is executed when the lnkDelete LinkButton is clicked in the ASP.Net GridView Row. Using the CommandArgument property of the ASP.Net LinkButton, I get the path of the file using which I am deleting the file.

C#

protected void DeleteFile(object sender, EventArgs e)
{
string filePath = (sender as LinkButton).CommandArgument;
File.Delete(filePath);
Response.Redirect(Request.Url.AbsoluteUri);
}



VB.NET

Protected Sub DeleteFile(ByVal sender As Object, ByVal e As EventArgs)
Dim filePath As String = CType(sender, LinkButton).CommandArgument
File.Delete(filePath)
Response.Redirect(Request.Url.AbsoluteUri)
End Sub

How to create simple Background Agent in Windows Phone

This article provides a minimal example on how to create Background Agents (Tasks) in Windows Phone. There is a more comprehensive example on Dev Center How to implement background agents for Windows Phone.

 

Introduction

Windows Phone apps are made dormant when running in the background or when the phone is locked (to conserve device memory and battery life). If your application needs to perform processing when it is (may be) in the background you can use a background agent to run activities according to some schedule.

Background agents are divided into Periodic Tasks and Resource-intensive Tasks. Periodic Task can run for no more than 25 seconds every 30 minutes. This sort of agent is suitable for many common use-cases:

  • Downloading data from remote server and then scheduling notifications (for example, when monitoring twitter or facebook updates)
  • Changing lock screen wallpaper ( like the Bing app)
  • Synchronizing data in the background, for example emails

Apps which require more device resources and/or which do not require a fixed update schedule, can use a resource intensive task. These tasks run when the device is connected to external power and/or connected to a WiFi network - they are very useful when you need to transfer a lot of data or perform some other long running task in the background.

This article provides a very simple example of how to create a Periodic Task.

If you want to also understand Resource-intensive tasks then check out How to implement background agents for Windows Phone (Dev Center). This is more complicated to read, but is more comprehensive and covers both periodic and resource-intensive tasks.

 

Limitations

Background agents have certain limitations, as listed below.

  • Background tasks can minimally be run every 30 minutes. There is a debug-only API to run them more regularly, but this is not available for released apps.
  • There are certain APIs which are not supported , you can check here.
  • Some low power devices do not support background agents
  • Background tasks are limited by number on each device and can be enabled or disabled from application settings.
  • They do not work when power saver mode is activated.

 

Basic requirements

  • You need to create an app project, it can be anything from simple basic windows phone app to panorama or pivot based application.
  • Then create your background agent project in the same solution and add its reference to the main app, with necessary code (which is hardly few lines) you can have your background agent running. You can test agents in the simulator as well.

 

References Required

Following references to the DLLs are required.

  • Microsoft.Xna.Framework.Media

This can be added by Project | References | Add Reference..

 

How to....

  • Create a simple windows phone application project as follows and give some suitable name to it.

Screenshot_(4)

  • Create a scheduled task agent project in Visual Studio, this should be added to the same solution. An easy way to do this is: go to solution explorer of main application, right click on solution and select add, select add project and automatically the project created will get added to the existing solution. Assign some suitable name to the project.

Screenshot_(5)

  • The next step is to add a reference to the main application. This can be done by going to Solution Explorer, right clicking references under main project and selecting the Add Reference option.

Screenshot_(6)

  • Next select Solutions section on the Add Reference dialog and you should be able to see the name of your scheduled task agent project name there select it and its done.

Screenshot_(7)

  • Next open ScheduledAgent.cs file from your background agent project and add following lines of code in OnInvoke() method
  protected override void OnInvoke(ScheduledTask task)
{
 
string toastMessage = "Periodic task running.";
 
ShellToast toast = new ShellToast();
toast.Title = "Background Agent Sample";
toast.Content = toastMessage;
toast.Show();
#if DEBUG_AGENT
ScheduledActionService.LaunchForTest(task.Name,TimeSpan.FromSeconds(60));
#endif
 
NotifyComplete();
}

Once the above code is added the Scheduled Agent or your background task is ready to fire a Toast notification whenever its called. As you may run this app to test, don't forget to add following macro at the top in your ScheduledAgent.cs file

#define DEBUG_AGENT

and after the above macro make sure you have all following namespace imports in place

using System.Diagnostics;
using System.Windows;
using Microsoft.Phone.Scheduler;
using Microsoft.Phone.Shell;
using System;


  • Now next step is to setup this Agent (task) to run in background from your main app, it can be done with the help of following lines of code. Make sure you place them in your MainPage.xaml.cs file of main project, I am attaching the complete file for your exposure to the code.
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using DynaLock.Resources;
using Microsoft.Phone.Scheduler;
 
namespace Application1
{
public partial class MainPage : PhoneApplicationPage
{
PeriodicTask periodicTask;
 
 
string periodicTaskName = "PeriodicAgent";
// Constructor
 
public MainPage()
{
InitializeComponent();
 
// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
agentsAreEnabled = true;
 
// Obtain a reference to the period task, if one exists
periodicTask = ScheduledActionService.Find(periodicTaskName) as PeriodicTask;
 
if (periodicTask != null)
{
RemoveAgent(periodicTaskName);
}
 
periodicTask = new PeriodicTask(periodicTaskName);
 
// The description is required for periodic agents. This is the string that the user
// will see in the background services Settings page on the device.
periodicTask.Description = "This demonstrates a periodic task.";
 
// Place the call to Add in a try block in case the user has disabled agents.
try
{
ScheduledActionService.Add(periodicTask);
 
// If debugging is enabled, use LaunchForTest to launch the agent in one minute.
#if(DEBUG_AGENT)
ScheduledActionService.LaunchForTest(periodicTaskName, TimeSpan.FromSeconds(10));
#endif
}
catch (InvalidOperationException exception)
{
if (exception.Message.Contains("BNS Error: The action is disabled"))
{
MessageBox.Show("Background agents for this application have been disabled by the user.");
agentsAreEnabled = false;
 
}
 
if (exception.Message.Contains("BNS Error: The maximum number of ScheduledActions of this type have already been added."))
{
// No user action required. The system prompts the user when the hard limit of periodic tasks has been reached.
 
}
 
}
catch (SchedulerServiceException)
{
// No user action required.
}
 
 
}
private void RemoveAgent(string name)
{
try
{
ScheduledActionService.Remove(name);
}
catch (Exception)
{
}
}
}
}

We call LaunchForTest() function only for debugging, which should be remove once your application goes into production environment.

Make sure to remove the DEBUG macro once you are done debugging of the project which will stop calling the agent after every few seconds, which should be done only if you wish to debug the application. If you keep that line it may cause failure in app submission process.

Checking the Internet connection type on Windows Phone

All Windows Phone applications that use Internet data should always check if there is a valid Internet connection; if there is no connection, a proper message should be displayed to the user. The correct way to check if you have an Internet connection (WIFI, Ethernet, or none) is by checking the property:

NetworkInterface.NetworkInterfaceType

Unfortunately checking this property is a synchronous operation, so calling it in the UI thread can block the UI for many seconds.

If your application relies on a specific server you might be tempted to simply check the Internet connection by calling the server. This could result in an inaccurate error message if your server is down, since the Internet may be available.

 


Utility class for checking the connection


The utility class below (included in the sample project) checks the network connection in another thread.

using System.Threading;
using Microsoft.Phone.Net.NetworkInformation;
 
namespace DotNetApp.Utilities
{
public class NetworkTypeEventArgs
{
#region Constructor
 
public NetworkTypeEventArgs(NetworkInterfaceType type, bool hasTimeout = false)
{
Type = type;
HasTimeout = hasTimeout;
}
 
#endregion
 
#region Properties
 
public bool HasTimeout { get; private set; }
 
public bool HasInternet
{
get { return Type != NetworkInterfaceType.None; }
}
 
public NetworkInterfaceType Type { get; private set; }
 
#endregion
}
 
/// <summary>
/// Static class to get the NetworkInterfaceType without blocking the UI thread.
/// </summary>
public static class NetworkInformationUtility
{
#region Fields
 
private static bool _isGettingNetworkType;
private static readonly object _synchronizationObject = new object();
private static Timer _timer;
 
#endregion
 
#region Methods
 
/// <summary>
/// Get the NetworkInterfaceType asynchronously.
/// </summary>
/// <param name="timeoutInMs">Specifies the timeout in milliseconds.</param>
public static void GetNetworkTypeAsync(int timeoutInMs)
{
lock (_synchronizationObject)
{
if (!_isGettingNetworkType)
{
_isGettingNetworkType = true;
 
if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
{
Thread thread = new Thread(GetNetworkType) {IsBackground = true};
thread.Start(timeoutInMs);
}
else
{
FireGetNetworkTypeCompleted(NetworkInterfaceType.None);
}
}
}
}
 
#endregion
 
#region Delegates
 
public delegate void NetworkTypeEventHandler(object sender, NetworkTypeEventArgs networkTypeEventArgs);
 
#endregion
 
#region Events
 
public static event NetworkTypeEventHandler GetNetworkTypeCompleted;
 
#endregion
 
#region Event Handlers
 
private static void OnTimerElapsed(object state)
{
FireGetNetworkTypeCompleted(NetworkInterfaceType.None, true);
}
 
#endregion
 
#region Private Methods
 
private static void GetNetworkType(object state)
{
_timer = new Timer(OnTimerElapsed, null, (int)state, 0);
 
// This is a blocking call, this is why a thread is used to let the UI to be fluid
NetworkInterfaceType type = NetworkInterface.NetworkInterfaceType;
 
_timer.Dispose();
_timer = null;
 
FireGetNetworkTypeCompleted(type);
}
 
private static void FireGetNetworkTypeCompleted(NetworkInterfaceType type, bool hasTimeout = false)
{
lock (_synchronizationObject)
{
if (_isGettingNetworkType)
{
_isGettingNetworkType = false;
 
NetworkTypeEventHandler networkTypeEventHandler = GetNetworkTypeCompleted;
 
if (networkTypeEventHandler != null)
{
networkTypeEventHandler(null, new NetworkTypeEventArgs(type, hasTimeout));
}
}
}
}
 
#endregion
}
}

Using the utility class


Here are the steps to use this class in your code:


  1. Add the NetworkInformationUtility.cs to your project.
  2. Attach method to the event NetworkInformationUtility.GetNetworkTypeCompleted.
  3. Call NetworkInformationUtility.GetNetworkTypeAsync(3000 /*timeout in ms*/);
  4. Retrieve the result on the GetNetworkTypeCompleted method that you attached to the event.

Code sample:

using System.Windows;
using DotNetApp.Utilities;
 
namespace NetworkInformationApp
{
public partial class MainPage {
public MainPage()
{
InitializeComponent();
}
 
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
 
NetworkInformationUtility.GetNetworkTypeCompleted += GetNetworkTypeCompleted;
 
NetworkInformationUtility.GetNetworkTypeAsync(3000); // Timeout of 3 seconds }
 
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
 
NetworkInformationUtility.GetNetworkTypeCompleted -= GetNetworkTypeCompleted;
}
 
private void GetNetworkTypeCompleted(object sender, NetworkTypeEventArgs networkTypeEventArgs)
{
string message;
 
if (networkTypeEventArgs.HasTimeout)
{
message = "The timeout occurred";
}
else if (networkTypeEventArgs.HasInternet)
{
message = "The Internet connection type is: " + networkTypeEventArgs.Type.ToString();
}
else {
message = "There is no Internet connection";
}
 
// Always dispatch on the UI thread Dispatcher.BeginInvoke(() => MessageBox.Show(message));
}
}
}

Checking network availability in Windows Phone

Many applications utilize network connection for various purposes like feeds, sending & receiving data to/from server, etc. The following article explains how one can detect if the network connection is available or not.

Network API Information

Example Code to understand the network connection

namespace NetworkTest
{
public partial class MainPage : PhoneApplicationPage
{
public static readonly DependencyProperty NetProperty =
DependencyProperty.Register("NetworkAvailability",
typeof(string),
typeof(MainPage),
new PropertyMetadata(string.Empty));
 
public MainPage()
{
InitializeComponent();
string isNetworkAvail =
NetworkInterface.GetIsNetworkAvailable() ? "on" : "off";
}
}
}

Enabling quick resume for Windows Phone apps

This article explains how to quickly resume the Windows Phone 8 application which is put in the background.

 

Introduction

Whenever your app loses focus (is put in the background), an instance of the app is saved. This instance is used to resume the app if the user tasks to it from a deep link or returns to it by selecting the back button on the foreground app. However if the user relaunches the app by selecting its icon on the start screen, by default the stored instance is removed and it is started from scratch.

On Windows Phone 8, Fast App Resume is a way to force a relaunch to use the saved instance rather than fully restart the app. This is much faster. This is not enabled by default and you will need to enable it in order to achieve this functionality in your applications.

 

Enable Fast App Resume

Enabling Fast App Resume is as simple as adding one attribute to an XML element in the manifest file.

  1. Open WMAppManifest.xml in any editor. (I use notepad++)
  2. Find the element DefaultTask
  3. Add the attribute ActivationPolicy="Resume"

You should end up with something that looks like this:

<DefaultTask Name="_default" NavigationPage="MainPage.xaml" ActivationPolicy="Resume"/>

References


Apart from setting param in WMAppManifest.xml, there's also a bit one needs to do in App.xaml.cs in order to make the 'fast app resume' feature work correctly.A nice working example is available on msdn: Fast app resume example

Make the application loosely coupled

In this series of tutorials, we build an entire Contact Management application from start to finish. The Contact Manager application enables you to store contact information - names, phone numbers and email addresses - for a list of people.

We build the application over multiple iterations. With each iteration, we gradually improve the application. The goal of this multiple iteration approach is to enable you to understand the reason for each change.

    Iteration #1 - Create the application. In the first iteration, we create the Contact Manager in the simplest way possible. We add support for basic database operations: Create, Read, Update, and Delete (CRUD).

    Iteration #2 - Make the application look nice. In this iteration, we improve the appearance of the application by modifying the default ASP.NET MVC view master page and cascading style sheet.

    Iteration #3 - Add form validation. In the third iteration, we add basic form validation. We prevent people from submitting a form without completing required form fields. We also validate email addresses and phone numbers.

    Iteration #4 - Make the application loosely coupled. In this third iteration, we take advantage of several software design patterns to make it easier to maintain and modify the Contact Manager application. For example, we refactor our application to use the Repository pattern and the Dependency Injection pattern.

    Iteration #5 - Create unit tests. In the fifth iteration, we make our application easier to maintain and modify by adding unit tests. We mock our data model classes and build unit tests for our controllers and validation logic.

    Iteration #6 - Use test-driven development. In this sixth iteration, we add new functionality to our application by writing unit tests first and writing code against the unit tests. In this iteration, we add contact groups.

    Iteration #7 - Add Ajax functionality. In the seventh iteration, we improve the responsiveness and performance of our application by adding support for Ajax.

This Iteration

In this fourth iteration of the Contact Manager application, we refactor the application to make the application more loosely coupled. When an application is loosely coupled, you can modify the code in one part of the application without needing to modify the code in other parts of the application. Loosely coupled applications are more resilient to change.

Currently, all of the data access and validation logic used by the Contact Manager application is contained in the controller classes. This is a bad idea. Whenever you need to modify one part of your application, you risk introducing bugs into another part of your application. For example, if you modify your validation logic, you risk introducing new bugs into your data access or controller logic.

(SRP), a class should never have more than one reason to change. Mixing controller, validation, and database logic is a massive violation of the Single Responsibility Principle.

There are several reasons that you might need to modify your application. You might need to add a new feature to your application, you might need to fix a bug in your application, or you might need to modify how a feature of your application is implemented. Applications are rarely static. They tend to grow and mutate over time.

Imagine, for example, that you decide to change how you implement your data access layer. Right now, the Contact Manager application uses the Microsoft Entity Framework to access the database. However, you might decide to migrate to a new or alternative data access technology such as ADO.NET Data Services or NHibernate. However, because the data access code is not isolated from the validation and controller code, there is no way to modify the data access code in your application without modifying other code that is not directly related to data access.

When an application is loosely coupled, on the other hand, you can make changes to one part of an application without touching other parts of an application. For example, you can switch data access technologies without modifying your validation or controller logic.

In this iteration, we take advantage of several software design patterns that enable us to refactor our Contact Manager application into a more loosely coupled application. When we are done, the Contact Manager won t do anything that it didn t do before. However, we ll be able to change the application more easily in the future.

Refactoring is the process of rewriting an application in such a way that it does not lose any existing functionality.

Using the Repository Software Design Pattern

Our first change is to take advantage of a software design pattern called the Repository pattern. We ll use the Repository pattern to isolate our data access code from the rest of our application.

Implementing the Repository pattern requires us to complete the following two steps:

  1. Create an interface
  2. Create a concrete class that implements the interface

First, we need to create an interface that describes all of the data access methods that we need to perform. The IContactManagerRepository interface is contained in Listing 1. This interface describes five methods: CreateContact(), DeleteContact(), EditContact(), GetContact, and ListContacts().

Listing 1 - Models\IContactManagerRepositiory.cs

using System;
using System.Collections.Generic;

namespace ContactManager.Models
{
public interface IContactRepository
{
Contact CreateContact(Contact contactToCreate);
void DeleteContact(Contact contactToDelete);
Contact EditContact(Contact contactToUpdate);
Contact GetContact(int id);
IEnumerable<Contact> ListContacts();

}
}

Next, we need to create a concrete class that implements the IContactManagerRepository interface. Because we are using the Microsoft Entity Framework to access the database, we ll create a new class named EntityContactManagerRepository. This class is contained in Listing 2.

Listing 2 - Models\EntityContactManagerRepository.cs

using System.Collections.Generic;
using System.Linq;

namespace ContactManager.Models
{
public class EntityContactManagerRepository : ContactManager.Models.IContactManagerRepository
{
private ContactManagerDBEntities _entities = new ContactManagerDBEntities();

public Contact GetContact(int id)
{
return (from c in _entities.ContactSet
where c.Id == id
select c).FirstOrDefault();
}


public IEnumerable ListContacts()
{
return _entities.ContactSet.ToList();
}


public Contact CreateContact(Contact contactToCreate)
{
_entities.AddToContactSet(contactToCreate);
_entities.SaveChanges();
return contactToCreate;
}


public Contact EditContact(Contact contactToEdit)
{
var originalContact = GetContact(contactToEdit.Id);
_entities.ApplyPropertyChanges(originalContact.EntityKey.EntitySetName, contactToEdit);
_entities.SaveChanges();
return contactToEdit;
}


public void DeleteContact(Contact contactToDelete)
{
var originalContact = GetContact(contactToDelete.Id);
_entities.DeleteObject(originalContact);
_entities.SaveChanges();
}

}
}


Notice that the EntityContactManagerRepository class implements the IContactManagerRepository interface. The class implements all five of the methods described by that interface.

You might wonder why we need to bother with an interface. Why do we need to create both an interface and a class that implements it?

With one exception, the remainder of our application will interact with the interface and not the concrete class. Instead of calling the methods exposed by the EntityContactManagerRepository class, we ll call the methods exposed by the IContactManagerRepository interface.

That way, we can implement the interface with a new class without needing to modify the remainder of our application. For example, at some future date, we might want to implement an DataServicesContactManagerRepository class that implements the IContactManagerRepository interface. The DataServicesContactManagerRepository class might use ADO.NET Data Services to access a database instead of the Microsoft Entity Framework.

If our application code is programmed against the IContactManagerRepository interface instead of the concrete EntityContactManagerRepository class then we can switch concrete classes without modifying any of the rest of our code. For example, we can switch from the EntityContactManagerRepository class to the DataServicesContactManagerRepository class without modifying our data access or validation logic.

Programming against interfaces (abstractions) instead of concrete classes makes our application more resilient to change.

You can quickly create an interface from a concrete class within Visual Studio by selecting the menu option Refactor, Extract Interface. For example, you can create the EntityContactManagerRepository class first and then use Extract Interface to generate the IContactManagerRepository interface automatically.

Using the Dependency Injection Software Design Pattern


Now that we have migrated our data access code to a separate Repository class, we need to modify our Contact controller to use this class. We will take advantage of a software design pattern called Dependency Injection to use the Repository class in our controller.

The modified Contact controller is contained in Listing 3.

Listing 3 - Controllers\ContactController.cs

using System.Text.RegularExpressions;
using System.Web.Mvc;
using ContactManager.Models;

namespace ContactManager.Controllers
{
public class ContactController : Controller
{
private IContactManagerRepository _repository;

public ContactController()
: this(new EntityContactManagerRepository())
{}


public ContactController(IContactManagerRepository repository)
{
_repository = repository;
}


protected void ValidateContact(Contact contactToValidate)
{
if (contactToValidate.FirstName.Trim().Length == 0)
ModelState.AddModelError("FirstName", "First name is required.");
if (contactToValidate.LastName.Trim().Length == 0)
ModelState.AddModelError("LastName", "Last name is required.");
if (contactToValidate.Phone.Length > 0 && !Regex.IsMatch(contactToValidate.Phone, @"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}"))
ModelState.AddModelError("Phone", "Invalid phone number.");
if (contactToValidate.Email.Length > 0 && !Regex.IsMatch(contactToValidate.Email, @"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"))
ModelState.AddModelError("Email", "Invalid email address.");
}

public ActionResult Index()
{
return View(_repository.ListContacts());
}

public ActionResult Create()
{
return View();
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "Id")] Contact contactToCreate)
{
// Validation logic
ValidateContact(contactToCreate);
if (!ModelState.IsValid)
return View();

// Database logic
try
{
_repository.CreateContact(contactToCreate);
return RedirectToAction("Index");
}
catch
{
return View();
}
}

public ActionResult Edit(int id)
{
return View(_repository.GetContact(id));
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Contact contactToEdit)
{
// Validation logic
ValidateContact(contactToEdit);
if (!ModelState.IsValid)
return View();

// Database logic
try
{
_repository.EditContact(contactToEdit);
return RedirectToAction("Index");
}
catch
{
return View();
}
}

public ActionResult Delete(int id)
{
return View(_repository.GetContact(id));
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Delete(Contact contactToDelete)
{
try
{
_repository.DeleteContact(contactToDelete);
return RedirectToAction("Index");
}
catch
{
return View();
}
}

}
}

Notice that the Contact controller in Listing 3 has two constructors. The first constructor passes a concrete instance of the IContactManagerRepository interface to the second constructor. The Contact controller class uses Constructor Dependency Injection.

The one and only place that the EntityContactManagerRepository class is used is in the first constructor. The remainder of the class uses the IContactManagerRepository interface instead of the concrete EntityContactManagerRepository class.

This makes it easy to switch implementations of the IContactManagerRepository class in the future. If you want to use the DataServicesContactRepository class instead of the EntityContactManagerRepository class, just modify the first constructor.

Constructor Dependency injection also makes the Contact controller class very testable. In your unit tests, you can instantiate the Contact controller by passing a mock implementation of the IContactManagerRepository class. This feature of Dependency Injection will be very important to us in the next iteration when we build unit tests for the Contact Manager application.

If you want to completely decouple the Contact controller class from a particular implementation of the IContactManagerRepository interface then you can take advantage of a framework that supports Dependency Injection such as StructureMap or the Microsoft Entity Framework (MEF). By taking advantage of a Dependency Injection framework, you never need to refer to a concrete class in your code.

Creating a Service Layer


You might have noticed that our validation logic is still mixed up with our controller logic in the modified controller class in Listing 3. For the same reason that it is a good idea to isolate our data access logic, it is a good idea to isolate our validation logic.

To fix this problem, we can create a separate service layer. The service layer is a separate layer that we can insert between our controller and repository classes. The service layer contains our business logic including all of our validation logic.

The ContactManagerService is contained in Listing 4. It contains the validation logic from the Contact controller class.

Listing 4 - Models\ContactManagerService.cs

using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Web.Mvc;
using ContactManager.Models.Validation;

namespace ContactManager.Models
{
public class ContactManagerService : IContactManagerService
{
private IValidationDictionary _validationDictionary;
private IContactManagerRepository _repository;


public ContactManagerService(IValidationDictionary validationDictionary)
: this(validationDictionary, new EntityContactManagerRepository())
{}


public ContactManagerService(IValidationDictionary validationDictionary, IContactManagerRepository repository)
{
_validationDictionary = validationDictionary;
_repository = repository;
}


public bool ValidateContact(Contact contactToValidate)
{
if (contactToValidate.FirstName.Trim().Length == 0)
_validationDictionary.AddError("FirstName", "First name is required.");
if (contactToValidate.LastName.Trim().Length == 0)
_validationDictionary.AddError("LastName", "Last name is required.");
if (contactToValidate.Phone.Length > 0 && !Regex.IsMatch(contactToValidate.Phone, @"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}"))
_validationDictionary.AddError("Phone", "Invalid phone number.");
if (contactToValidate.Email.Length > 0 && !Regex.IsMatch(contactToValidate.Email, @"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"))
_validationDictionary.AddError("Email", "Invalid email address.");
return _validationDictionary.IsValid;
}


#region IContactManagerService Members

public bool CreateContact(Contact contactToCreate)
{
// Validation logic
if (!ValidateContact(contactToCreate))
return false;

// Database logic
try
{
_repository.CreateContact(contactToCreate);
}
catch
{
return false;
}
return true;
}

public bool EditContact(Contact contactToEdit)
{
// Validation logic
if (!ValidateContact(contactToEdit))
return false;

// Database logic
try
{
_repository.EditContact(contactToEdit);
}
catch
{
return false;
}
return true;
}

public bool DeleteContact(Contact contactToDelete)
{
try
{
_repository.DeleteContact(contactToDelete);
}
catch
{
return false;
}
return true;
}

public Contact GetContact(int id)
{
return _repository.GetContact(id);
}

public IEnumerable<Contact> ListContacts()
{
return _repository.ListContacts();
}

#endregion
}
}


Notice that the constructor for the ContactManagerService requires a ValidationDictionary. The service layer communicates with the controller layer through this ValidationDictionary. We discuss the ValidationDictionary in detail in the following section when we discuss the Decorator pattern.

Notice, furthermore, that the ContactManagerService implements the IContactManagerService interface. You should always strive to program against interfaces instead of concrete classes. Other classes in the Contact Manager application do not interact with the ContactManagerService class directly. Instead, with one exception, the remainder of the Contact Manager application is programmed against the IContactManagerService interface.

The IContactManagerService interface is contained in Listing 5.

Listing 5 - Models\IContactManagerService.cs

using System.Collections.Generic;

namespace ContactManager.Models
{
public interface IContactManagerService
{
bool CreateContact(Contact contactToCreate);
bool DeleteContact(Contact contactToDelete);
bool EditContact(Contact contactToEdit);
Contact GetContact(int id);
IEnumerable ListContacts();
}
}


The modified Contact controller class is contained in Listing 6. Notice that the Contact controller no longer interacts with the ContactManager repository. Instead, the Contact controller interacts with the ContactManager service. Each layer is isolated as much as possible from other layers.

Listing 6 - Controllers\ContactController.cs

using System.Web.Mvc;
using ContactManager.Models;

namespace ContactManager.Controllers
{
public class ContactController : Controller
{
private IContactManagerService _service;

public ContactController()
{
_service = new ContactManagerService(new ModelStateWrapper(this.ModelState));

}

public ContactController(IContactManagerService service)
{
_service = service;
}

public ActionResult Index()
{
return View(_service.ListContacts());
}

public ActionResult Create()
{
return View();
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create([Bind(Exclude = "Id")] Contact contactToCreate)
{
if (_service.CreateContact(contactToCreate))
return RedirectToAction("Index");
return View();
}

public ActionResult Edit(int id)
{
return View(_service.GetContact(id));
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Contact contactToEdit)
{
if (_service.EditContact(contactToEdit))
return RedirectToAction("Index");
return View();
}

public ActionResult Delete(int id)
{
return View(_service.GetContact(id));
}

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Delete(Contact contactToDelete)
{
if (_service.DeleteContact(contactToDelete))
return RedirectToAction("Index");
return View();
}

}
}


Our application no longer runs afoul of the Single Responsibility Principle (SRP). The Contact controller in Listing 6 has been stripped of every responsibility other than controlling the flow of application execution. All the validation logic has been removed from the Contact controller and pushed into the service layer. All of the database logic has been pushed into the repository layer.

Using the Decorator Pattern


We want to be able to completely decouple our service layer from our controller layer. In principle, we should be able to compile our service layer in a separate assembly from our controller layer without needing to add a reference to our MVC application.

However, our service layer needs to be able to pass validation error messages back to the controller layer. How can we enable the service layer to communicate validation error messages without coupling the controller and service layer? We can take advantage of a software design pattern named the Decorator pattern.

A controller uses a ModelStateDictionary named ModelState to represent validation errors. Therefore, you might be tempted to pass ModelState from the controller layer to the service layer. However, using ModelState in the service layer would make your service layer dependent on a feature of the ASP.NET MVC framework. This would be bad because, someday, you might want to use the service layer with a WPF application instead of an ASP.NET MVC application. In that case, you wouldn t want to reference the ASP.NET MVC framework to use the ModelStateDictionary class.

The Decorator pattern enables you to wrap an existing class in a new class in order to implement an interface. Our Contact Manager project includes the ModelStateWrapper class contained in Listing 7. The ModelStateWrapper class implements the interface in Listing 8.

Listing 7 - Models\Validation\ModelStateWrapper.cs

using System.Web.Mvc;

namespace ContactManager.Models.Validation
{
public class ModelStateWrapper : IValidationDictionary
{
private ModelStateDictionary _modelState;

public ModelStateWrapper(ModelStateDictionary modelState)
{
_modelState = modelState;
}

public void AddError(string key, string errorMessage)
{
_modelState.AddModelError(key, errorMessage);
}

public bool IsValid
{
get { return _modelState.IsValid; }
}
}
}

Listing 8 - Models\Validation\IValidationDictionary.cs

namespace ContactManager.Models.Validation
{
public interface IValidationDictionary
{
void AddError(string key, string errorMessage);
bool IsValid {get;}
}
}


If you take a close look at Listing 5 then you ll see that the ContactManager service layer uses the IValidationDictionary interface exclusively. The ContactManager service is not dependent on the ModelStateDictionary class. When the Contact controller creates the ContactManager service, the controller wraps its ModelState like this:

_service = new ContactManagerService(new ModelStateWrapper(this.ModelState));

Summary


In this iteration, we did not add any new functionality to the Contact Manager application. The goal of this iteration was to refactor the Contact Manager application so that is easier to maintain and modify.

First, we implemented the Repository software design pattern. We migrated all of the data access code to a separate ContactManager repository class.

We also isolated our validation logic from our controller logic. We created a separate service layer that contains all of our validation code. The controller layer interacts with the service layer, and the service layer interacts with the repository layer.

When we created the service layer, we took advantage of the Decorator pattern to isolate ModelState from our service layer. In our service layer, we programmed against the IValidationDictionary interface instead of ModelState.

Finally, we took advantage of a software design pattern named the Dependency Injection pattern. This pattern enables us to program against interfaces (abstractions) instead of concrete classes. Implementing the Dependency Injection design pattern also makes our code more testable. In the next iteration, we add unit tests to our project.

Advertsing

125X125_06

Planet Xamarin

Planet Xamarin

Calendar

<<  November 2017  >>
MonTueWedThuFriSatSun
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

View posts in large calendar

Month List