In my previous article I presented how to create a basic window as new feature in the SCCM management console.
Then, I’ll show how to interact with SCCM objects thanks to the SCCM SDK. In this article I’ll show the software distribution part.
Software distribution consists of deploying applications on a set of client computers or servers.
With SCCM, this operation is accomplished thanks to 3 objects :
- A package : this object contains programs that will be executed at deployment. For example, a package called Silverlight could contain 2 programs (an installation program and an uninstallation one). A program of a package is an executable file.
- A collection : this object is a computer container. It is used to group clients thanks to queries such as “Which OS do they run under ?” or “Clients with Silverlight installed”, etc…
- An advertisement : this is the object used to deploy a program of a package on a collection. It is the link between a program’s package and a collection.
As I mentioned in my previous article, the SDK is a WMI .NET wrapper. Every SCCM object in that wrapper is typed as a IResultObject object.
Firstly, to manipulate SCCM objects through the wrapper, you should open/get a connection to the SCCM server in order to process operations on it. In our case, we’ll directly operate inside the SCCM management console (as I explained in my previous post).
You can access the connection manager through a property of our window :
| WqlConnectionManager connection = (WqlConnectionManager)PageData.PropertyManager.ConnectionManager; |
To access properties of an IResultObject object, you should get or set them thanks to an indexer. It means that you access properties with a string. You’ll have to know each of the properties of your object that you are manipulating.
Let’s see an example while creating an advertisement :
| IResultObject myAdvertisement = connection.CreateInstance("SMS_Advertisement"); |
The
CreateInstance method will create an instance of the class that you specified as a parameter. To find the type of the object that you want to create, the msdn will be so helpful ! In fact, you’ll always need the msdn in order to know each property of the objects you want to manipulate. For example, navigate to the
SMS_Advertisement class msdn page.
In this way, you can now set the name of the advertisement by doing this :
| myAdvertisement["AdvertisementName"].StringValue = “My new advertisement”; |
As you can see, properties are not typed, it’s your job to know their type and to chose the value type of the property (StringValue, BooleanValue, etc…).
Another operation that you can do with the SDK is to execute WQL (WMI Query Language) queries. This query language is similar to classic SQL query language.
You just have to call the ExecuteQuery method from the QueryProcessor object of your connection manager object.
| WqlConnectionManager connection = (WqlConnectionManager)PageData.PropertyManager.ConnectionManager; IResultObject result = connection.QueryProcessor.ExecuteQuery(“SELECT * FROM SMS_Advertisement”); |
To dive into something more practical, we can try to get a program from a specific package and assign it to a computer collection through an advertisement :
- First, we’ll create a reusable method in order to execute a WQL query and return its result :
| private IResultObject ExecuteQuery(string query) { try { WqlConnectionManager connection = (WqlConnectionManager)PageData.PropertyManager.ConnectionManager; return connection.QueryProcessor.ExecuteQuery(query); } catch (Exception ex) { MessageBox.Show(ex.Message); return null; } } |
- Then, let’s get a package called “MyPackage” :
| private IResultObject GetMyPackage() { try { IResultObject packages = ExecuteQuery("SELECT * FROM SMS_Package WHERE Name='MyPackage’"); foreach (IResultObject p in packages) { return p; } return null; } catch (Exception ex) { MessageBox.Show(ex.Message); return null; } } |
- We can now retrieve (for example) an “INSTALL” program from this package :
private IResultObject GetInstallPackageProgram(IResultObject package) { try { IResultObject programs = ExecuteQuery(string.Concat(“SELECT * FROM SMS_Program WHERE PackageID=’”, package[“PackageID”].StringValue, “’”)); foreach(IResultObject p in programs) return p; } catch(Exception ex) { MessageBox.Show(ex.Message); return null; } } |
- After that, let’s retrieve a specific collection (precisely its ID) called “MyCollection” where to deploy the advertisement we will create below :
| private string GetMyCollectionID(string collectionName) { try { IResultObject collectionIDs = ExecuteQuery(“SELECT CollectionID FROM SMS_Collection WHERE Name=’MyCollection’”); foreach(IResultObject c in collectionIDs) return c; } catch(Exception ex) { MessageBox.Show(ex.Message); return null; } } |
- At least, we will create the advertisement in order to associate the package program and the collection. With this operation, the program will be deployed on the collection :
| private IResultObject CreateMyAdvertisement() { try { WqlConnectionManager connection = (WqlConnectionManager)PageData.PropertyManager.ConnectionManager; IResultObject myPackage = GetMyPackage(); IResultObject newAdvertisement = connection.CreateInstance("SMS_Advertisement"); newAdvertisement["CollectionID"].StringValue = GetMyCollectionID(); newAdvertisement["AdvertisementName"].StringValue = “MyAdvertisement”; newAdvertisement["PackageID"].StringValue = myPackage[“PackageID”].StringValue; newAdvertisement["ProgramName"].StringValue = GetInstallPackageProgram(myPackage); newAdvertisement.Put(); newAdvertisement.Get(); return newAdvertisement; } catch (Exception ex) { MessageBox.Show(ex.Message); return null; } } |
The Put() method effectively creates the advertisement object in SCCM. You can see it appear in the advertisement list though.
The Get() method refreshes the properties of the current object.
A short briefing about the product itself : “System Center Configuration Manager 2007 R2 comprehensively assesses, deploys, and updates servers, client computers, and devices-across physical, virtual, distributed, and mobile environments”
IT administrators use the administration console in order to process operations on the infrastructure (OS & application deployment, software metering, reporting, etc…). The management console is shown below :

