Home - About me - Browse by categories

Azure SDK on Windows 8 Consumer preview : there was an error attaching the debugger…

When I was trying to debug a Windows Azure application in Visual Studio 2010 on Windows 8 Consumer Preview, I was getting the following error :

image

If you encounter this error, open the Control Panel, go to the Programs section and click the Turn Windows features on or off link. In the Windows features, check that the Internet Information Service Hostable Web Core feature is installed on your machine. If not, install it :

image

It solves my problem and now I can debug Windows Azure applications without any error ! It seems that the Web PI 4.0 preview does not detect this dependency while installing the Windows Azure SDK…

Hope this helps image !

Julien

read more

[Azure] Communication entre instances avec les endpoints internes

Il y a quelques temps j’ai posté deux billets décrivant des techniques pour réaliser de l’invalidation de cache sur plusieurs instances d’un rôle Windows Azure :

Dans ce billet, je souhaiterai vous présenter une autre manière de communiquer entres différentes instances d’un même rôle, en utilisant les Endpoints internes.

Les endpoints internes sont des points d’accès sur lesquels chaque instance est en capacité, par exemple, d’hoster un service WCF. Il existe plusieurs avantages dans l’utilisation de ceux-ci :

  • Ils sont internes, donc inaccessibles depuis l’extérieur
  • Il est possible de communiquer via un binding en net.tcp
  • Leur utilisation n’entraîne pas de surcoût sur votre facture Windows Azure

Création d’un endpoint interne

Pour ajouter un endpoint interne à un rôle Windows Azure, rendez-vous dans les propriétés de celui-ci dans votre projet Visual Studio, puis accédez à l’onglet Endpoints :

image

Il suffit de cliquer sur le bouton Add Endpoint, de le nommer, de mettre son type à Internal, de choisir le protocole et  enfin de définir le port privé sur lequel le endpoint sera accessible :

image

Toutes les instances du rôles exposeront alors ce endpoint automatiquement !

###

Héberger un service WCF sur un endpoint interne

Il est possible de faire en sorte qu’un service WCF soit hébergé au démarrage de chaque instance. Celui-ci pourra être appelé par n’importe quelle autre instance du rôle. Par exemple, dans le cas d’un scénario d’invalidation de cache, une instance de rôle doit être capable de notifier toutes les autres de réinitialiser leur cache local. Pour cela, il suffit de créer un canal de communication via WCF entre les instances.

Dans le cas présent, le contrat de service WCF est très simple :

[ServiceContract]
public interface ICacheInvalidationService
{
[OperationContract]
void InvalideCache();
}

Son implémentation aussi :

public class CacheInvalidationService : ICacheInvalidationService
{
public void InvalideCache()
{
//invalidation du cache local
}
}

Le démarrage du service WCF se fait dans la méthode OnStart du WebRole. En premier lieu, il faut récupérer l’adresse du endpoint interne qui a été créé :

if (RoleEnvironment.CurrentRoleInstance.InstanceEndpoints
.Any(ip => ip.Key == "CacheInvalidationEndpoint"))
{
IPEndPoint endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints
.First(ip => ip.Key == "CacheInvalidationEndpoint").Value.IPEndpoint;

}

Ensuite, l’hébergement du service WCF se fait très simplement à l’aide d’un ServiceHost :

public class WebRole : RoleEntryPoint
{
private ServiceHost _serviceHost;

public override bool OnStart()
{
if (RoleEnvironment.CurrentRoleInstance.InstanceEndpoints
.Any(ip => ip.Key == "CacheInvalidationEndpoint"))
{
IPEndPoint endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints
.First(ip => ip.Key == "CacheInvalidationEndpoint").Value.IPEndpoint;

Uri baseAddress = new Uri(string.Format("net.tcp://{0}", endpoint));
_serviceHost = new ServiceHost(typeof(CacheInvalidationService), baseAddress);

NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);
_serviceHost.AddServiceEndpoint(typeof(ICacheInvalidationService), binding, "CacheInvalidation");

try
{
_serviceHost.Open();
}
catch
{
Trace.WriteLine("Impossible de démarrer le service d'invalidation de cache");
}
}

return base.OnStart();
}
}

Il est également possible de surcharger la méthode OnStop du rôle pour arrêter le service WCF proprement :

