Home - About me - Browse by categories

[Azure] Invalidation de settings ou de cache à l’aide d’une clé de configuration

Dans ce post je vais vous expliquer une technique que j’ai utilisée pour invalider le cache / recharger les settings sur toutes les instances du rôle Web qui héberge mon blog (en vrai il n’y en a qu’une seule, mais je trouve l’astuce sympa image)

Le constat est simple : mes posts et les settings du blog (email, smtp, etc…) sont persistés dans le stockage table de Windows Azure. Afin d’éviter les aller-retours vers le stockage par table, je monte tout en cache mémoire (le nombre de transaction est facturé et en plus du coup ça envoi du lourd en terme de perf).

Problème : si je change un settings dans mon storage, comment est-ce que je demande à mon service de recharger les données ? Idem si pour une raison x ou y je souhaite vider le cache de posts, je dois avoir une solution. Si on se place dans un contexte Windows Azure multi-instances (cas très fréquent) c’est une couche de complexité supplémentaire qui se rajoute car il faut notifier chaque instance !

La solution la plus simple est d’utiliser un setting Windows Azure et de faire en sorte que vos instances écoutent les changements de configuration. Dès lors, il suffit de détecter le changement de la bonne clé de settings, ConfigVersion dans mon cas (ou CléBidon si vous voulez) et de reinitialiser vos différents services (ici mon service de cache et mon service de settings).

Tout cela se passe dans le fichier WebRole.cs du webRole, via l’événement Changed de RoleEnvironment :

public class WebRole : RoleEntryPoint
{
public override bool OnStart()
{
// For information on handling configuration changes
// see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
RoleEnvironment.Changed += OnRoleEnvironmentChanged;
return base.OnStart();
}

private void OnRoleEnvironmentChanged(object sender, RoleEnvironmentChangedEventArgs e)
{
if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange)) {
foreach (var change in e.Changes.OfType<RoleEnvironmentConfigurationSettingChange>()) {
if (change.ConfigurationSettingName == "ConfigVersion")
{
var cacheService = UnityRoot.Container.Resolve<ICacheService>();
cacheService.InvalidateCache();
var settingsManager = UnityRoot.Container.Resolve<ISettingsManager>();
settingsManager.Reload();
}
}
}
}
}

A bientôt image