This console is extensible thanks to the SCCM SDK (you can download it here). This SDK consists of a .NET WMI wrapper. This wrapper allow us, for example, to extend the console by adding new menus and/or windows in it. It is also possible to develop tierce applications which interact with SCCM thanks to the provided SDK.
For this first article about SCCM development, I’ll show how to create a new window available in the management console by clicking on a new context menu item.
First, Open Visual Studio => create a Windows Forms Control Library project.

Then, add the following references to the project :
- admin.wqlqueryengine.dll
- microsoft.configurationmanagement.dll
- microsoft.configurationmanagement.managementprovider.dll
- Microsoft.ManagementConsole.dll
Note : These dll are present in the SCCM installation folder : “\Microsoft Configuration Manager\AdminUI\bin\”
After that, modify the base class of the windows forms. In SCCM our window will not inherit from “UserControl” but from SmsCustomDialog.
Now, change the namespace of the application to include the following base namespace : Microsoft.ConfigurationManagement.AdminConsole.
In my example, the namespace of the application would be “Microsoft.ConfigurationManagement.AdminConsole.MyFirstSccmApplication”.
Override the Initialize method. This method will get the data context of the management console from which it has been called.
Now, you can create the design of your window as if you were developing a classical windows form.

As the screenshot above shows, we’ll do it easy first ! When clicking on the button a MessageBox will appear. A classical and mythical “Hello World” will appear.
Here is the code-behind :
|
public partial class SayHelloWindow: SmsCustomDialog { public SayHelloWindow() { InitializeComponent(); }
public override bool Initialize(System.Reflection.Assembly assembly, SmsFormData propertySheet, SmsPageData pageData) { base.Initialize(assembly, propertySheet, pageData); return true; }
private void btnSayHello_Click(object sender, EventArgs e) { MessageBox.Show("Hello world !!"); } }
|
The big question is now : How can we access to that beautiful and so functional window ?!
First, copy all assemblies resulting from the compilation of the VS project and paste them to the bin folder of the management console : “\Microsoft Configuration Manager\AdminUI\bin”
Custom extensions that you develop will be available in the management console by editing two XML files though:
- One file to reference the assembly of the custom window (SayHelloDialog.xml) :
<?xml version="1.0" encoding="utf-8"?> <SmsFormData FormatVersion="1.0" xmlns=”http://schemas.microsoft.com/SystemsManagementServer/2005/03/ConsoleFramework”> <Form Id="{ED8B671C-64E4-4ffd-BC99-8CC185195D3C}" CustomData="User Properties" FormType="CustomDialog" > <Assembly Name="MyFirstSccmApplication" Namespace="Microsoft.ConfigurationManagement.AdminConsole.MyFirstSccmApplication" ClassType="SayHelloWindow"/> </Form> </SmsFormData> |
- One file to create the context menu item on which the window can be instanciated (SayHelloAction.xml) :
|
<ActionDescription Class="ShowDialog" DisplayName="Say Hello" MnemonicDisplayName="Mnemonic" Description="Say Hello to the world"> <DialogId>SayHelloDialog</DialogId> </ActionDescription>
|
Note: The value of the “DialogId” tag in the second XML file should match the name of the first XML file.
Note (bis): The value of the “Id” attribute of the “Form” tag is manually generated thanks to the guidgen.exe tool.
The two files are located in the following folders:
- SayHelloActions.xml => “\Microsoft Configuration Manager\AdminUI\XmlStorage\Extensions\Actions\{GUID}\”
- SayHelloDialog.xml => “\Microsoft Configuration Manager\AdminUI\XmlStorage\Extensions\Forms\”
{GUID} => This is the GUID corresponding to the object which the window will appear.
For example, to enable a new context menu item while right clicking on a package in the management console, you’ll have to put the XML file in “\Microsoft Configuration Manager\AdminUI\XmlStorage\Extensions\Actions\3ad39fd0-efd6-11d0-bdcf-00a0c909fdd7\”.
The list of the useful GUID can be found here.
Then you should have the following results 