public override void OnStop()
{
if (_serviceHost != null)
{
try
{
_serviceHost.Close();
}
catch
{
_serviceHost.Abort();
}
}
base.OnStop();
}

A présent, toute instance de ce rôle expose un service WCF permettant l’invalidation de son cache local !

Contacter toutes les instances

La dernière étape consiste à écrire le code qui permet d’appeler le service d’invalidation de cache sur toutes les instances du rôle.

Pour cela, il est nécessaire de récupérer tous les IPEndPoint qui portent le nom CacheInvalidationEndpoint :

var ipEndpoints =
from instance in RoleEnvironment.CurrentRoleInstance.Role.Instances
from endpoint in instance.InstanceEndpoints
where endpoint.Key == "CacheInvalidationEndpoint"
select endpoint.Value.IPEndpoint;

Ensuite, il suffit de parcourir les endpoints pour créer un canal de communication vers chacun d’eux, à l’aide d’une ChannelFactory WCF :

foreach (var ipEndPoint in ipEndpoints)
{
try
{
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);

ChannelFactory<ICacheInvalidationService> channelFactory =
new ChannelFactory<ICacheInvalidationService>(binding);

string uri = string.Format("net.tcp://{0}/CacheInvalidation", ipEndPoint);
EndpointAddress address = new EndpointAddress(uri);

ICacheInvalidationService service = channelFactory.CreateChannel(address);
if (service != null)
{
service.InvalideCache();
}
}
catch
{
//log exception
}
}

Et voilà, toutes les instances ont maintenant été notifiée de vider leur cache local !

Vraiment simple à mettre en place, et super utile !

Pour tester, récupérez le projet d’exemple et mettez un point d’arrêt dans la méthode InvalidateCache du service WCF. Lancez le rôle Azure (configuré pour exécuter deux instances) et appelez ensuite l’URL /Home/InvalidateCache sur l’application MVC. Vous verrez que Visual Studio s’arrête bien deux fois dans le service, une fois pour chaque instance du rôle image

Le code source est disponible ici.

A bientôt !

read more

2012 c'est parti : Meilleurs voeux, livre sur ASP.NET MVC 4, Techdays...

Avant tout, je profite de ce post pour vous souhaiter une excellente année 2012 ! Qu’elle soit aussi riche que 2011 professionnellement et qu’elle vous apporte tout ce que vous souhaitez : santé, bonheur et réussite !

Pour ma part, 2012 s’annonce déjà très riche en travail image

Pour commencer, un livre sur ASP.NET MVC 4 actuellement en cours d’écriture et sur lequel j’aurai amplement l’occasion de revenir d’ici à sa sortie !