Technorati Tags: [windows](http://technorati.com/tags/windows),[windows](http://technorati.com/tags/windows),[windows](http://technorati.com/tags/windows)
read more

[Livre] MVVM : De la découverte à la maîtrise

Un billet rapide pour vous présenter un ouvrage dédié au pattern MVVM et à son utilisation dans le cadre de projets WPF/Silverlight et Silverlight pour Windows Phone.

image

Coécrit par deux collègues et amis Jonathan Antoine et Jonathan Antoine, ce livre s’adresse à toutes personnes désireuses de découvrir MVVM ou d’approfondir leurs connaissances sur le sujet.

Bien que je n’ai pas encore lu tout l’ouvrage (sorti aujourd’hui même), j’ai eu l’occasion de participer à la relecture de certains chapitres de celui-ci et j’ai énormément apprécié l’approche des auteurs : du pratique, du concret et la réalité du terrain concernant MVVM !

Pour en savoir plus c’est par là : http://www.digitbooks.fr/catalogue/mvvm-antoine-lebrun.html

Bravo à Jon et Tom, et surtout, bonne lecture à tous !

A bientôt ! image

Technorati Tags: [livre](http://technorati.com/tags/livre),[livre](http://technorati.com/tags/livre),[livre](http://technorati.com/tags/livre),[livre](http://technorati.com/tags/livre),[livre](http://technorati.com/tags/livre),[livre](http://technorati.com/tags/livre),[livre](http://technorati.com/tags/livre),[livre](http://technorati.com/tags/livre),[livre](http://technorati.com/tags/livre),[livre](http://technorati.com/tags/livre)
read more

[EN] [ASP.NET MVC 4] Asynchronous controllers

Asynchronous execution is the future of Windows development : it has been largely demonstrated during the //Build conference two weeks ago.

In previous versions of ASP.NET MVC it was possible to create asynchronous controllers by inheriting the AsyncController class and using some conventions :

  • MyActionAsync : method that returns void and launches an asynchronous process
  • MyActionCompleted : method that returns an ActionResult (the result of the MVC action MyAction, in this case)

To allow the MVC engine to manage asynchronous operations and pass the result to the view engine, developers had to use the propery AsyncManager of the AsyncController. The completed method parameters was passed by the MVC engine through this object.

For example, the controller that is defined bellow allows to get a Json-serialized list of movies – asynchronously – from an OData service :

public class MoviesController : AsyncController
{
public ActionResult Index()
{
return View();
}

public void GetJsonMoviesAsync(int? page)
{
const int pageSize = 20;
int skip = pageSize * ((page ?? 1) - 1);
string url = string.Format("http://odata.netflix.com/[…]&$skip={0}&$top={1}",
skip, pageSize);

//the asynchronous operation is declared
AsyncManager.OutstandingOperations.Increment();

var webClient = new WebClient();
webClient.DownloadStringCompleted += OnWebClientDownloadStringCompleted;
webClient.DownloadStringAsync(new Uri(url));//the asynchronous process is launched
}

private void OnWebClientDownloadStringCompleted(object sender,
DownloadStringCompletedEventArgs e)
{
//the asynchronous process ends
//"movies" result is added to the parameters of the AsyncManager
//NB : it's the name of the parameter that is take by the
//GetJsonMoviesCompleted method
List<Movie> movies = null;
if (AsyncManager.Parameters.ContainsKey("movies"))
{
movies = (List<Movie>)AsyncManager.Parameters["movies"];
movies.Clear();
}
else
{
movies = new List<Movie>();
AsyncManager.Parameters["movies"] = movies;
}

movies.AddRange(Movie.FromXml(e.Result));

//the ends of the asynchronous operation (launches the call of "Action"Completed)
AsyncManager.OutstandingOperations.Decrement();
}

public ActionResult GetJsonMoviesCompleted(List<Movie> movies)
{
//on retourne le résultat Json
return Json(movies, JsonRequestBehavior.AllowGet);
}
}

It’s not really complicated to create an asynchronous controller but ASP.NET MVC 4 and C# 5 with the new async and await keywords will make it easier !

public class MoviesController : AsyncController
{
public ActionResult Index()
{
return View();
}

public async Task<ActionResult> GetJsonMovies(int? page)
{
const int pageSize = 20;
int skip = pageSize * ((page ?? 1) - 1);
string.Format("http://odata.netflix.com/[…]&$skip={0}&$top={1}",
skip, pageSize);

var webClient = new WebClient();
string xmlResult = await webClient.DownloadStringTaskAsync(url);
return Json(Movie.FromXml(xmlResult), JsonRequestBehavior.AllowGet);
}
}

As you can see in the previous code snippet, in ASP.NET MVC 4 you always should inherits from AsyncController but there is no more naming conventions, no more Async/Completed methods, no more AsyncManager and the action returns a Task instead of an ActionResult !

It’s awesome !

Hope this helps image

read more

[ASP.NET MVC 4] Contrôleurs asynchrones !

On le sait, cela a été largement abordé il y a deux semaines lors de la //Build conférence : le futur du développement est dans l’asynchrone.

Bien entendu, il était déjà possible de réaliser des contrôleur asynchrone dans les versions précédente d’ASP.NET MVC et ce en dérivant nos contrôleurs de la classe AsyncController. Le moteur MVC se basait alors sur des conventions :

  • MonActionAsync : méthode qui retourne void et qui démarre un traitement asynchrone
  • MonActionCompleted : méthode qui retourne un ActionResult (le résultat de l’action MVC MonAction, dans ce cas).

Afin de synchroniser le tout, l’AsyncController fournissait une propriété AsyncManager permettant notamment au moteur MVC de connaître le nombre d’opération asynchrone en cours, de gérer celles-ci et de passer les paramètres à la méthode de retour d’action (MonActionCompleted) à la fin du traitement asynchrone, et ce pour retourner le résultat.

Par exemple, le contrôleur ci-dessous expose une action GetJSonMovies asynchrone, qui se charge d’aller récupérer une liste de films via un flux OData :

public class MoviesController : AsyncController
{
public ActionResult Index()
{
return View();
}

public void GetJsonMoviesAsync(int? page)
{
const int pageSize = 20;
int skip = pageSize * ((page ?? 1) - 1);
string url = string.Format("http://odata.netflix.com/[…]&$skip={0}&$top={1}",
skip, pageSize);

//on "déclare" l'opération asynchrone
AsyncManager.OutstandingOperations.Increment();

var webClient = new WebClient();
webClient.DownloadStringCompleted += OnWebClientDownloadStringCompleted;
webClient.DownloadStringAsync(new Uri(url));//on lance le traitement asynchrone
}

private void OnWebClientDownloadStringCompleted(object sender,
DownloadStringCompletedEventArgs e)
{
//le traitement asynchrone se termine
//on rajoute le résultat "movies" au paramètre du AsyncManager
//NB : il s'agit du nom du paramètre de la méthode GetJsonMoviesCompleted !!
List<Movie> movies = null;
if (AsyncManager.Parameters.ContainsKey("movies"))
{
movies = (List<Movie>)AsyncManager.Parameters["movies"];
movies.Clear();
}
else
{
movies = new List<Movie>();
AsyncManager.Parameters["movies"] = movies;
}

movies.AddRange(Movie.FromXml(e.Result));

//on indique que l'opération se termine (déclenche l'appel du "Action"Completed)
AsyncManager.OutstandingOperations.Decrement();
}

public ActionResult GetJsonMoviesCompleted(List<Movie> movies)
{
//on retourne le résultat Json
return Json(movies, JsonRequestBehavior.AllowGet);
}
}

Nous sommes d’accord, ce code n’est pas extrêment compliqué, mais ASP.NET MVC 4, par le biais des nouveautés de C# 5 et de l’utilisation des mots clés async et await va grandement le simplifier, comme il est possible de le constater ci-dessous :

public class MoviesController : AsyncController
{
public ActionResult Index()
{
return View();
}

public async Task<ActionResult> GetJsonMovies(int? page)
{
const int pageSize = 20;
int skip = pageSize * ((page ?? 1) - 1);
string.Format("http://odata.netflix.com/[…]&$skip={0}&$top={1}",
skip, pageSize);

var webClient = new WebClient();
string xmlResult = await webClient.DownloadStringTaskAsync(url);
return Json(Movie.FromXml(xmlResult), JsonRequestBehavior.AllowGet);
}
}

Comme vous pouvez le voir, en ASP.NET MVC 4 on continue à dériver AsyncController, en revanche plus besoin de faire appelle à l’AsyncManager ou même d’utiliser des conventions Action**Async**/Action**Completed** ! Notez également que la méthode ne retourne plus un ActionResult mais un Task (induit par l’utilisation de async et await).

Franchement, ça poutre !

A bientôt image

read more

[EN] [ASP.NET MVC] Handle HTTP errors

This subject seems to be really basic when developing a web application but it seems that it’s very discussed on the web too. In a lot of forum threads or blog posts we can find very various methods to handle HTTP exception within an ASP.NET MVC application. This post exposes a way to do that. I’m not pretending that it’s the best way but I think that it’s an elegant one image (so don’t hesitate to comment on this post if you’ve remarks or suggestions).

What’s the real need ?

I think that developers should manage HttpException in an other way than other exceptions for 3 main reasons :

    - Respect of web-standards (a not found error returns a 404 http code, that’s it !) - SEO : search engines use http codes (because it’s standards) to build their indexes. - The user : a user-friendly page is already better than a stack trace…

I think that the most important is that the error code is well returned by the server : for example the URL http://www.mywebsite.com/Pages/some-page-that-does-not-exists is called the server should return a 404 status code and not a 302 (found) followed by a 200 (or 404) from a specific error page like http://www.mywebsite.com/Errors/Error404).

When HttpException are thrown in an ASP.NET MVC application ?

HttpException are thrown by the ASP.NET MVC engine or by the application code, directly in the asp.net controllers of your apps :

throw new HttpException(404, "Not found");

In some cases, they can also be thrown by the server (for internal errors, for example). But all HttpException can be handled in the application.

How to handle these exceptions ?

After a lot of researches and some tests I think that http exceptions should be handled in two places :

    - In a base controller inherited by all the controllers of the application - In the Global.asax file

Handle http exception in the controller :

Exceptions that are thrown by the developer directly in the application code can be handle in a base controller. For example :

public ActionResult Product(int id)
{
var product = _unitOfWork.GetProduct(id);
if(product == null)
throw new HttpException(404, "Le produit est introuvable");

return View(product);
}

By inheriting the System.Web.Mvc.Controller class it’s possible to override an OnException method. This method is called when an exception occurs in a controller method (action) :

protected override void OnException(ExceptionContext filterContext) {
base.OnException(filterContext);

if (filterContext.Exception != null) {
filterContext.ExceptionHandled = true;

if (filterContext.Exception is HttpException) {
if (!ControllerContext.RouteData.Values.ContainsKey("error")) {
ControllerContext.RouteData.Values.Add("error", filterContext.Exception);
}

var httpException = (HttpException) filterContext.Exception;

switch (httpException.GetHttpCode()) {
case 404:
filterContext.HttpContext.Response.StatusCode = 404;
filterContext.HttpContext.Response.StatusDescription = httpException.Message;
View("Error404", null).ExecuteResult(ControllerContext);
break;
case 500:
filterContext.HttpContext.Response.StatusCode = 500;
filterContext.HttpContext.Response.StatusDescription = httpException.Message;
View("Error500", null).ExecuteResult(ControllerContext);
break;
default:
filterContext.HttpContext.Response.StatusDescription = httpException.Message;
View("GenericError", null).ExecuteResult(ControllerContext);
break;
}
}

//autre traitement si pas HttpException (log par exemple...)
}
}

As you can see in this code snippet the first step is to check that the exception is an HttpException. If yes, a redirection to an appropriate error page is done just after setting the status code and status description of the http response. The views are in the Shared folder of the application.

Now http exceptions that are thrown in a controller return the good status code and redirect to a user friendly page.

Handle HTTP exceptions in the Global.asax :

It’s in the Global.asax file that all other http exception are handled. To to that you should subscribe to the Error event of the mvc application (in the Init method override) :

public override void Init()
{
base.Init();
this.Error += new EventHandler(MvcApplication_Error);
}

In the Error event handler, initialize an errors-dedicated controller and create appropriate route data to work with the error :

var routeData = new RouteData();
routeData.Values.Add("controller", "Errors");

var lastException = Server.GetLastError();

if (lastException is HttpException) {
var httpException = (HttpException) lastException;
switch(httpException.GetHttpCode()) {
case 404:
routeData.Values.Add("action", "Error404");
break;
case 500:
routeData.Values.Add("action", "Error500");
break;
default:
routeData.Values.Add("action", "GenericError");
break;
}
}
else
{
routeData.Values.Add("action", "GenericError");
}

routeData.Values.Add("exception", lastException);

Server.ClearError();

IController errorController = _unityContainer.Resolve<ErrorsController>();
errorController.Execute(new RequestContext(
new HttpContextWrapper(Context), routeData));

The ErrorsController :

public class ErrorsController : Controller
{
public ActionResult Error404() {
Response.StatusCode = 404;
Exception exception = null;
if(RouteData.Values.ContainsKey("exception")) {
exception = (Exception) RouteData.Values["exception"];
}
return View(exception);
}

public ActionResult Error500() {
Response.StatusCode = 500;
Exception exception = null;
if (RouteData.Values.ContainsKey("exception"))
{
exception = (Exception)RouteData.Values["exception"];
}
return View(exception);
}

public ActionResult GenericError() {
Exception exception = null;
if (RouteData.Values.ContainsKey("exception"))
{
exception = (Exception)RouteData.Values["exception"];
}
return View(exception);
}
}

As you can see each action defines itself the http status code of the http response.

Now all http exceptions are handled in a user and SEO friendly way in your ASP.NET MVC applications !

Hope this helps image

read more