Access to the part 2 of my posts about SCCM development here.
Vous souhaitez découvrir les nouvelles technologies Microsoft, les ExaTech Days sont là pour vous !
Venez nous rejoindre à Toulouse le 8 Juin 2010 :

Et à Nantes le 15 Juin 2010 :
J’animerai une session sur Windows Phone 7 à Toulouse et à Nantes en collaboration avec Julien Dollon.
Tout a commencé il y a un peu plus d’un an lorsque Julien, Olivier et moi-même avons décidé de participer au concours Imagine Cup. Passionnés par les technologies Microsoft et en particulier par les technologies .NET, il va de soi que participer au plus grand concours sur les nouvelles technologies organisé par Microsoft est un beau challenge !
De plus, étant donné que nous sommes dans la même classe et que nous travaillions alors sur un projet commun à savoir la communauté Dotnet-France, nous ne pouvions pas ne pas y participer ! Mais pour avoir une équipe complète, il nous manquait un membre + un mentor. Nous nous sommes alors tournés vers deux personnes que nous connaissions de SUPINFO : Yann Lautredou (à l’époque directeur du laboratoire .NET de SUPINFO) en tant que mentor et Mauricio Diaz Orlich (à l’époque directeur du laboratoire Web&Dev de SUPINFO).
Atout supplémentaire pour l’équipe, Mauricio étant MSP, il faisait grimper le quota à 3 MSP au total dans l’équipe en plus de Julien et Olivier.
![clip_image002[4] clip_image002[4]](http://blogs.dotnet-france.com/bertrandv/image.axd?picture=clip_image002%5B4%5D_thumb.jpg)
De gauche à droite, Olivier Courtois, Julien Dollon, Vincent Bouatou (Microsoftee), Mauricio Diaz Orlich et Bertrand Vergnault
Pour rappel voici le thème de l’année : « Imaginez un monde où la technologie nous aide à répondre aux enjeux les plus cruciaux de notre société ».
Ce thème étant très vaste, nous avons mis du temps pour nous focaliser sur une problématique et en ressortir un réel projet à présenter pour ce concours : une solution de protection des enfants sur Internet.
Comment en sommes-nous arrivés à la définition de ce projet ? Olivier ayant travaillé pendant plusieurs années avec l’association Docteur Souris dont le but est d’apporter les nouvelles technologies dont Internet aux enfants hospitalisés de longue durée, une problématique est très vite ressortie : Comment assurer la sécurité des enfants sur Internet de façon fiable et sûre ?
C’est donc à cette problématique que nous avons souhaité apporter un élément de réponse et de le présenter au concours Imagine Cup dans la catégorie Software Design, catégorie reine de la compétition.
Concernant, la définition du projet et des partenaires, je vous renvoie vers l’article d’Olivier où sont exposés tous les documents que l’on a rendu pour la compétition.
En ce qui concerne la répartition des rôles, il a été défini deux chefs de projet à savoir Olivier et Julien. Olivier s’occupant des relations avec le partenaire principal (Docteur Souris) ainsi que de la partie communication externe. Julien pris la responsabilité technique du projet ainsi que le rôle de designer de l’équipe.
Concernant le développement des applications composant la solution de protection des enfants sur Internet, elle a été divisé comme suit : un développeur pour le site web de la communauté réalisé à l’aide de SharePoint 2007, un développeur sur la partie moteur communautaire permettant de centraliser et d’analyser tous les résultats des évaluations des sites web testés, un développeur sur la partie contrôle parental PC qui consiste en le client installé sur l’ordinateur familial et qui permet d’analyser et de rediriger en cas de besoin le trafic http et enfin un développeur dont le rôle était de développer les différents « bookmarklets » permettant à un utilisateur de pouvoir soumettre et de pouvoir noter un site très facilement.
Grâce à ce projet, nous avons eu la chance de pouvoir être sélectionné pour la finale française de la compétition. Pour cela, il a fallu rédiger un document d’une quinzaine de page (disponible sur le blog d’Olivier) permettant de présenter l’équipe, la problématique choisie, la solution à cette problématique ainsi que les technologies employées pour arriver à nos fins.
Nous faisions donc partie des 6 équipes finalistes et afin de nous préparer au mieux pour le grand moment de la soutenance devant le jury de la finale française, Microsoft avait organisé un week-end de coaching pour toutes les équipes retenues.
Ce bootcamp a été organisé dans un grand hôtel en banlieue parisienne…une sorte de mise au vert avant le grand rendez-vous !
Au programme du week-end : échanges avec des membres de la DPE de Microsoft à propos de la problématique et des technologies employées pour la résoudre, mise en place d’un « elevator pitch » permettant de vendre notre projet en quelques mots ainsi qu’un travail de réflexion sur la mise en place d’un business plan pour notre solution.

Salles d’ateliers durant le bootcamp
Nous avons donc pu nous rendre compte que l’on avait absolument pas assez bossé…et les membres de la DPE qui étaient présents ne se sont pas gênés pour nous le faire remarquer :D Tout ceci bien sûr dans l’optique de nous donner un coup de fouet pour que l’on se mette à 300% sur le projet !
Ce week-end a été conclu par un passage devant un jury blanc afin de nous entrainer à la mise en place de notre discours durant la finale française.

Nos deux chefs de projet ;)
Pour notre équipe, ce week-end de coaching a constitué une étape importante puisqu’il s’agissait en fait de la première vraie rencontre entre tous les membres de l’équipe : Mauricio et Yann étant basés à Paris, nous n’avions pas pu jusqu’alors nous rassembler ! L’effet de cohésion dans l’équipe ne s’en ai vu qu’augmentée après ce week-end ;)
Après ce bootcamp intense, nous nous sommes donc remis au travail de plus belle afin d’être prêt pour la finale française qui avait lieu dans les locaux de la DPE, rue de l’Université à Paris.
Mais dans l’optique de réaliser une prestation de grande qualité, Olivier, Julien et moi avons rejoint Mauricio et Yann à Paris 3 jours avant le jour de la finale. SUPINFO nous a accueilli dans ses locaux rue de Bassano où l’on a pu préparer notre présentation : les slides, les démos, le story-telling, etc…devant plusieurs membres de l’administration comme Marc Pybourdin, Thierry Boidart ainsi que certains des directeurs de labo de SUPINFO. Durant ces 3 jours de préparation, nous avons modifié, déplacé, supprimé, réajusté les démos, les diapos de présentation, etc…afin d’obtenir le résultat présent sur le blog d’Olivier (en ce qui concerne la présentation en elle-même).
Puis le jour de la finale tant attendue arriva : attente insoutenable dans les locaux de la DPE puis premier passage devant un premier jury composé entre autres de Vincent Bellet et Pascal Belaud. La présentation se passe à merveille : Mauricio enchaîne le speech en anglais, les démos passent nickel ainsi que l’engouement du jury lors des réponses à leurs questions.
Mais ce n’est pas fini, il reste un second jury à convaincre !!...Il reste encore 20 minutes de présentation + 10 minutes de réponse aux questions avant d’aller pouvoir se détendre et profiter de la réception organisée par MS :D
Le second jury est composé de responsables d’associations ainsi que Guillaume Belmas, MVP. Ce second jury nous a valu quelques frayeurs et nous l’avons senti moins convaincu face à notre propos mais cependant, nous étions plutôt contents de nos deux prestations.
Une fois ce moment passé, direction le premier étage de la Tour Eiffel : Microsoft aime faire les choses en grand et c’est dans ce symbole parisien que nous avons pu fêter et faire partager notre projet aux invités. Chaque équipe avait en effet à disposition un stand lui permettant d’exposer son projet aux différents journalistes, Microsoftees, personnages politiques, etc…présents lors de cette réception.
Vint ensuite le moment tant redouté de l’annonce des résultats…ce moment qui nous a valu une terrible déception (nous souhaitions évidemment la première place !) : nous sommes annoncé comme 3ème !...médaille de bronze…le billet vers la finale mondiale au Caire en Egypte nous passe sous le nez !