Trois sessions aux Techdays 2012 (merci aux personnes concernées pour leur confiance !) :

  • *Architecture, bonnes pratiques et recettes pour la réussite de vos projets avec ASP.NET MVC* : je coanimerai cette session avec [Rui Carvalho](http://www.rui.fr/). Nous tenterons de vous fournir un ensemble de bonnes pratiques et des `trucs` que nous utilisons régulièrement chez nos clients dans la mise en place de projets ASP.NET MVC ! Plus d’info sur la session sur le [Rui Carvalho](http://www.rui.fr/)
  • *La dure lutte du développeur : 10 trucs pratiques pour une application mobile bien peaufinée :* il manque souvent peu de choses pour qu’une application soit parfaite ! Malheuresement ce petit effort est parfois négligé avant la publication d’une application. Cyril Cathala, David Poulin et moi-même vous donnerons des conseils pratiques pour peaufiner toutes vos applications Windows Phone ! Plus d’info sur la session sur le [site des Techdays 2012…](http://www.microsoft.com/france/mstechdays/programmes/parcours.aspx?SessionID=8ff36860-fd09-4981-bfe9-253aaaba4736)
  • *Enseigner les technologies Microsoft, un exemple avec Windows Phone :* je co-animerai cette session avec Julie Knibbe. L’idée est de vous présenter, par l’exemple de Windows Phone, les ressources qui sont à votre disposition pour enseigner les technologies Microsoft ! Plus d’info sur la session sur le [site des Techdays 2012…](http://www.microsoft.com/france/mstechdays/programmes/parcours.aspx?SessionID=b2ef1ab8-f6fd-4072-b494-e67813dba7e3)
Rendez-vous aux Techdays donc !

image

Et évidemment, en 2012 toujours, mon travail au quotidien comme consultant chez Infinite Square ! image Il me permettra d’animer ce blog qui sera certainement rythmé par Windows Phone, ASP.NET MVC 4 et Windows Azure !

Bon 2012 !

Julien

read more

[ASP.NET MVC] Multicast dans une application hébergée sur Azure avec AppFabric ServiceBus et NetEventRelayBinding

Il y a quelques semaines j’ai posté une astuce pour invalider un cache mémoire sur un changement de configuration d’instance Windows Azure. Bien que cette technique fonctionne, elle nécessite une intervention humaine, puisqu’à chaque fois que l’on souhaite invalider le cache, il faut modifier la configuration du service hébergé sur Azure.

Afin d’éviter de faire cela, je me suis penché sur l’utilisation d’AppFabric ServiceBus dans Azure et notamment du NetEventRelayBinding pour faire en sorte que lorsque je publie / supprime ou modifie un post, toutes les instances de mon blog soit notifiées et invalident leur cache mémoire.

Pour faire simple, j’expose un endpoint sur le service bus Azure, sur lequel toutes les instances vont s’abonner. Dès que l’une d’entre elle contact ce endpoint, toutes les autres sont notifiées.

Le bus des services permet de mettre en place un relai entre un client et un host de service WCF. Par exemple, il est possible d’avoir un service WCF qui soit hébergé sur un serveur IIS dans votre infrastructure et que ce service soit consommé depuis Azure ou une application totalement externe via le bus des services, évitant ainsi des problèmes de sécurité et de configuration de pare-feu.

L’autre scénario (mis en place ici) est le multicast ou le bus des services sert également de relai vers un host WCF, mais en mode multicast.

Pour mettre cela en place, il faut procéder en différentes étapes, décrites ci-après.

##

1. Activer un domaine sur le bus des services Windows Azure

Connectez-vous au portail d’administration Windows Azure sur http://windows.azure.com puis rendez-vous dans la section Bus des services, Contrôle d’accès et Cache via le menu de gauche :

image

Sélectionnez ensuite Bus des services dans le noeud AppFabric, puis cliquez sur Nouveau dans le ruban. Une popup s’ouvre alors, vous permettant d’ajouter un nouveau domaine sur lequel vous pourrez exposer vos services via AppFabric :

image

Choisissez votre espace de nom, la région dans laquelle exposer le bus des services, l’abonnement sur lequel vous souhaitez l’ajouter… puis valider la popup. Patientez jusqu’à ce que le Bus des services ajouté soit marqué comme Actif dans la liste.

image

2. Création du contrat de service et de l’implémentation du service

Comme AppFabric Service Bus sert de relais entre clients et host WCF, on utilise les mêmes mécanismes que WCF classique pour créer contrat de services et implémentations de services.

Dans mon cas, le contrat est ultra simple :

[ServiceContract(Name = "IRelayCacheInvalidationEventContract", Namespace = "http://www.juliencorioland.net/Services/")]
public interface IRelayCacheInvalidationEventContract
{
[OperationContract(IsOneWay = true)]
void InvalidateCache();
}

Attention toutefois à bien marquer toutes les OperationContract comme étant en mode One-Way, une condition nécessaire à l’utilisation du contrat sur le bus des services Azure.

J’ai également prévu une interface pour représenter le canal de communication WCF qui sera utilisé pour invalider le cache :

public interface IRelayCacheInvalidationEventChannel : IRelayCacheInvalidationEventContract, IClientChannel
{
}

A présent l’implémentation du service, une fois encore très simple ici puisqu’il s’agit d’implémenter l’interface IRelayCacheInvalidationEventContract :

public class CacheInvalidator : IRelayCacheInvalidationEventContract
{
public void InvalidateCache()
{
ICacheService cacheService = ServiceLocator.Current.GetInstance<ICacheService>();
if(cacheService != null)
{
cacheService.InvalidateCache();
}
}
}

###

###

3. Ajout du code pour hoster le service dans le Global.asax du rôle web ASP.NET MVC

Dans cette étape, il s’agit d’ajouter le code de création de l’host WCF qui sera exécuté par toutes les instances lors du démarrage de l’application web.

Pour cela, il faut dans un premier temps récupérer 3 informations : le domaine du bus des services, le nom l’émetteur par défaut (issuer name) et la clé partagée (shared secret). Pour récupérer ces informations, sélectionnez votre bus des services dans l’interface d’administration et cliquez sur le bouton Affichage de la zone** Clé par défaut**, à droite. Une popup s’affiche alors :

image

Personnellement, j’ai choisi de rajouter ces éléments au fichier de configuration du mon instance Azure, ce qui me permet de les récupérer de la sorte :

string serviceNamespace = RoleEnvironment.GetConfigurationSettingValue("CacheInvalidationRelayDomainNamespace");
string issuerName = RoleEnvironment.GetConfigurationSettingValue("CacheInvalidationRelayIssuerName");
string issuerSecret = RoleEnvironment.GetConfigurationSettingValue("CacheInvalidationRelayIssuerSecret");

Ensuite, vous devez créer une EndpointBehavior pour identifier l’appel sur le bus des services. Cela s’effectue à l’aide d’un TokenProvider et d’une instance de la classe TransportClientEndpointBehavior :

TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider(issuerName, issuerSecret);
TransportClientEndpointBehavior relayCredentials = new TransportClientEndpointBehavior(tokenProvider);

Pour avoir accès à ces classes, il vous faut référencer la librairie Microsoft.ServiceBus.dll.

A présent, utilisez l’api du service bus pour créer l’Uri qui hostera le relais vers le service :

Uri relayAddress = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "/CacheInvalidation/");

Puis comme vous l’auriez fait en WCF, crééez le ServiceHost et ajoutez lui l’endpoint behavior comme cela :

_serviceHost = new ServiceHost(typeof(CacheInvalidator), relayAddress);
foreach (var endpoint in _serviceHost.Description.Endpoints)
{
endpoint.Behaviors.Add(relayCredentials);
}
_serviceHost.Open();

###

###

Remarquez que l’endpoint behavior est rajoutée sur tous les endpoints configurés pour le service CacheInvalidator.

A présent, toutes les instances peuvent être atteintes via du multicast et donc pourront invalider leur cache mémoire !

4. Ajout du code pour récupérer un canal WCF et lancer l’invalidation de cache

Comme en WCF, on utilise un ChannelFactory pour récupérer un canal de communication. Pour pouvoir accéder au bus des services, il faut récupérer les mêmes informations que précédemment à savoir espace de noms, émetteur et clé partagé. Il faut également créer la behavior permettant d’authentifier l’appel

string serviceNamespace = RoleEnvironment.GetConfigurationSettingValue("CacheInvalidationRelayDomainNamespace");
string issuerName = RoleEnvironment.GetConfigurationSettingValue("CacheInvalidationRelayIssuerName");
string issuerSecret = RoleEnvironment.GetConfigurationSettingValue("CacheInvalidationRelayIssuerSecret");

TokenProvider tokenProvider = TokenProvider.CreateSharedSecretTokenProvider(issuerName, issuerSecret);
TransportClientEndpointBehavior relayCredentials = new TransportClientEndpointBehavior(tokenProvider);
Uri relayAddress = ServiceBusEnvironment.CreateServiceUri("sb", serviceNamespace, "/CacheInvalidation/");

A partir de là, il est possible de créer la ChannelFactory et de récupérer un canal de communication de type IRelayCacheInvalidationEventChannel pour invalider le cache :

ChannelFactory<IRelayCacheInvalidationEventChannel> channelFactory =
new ChannelFactory<IRelayCacheInvalidationEventChannel>("CacheInvalidationEndpoint",
new EndpointAddress(relayAddress));
channelFactory.Endpoint.Behaviors.Add(relayCredentials);
_cacheInvalidationChannel = channelFactory.CreateChannel();

_cacheInvalidationChannel.Open();
_cacheInvalidationChannel.InvalidateCache();

Pensez à bien fermer le canal lorsque vous n’en n’avez plus besoin :

_cacheInvalidationChannel.Close();

Le code étant en place, il ne reste plus qu’à configurer le service WCF, dans le Web.config du rôle web ASP.NET MVC !

###

5. Configuration du service WCF

Comme toujours la configuration d’un service WCF se passe dans la section system.serviceModel du fichier de configuration de l’application : ici le Web.config du rôle web !

Tout d’abord, il faut ajouter les extensions propres à l’utilisation du bus des services :

<system.serviceModel>
<extensions>
<bindingExtensions>
<add name="netEventRelayBinding" type="Microsoft.ServiceBus.Configuration.NetEventRelayBindingCollectionElement, Microsoft.ServiceBus, Version=1.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</bindingExtensions>
</extensions>
</system.serviceModel>

Ensuite il faut ajouter la définition du binding netRelayEventBinding (toujours dans system.serviceModel) :

<bindings>
<netEventRelayBinding>
<binding name="default" />
</netEventRelayBinding>
</bindings>

Puis le endpoint du service :

<services>
<service name="MetroBlog.Bll.CacheInvalidator">
<endpoint name="CacheInvalidationEndpoint"
contract="MetroBlog.Interfaces.IRelayCacheInvalidationEventContract"
binding="netEventRelayBinding"
bindingConfiguration="default" />
</service>
</services>

Pour terminer par la configuration du client :

<client>
<endpoint name="CacheInvalidationEndpoint"
contract="MetroBlog.Interfaces.IRelayCacheInvalidationEventContract"
binding="netEventRelayBinding"
bindingConfiguration="default"
/>
</client>

Et voilà ! Si vous avez bien suivi toutes les étapes, vos instances sont toutes capables d’invalider leur cache grâce au multicast de AppFabric Service Bus !

A bientôt image

read more

[EN] [Windows Phone] Best practices for periodic tasks with background agents

As you probably already know Windows Phone 7.1 SDK (Mango) allows to create background agents to realize some operations when the application is not running.

There are two types of tasks : periodic tasks and long running tasks. This post is about periodic tasks that are executed each 30 minutes by the operating system. There are some limitations with the API that may be used in background agent. For further information please go to this MSDN page.

There are some constraints with background periodic tasks :

  • automatically executed by the OS each 30 minutes
  • the operation can’t exceed 25 seconds per run
  • if the phone switch to battery saver mode the background agent may not be executed
  • on some devices only 6 background agents may be planned simultaneously
  • agents can’t use more that 6MB of memory
  • agents have to be re-planned each 2 weeks
  • an agent that crashes two times is automatically disabled by the system

Avoid exception propagation in background agent

Because two crashes will disable the background agent exception handling is really important in the development. For example, common errors occur when using a WebRequest  : the agent creates an HTTP request, the connection is lost, the callback throws an exception that is uncatched ! To avoid this, you can use the following code :

try
{
var httpWebRequest = WebRequest.CreateHttp("http://www.monsite.com/service.aspx");
httpWebRequest.BeginGetRequestStream(asyncResult =>
{
try
{
var responseStream = httpWebRequest.EndGetRequestStream(asyncResult);
//do stuff with the response
}
catch (Exception exception)
{
OnError(exception);
}
}, null);
}
catch (Exception exception)
{
OnError(exception);
}

Schedule a background agent

Background agents are automatically disabled after two weeks : you have to re-schedule them. Windows Phone 7.5 has a centralized interface to manage all background agents that are available on the system so the user can disable an agent without run your application. If you try to schedule a periodic task with a disabled background agent an InvalidOperationException is thrown. You have to take care of this case and catch the exception as demonstrated bellow.

The first step is to get the periodic task by its name :

var periodicTask = ScheduledActionService.Find("AgentDemo") as PeriodicTask;

Next, delete the periodic task if it exists :

if (periodicTask != null)
{
try
{
ScheduledActionService.Remove(PeriodicTaskName);
}
catch (Exception) { }
}

Re-create the periodic task and set the description (it’s mandatory) :

periodicTask = new PeriodicTask("AgentDemo");
periodicTask.Description = "Agent description";

Try to schedule the periodic task :

try
{
ScheduledActionService.Add(periodicTask);
}
catch (InvalidOperationException ioe)
{
if (ioe.Message.Contains("BNS Error: The action is disabled"))
{
//agent is disabled for the application
}
}

Now the agent can be run by the system if it’s not disabled image

Memory usage limit

Background agent can’t use more than 6MB of memory. You can get the current memory usage using the following snippet :

var memory = DeviceStatus.ApplicationMemoryUsageLimit
- DeviceStatus.ApplicationCurrentMemoryUsage;

Hope this helps image

read more