Notre “médaille” pour la 3ème place à la finale française
Nous repartons alors un peu déçu mais avec notre lot de consolation sous le bras (une Xbox 360)…
Ce n’est seulement que le lendemain où nous discutons avec les autres membres de l’équipe et poussé par Vincent Bouatou pour participer à un des awards organisé durant le concours. L’award en question se prénommant : H.E. Mrs. Suzanne Mubarak Special Award. En effet, la femme du Président Egyptien étant fondatrice d’une fondation pour la protection des enfants, l’égalité des femmes, etc…et dont le sujet de cet award devait rassembler les 5 meilleures équipes parmi celles du monde entier de la catégorie Software Design qui répondaient aux buts de cette fondation, nous avons donc pu nous inscrire à cette catégorie.
Il a fallu rédiger de nouveau un document, de 5 pages maximum, expliquant notre projet.
Une semaine plus tard nous avons eu la très très bonne surprise d’apprendre que nous avions été sélectionné directement pour la finale mondiale au Caire en Egypte parmi les 94 équipes qui s’étaient présentées pour cette catégorie.
Nous prenons notre revanche sur la déception de la finale française !...A nous le Caire !!!
Nous avons pu aussi voir nos adversaires : 4 autres équipes de nationalité américaine, égyptienne, polonaise et une équipe indonésienne.
La finale mondiale a été une semaine exceptionnelle : entre l’hôtel 5 étoiles luxueux, les visites des pyramides et du sphinx, les échanges avec les étudiants du monde entier et pour finir en apothéose avec le World Festival devant les pyramides et la remise des prix !!

L’équipe en compagnie de Vincent Bouatou devant notre stand à la finale mondiale
Cette expérience a été pour nous l’une des plus riches de notre vie. Non seulement en termes de découverte du monde (différentes cultures) mais aussi sur la conduite de projet, technique et surtout le fait de porter une idée et de se battre pour que l’on le croit en nous.
Auteur : Bertrand Vergnault
Co-Auteur : Julien Dollon

Remise du prix pour la 3ème place à la finale mondiale (on peut noter que Mauricio se prépare à twitter l’info :D )

World Festival devant les Pyramides
C’est aujourd’hui que j’ai pu recevoir la très bonne nouvelle !
Je rejoins avec le plus grand honneur et plaisir la grande communauté des MSP :)
Merci à Microsoft de m’accorder toute leur confiance.
Je tiens à remercier tous les MSP/MVP de Dotnet-France qui ont pu me soutenir et en particulier une personne qui m’est chère : Julien Dollon.
Alors qu’un collègue admin dont je ne citerai pas le nom souhaitait savoir comment réaliser ceci, je me suis dit qu’un petit coup de pouce de la part d’un développeur serait sympa !! :D
Tout d’abord, il faut ajouter la référence Sytem.Management.Automation à notre application. Hors, le problème est qu’elle ne nous est pas proposée dans la liste des références disponibles. Cependant, nous allons quand même pouvoir la référencer éditant le fichier csproj à la main avec le bloc notes.
Voici la ligne à ajouter à l’intérieur de la balise ItemGroup :
<Reference Include="System.Management.Automation" />
A la réouverture de notre projet, la référence est maintenant bien ajoutée et il faut ensuite ajouter l’espace de nom à notre classe :
using System.Management.Automation;
Rentrons maintenant dans le vif du sujet :
J’ai créé, pour l’exemple, une classe CommandResult qui contient deux propriétés : Nom et Definition :
public class CommandResult
{
public string Name { get; set; }
public string Definition { get; set; }
}
J’ai créé aussi une classe CommandManager qui contient une méthode GetPSCommands permettant de renvoyer une liste de CommandResult correspondant à toutes les commandes existants en PowerShell :
public class CommandManager
{
public List<CommandResult> GetPSCommands()
{
//On créé un pipeline powershell permettant d'exécuter des commandes
PowerShell powershell = PowerShell.Create();
//On ajoute la commande souhaitée
powershell.AddCommand("get-command");
//On exécute la commande
IAsyncResult result = powershell.BeginInvoke();
PSDataCollection<PSObject> lstPSData = powershell.EndInvoke(result);
List<CommandResult> lstResults = new List<CommandResult>();
if (!lstPSData.Count.Equals(0))
//On récupère les membres souhaités de chaque résultat
lstResults = (from o in lstPSData
select new CommandResult()
{
Definition = o.Members["Definition"].Value.ToString(),
Name = o.Members["Name"].Value.ToString()
}).ToList();
return lstResults;
}
}
Plus d’infos à propos des types de chaque objet utilisé sur la msdn.
Maintenant nous allons afficher les résultats dans une simple ListView d’une application WPF :
Voilà pour le côté XAML :
<Grid>
<ListView x:Name="lstResultCommand">
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Path=Name}" />
<GridViewColumn DisplayMemberBinding="{Binding Path=Definition}" />
</GridView>
</ListView.View>
</ListView>
</Grid>
Voilà pour le côté code-behind :
public Window1()
{
InitializeComponent();
this.lstResultCommand.ItemsSource = new CommandManager().GetPSCommands();
}
Et maintenant voici le résultat :

Aujourd’hui vient de sortir Silverlight 3 en version RTW avec le numéro de version 3.0.40624.0.
Il est possible de le télécharger sur le site officiel.
Vous pourrez retrouver les nouveautés de Silverlight 3 dans cet article de Julien Dollon.
Ayant développé une application WPF que je trouvai très gourmande en ressources, j’ai eu à profiler celle-ci afin de savoir précisément quelles animations ou quels composants consommaient trop de ressources.
Pour cela, un outil très performant et très puissant m’a permis de réaliser cela : la WPF Performance Suite présent dans le SDK de Windows.
Pour vous éviter d’avoir à télécharger tout le SDK voici le msi directement téléchargeable ici.
Cette application se compose de plusieurs fonctionnalités de profilage organisable par onglets :
Le premier onglet contenant l’application Perforator va vous permettre d’analyser le rendu de votre application : vous pourrez observer le rafraichissement de vos animations, le nombre de frames/seconde, etc…
La seconde application est Visual Profiler. Cette application va vous permettre de profiler les services WPF permettant la gestion des évènements et la disposition des éléments dans votre application.
Je ne présenterai que l’application Perforator qui m’a le plus aidé dans mon cas. Pour les autres applications, je vous conseille l’article de la msdn qui est très bien fait à ce sujet.
Perforator vous permet, par exemple, en temps réel, de modifier les paramètres de rendu de votre application afin d’observer les fluctuations que cela apporte. De plus, chose très intéressante dans mon cas, les rafraichissement de chaque composant de votre application est mis en avant grâce à une coloration de ces composants. A chaque rafraichissement du composant, celui-ci change de couleur. Pour cela, il faut activer l’option : “Show dirty region update overlay”. Voici ce que l’on observe :
En passant sur un des boutons, on déclenche une animation et la zone d’animation se colore d’une couleur différente à chaque rafraichissement, c’est-à-dire très rapidement !
On peut donc facilement observer les animations consommatrices de ressources par exemple.
Ces outils sont donc très puissants et je vous recommande de lire l’article de la msdn que j’ai précité plus haut pour avoir une vision complète de tout ce qu'il est possible de visualiser à l'aide de cette d'outils. Je n’ai en effet délibérément présenté qu’une des nombreuses fonctionnalités de cette suite.
Depuis ce matin, le moteur de recherche Bing de Microsoft est disponible en version bêta.
Parmi les fonctionnalités intéressantes :
- Filtre des résultats d’images suivants plusieurs critères tels que la taille, la couleur (N&B ou couleur), le type d’image ainsi que la disposition :
- De même pour les vidéos :
- Pour concurrencer Google Maps, il y a bien sûr accès à Microsoft Virtual Earth reprenant la même interface que Live Search Maps :
Enfin, Bing intègre un contrôle parental avec deux niveaux de filtrages : Modéré et Strict.
Maintenant à vous de le tester !
Sur son blog ScottGu's publie aujourd'hui un article concernant la mise à disposition d'un tutorial ASP.NET MVC au format HTML. Beaucoup plus lisible qu'un simple PDF ;)
Retrouvez donc ce tutorial à cette adresse : http://weblogs.asp.net/scottgu/archive/2009/04/28/free-asp-net-mvc-nerddinner-tutorial-now-in-html.aspx