01 Feb 2013 in
ASP.NET MVC
|
Windows Phone
L’info ne vous a surement pas échapée, les Techdays 2013 commencent dans un peu plus d’une semaine maintenant, le 12 Février !
J’aurais la chance d’animer deux sessions lors de cette nouvelle édition :
- Introduction au développement Windows Phone 8 : avec Introduction au développement Windows Phone 8 (Microsoft), nous vous donnerons tous les pointeurs pour bien démarrer vos applications Windows Phone ! De l’installation des outils, en passant par la création d’un premier projet jusqu’à la création de votre compte développeur et à la publication d’une application sur le Windows Phone store, nous essayerons de vous donner une bonne vue d’ensemble de la plateforme Windows Phone, pour les développeurs !
- Quoi de neuf dans ASP.NET MVC 4 : avec Quoi de neuf dans ASP.NET MVC 4 (Infinite Square), nous ferons un tour d’horizon des nouveautés d’ASP.NET MVC 4, avec de nombreuses démonstrations au programme : async/await, templates mobile, bundling, open auth et bien d’autres ! Un coktail de démos pour bien prendre en main toutes ces nouveautés !
Rendez-vous au Palais des Congrès le 12 !
Julien
read more
21 Dec 2012 in
ASP.NET MVC
|
Web Development
Lorsque l’on développe une Single Page Application (SPA) en JavaScript, il est souvent recommandé de mettre en place la gestion du bouton back pour l’historique de navigation, ainsi que de la navigation par fragment, permettant de conserver des URL propres à chaque ressource et permettant ainsi aux utilisateur d’utiliser la SPA comme n’importe qu’elle autre application.
Comprendre la navigation par fragment
Il s’agit en fait des éléments que l’on rajoute à une URL de page, après le caractère #
. On parle aussi d’ancre dans la page. Par exemple, le lien suivant http://www.monsite.com/page1.html#menu, permet de rediriger l’utilisateur directement vers une section de le page.
Ce système existant dans HTML depuis de nombreuses années a été ré-exploité en JavaScript pour de la navigation par fragment. Par exemple, l’équivalent de la page http://www.monsite.com/customers/32, qui affiche le détail du client ayant 32 pour id, peut se retrouver sous la forme de http://www.monsite.com/customers/32 afin d’être exploité directement depuis du code JavaScript. Les éléments qui suivent le caractère #
représente le hash
de l’URL.
Il suffit donc d’avoir un mécanisme en JavaScript pour détecter les changements de hash et permettre à l’utilisateur de passer de ressource en ressource à l’aide des boutons précédent / suivant du navigateur, de mettre une ressource en favoris, d’envoyer une ressource par mail à un autre utilisateur, etc…
C’est ce que permet de faire le plugin jQuery BBQ : http://benalman.com/projects/jquery-bbq-plugin/
Mise en place de jQuery BBQ
Commencez par télécharger les sources du plugin ici ou ici (en version minified
). Ajoutez ensuite le fichier à votre projet de développement et référencez le dans la/les page(s) dans la(les)quelle(s) vous souhaitez l’utiliser.
<script src="/Scripts/jquery.ba-bbq.js"></script>
Une fois ceci fait, il est possible de s’abonner à un événement hashchange
sur la window. Cet événement sera levé à chaque fois que le hash de l’URL sera modifié :
<div id="menu">
- @Html.ActionLink("Clients", "Index", "Customers", null, new { @class = "menu-link" })
- @Html.ActionLink("Achats", "Index", "Orders", null, new { @class = "menu-link" })
<div id="contentDiv">
<div id="currentFragment">
@section scripts{
<script type="text/javascript">
$(document).ready(function () {
$(window).bind("hashchange", function (e) {
//récupération du fragment
var fragment = e.fragment;
$("#currentFragment").html("" + fragment + "
");
});
});
</script>
}
Dès lors, dès que le fragment change dans l’URL, le hash est affiché sur la page, dans le conteneur currentFragment
:
A présent, il suffit de remplacer les liens directs des différentes sections de l’application par des liens fragmentés :
$(".menu-link").each(function(index, item) {
var href = $(item).attr("href");
var newHref = thisUrl + "#" + href;
$(item).attr("href", newHref);
});
Et de charger le contenu représenter par le fragment lorsque le hash change :
$(window).bind("hashchange", function (e) {
//récupération du fragment
var fragment = e.fragment;
$("#currentFragment").html("" + fragment + "
");
//chargement du contenu
$("#contentDiv").load(fragment);
});
Enfin, pour faire en sorte que le contenu soit également chargé lorsque l’utilisateur accède directement à votre application web via une URL fragmentée, il est nécessaire de forcer l’évènement hashchange
sur le document ready :
$(window).trigger("hashchange");
Et voilà, le tour est joué. Vous pouvez récupérer les sources de l’exemple ici.
Enjoy
Julien
read more
20 Dec 2012 in
ASP.NET MVC
|
Web Development
Dans certains cas, il peut être intéressant de pouvoir formater du JavaScript avec Razor, pour tirer profit des données du modèle directement dans vos scripts JavaScript.
Pour cela, il suffit d’utiliser la notation <text></text>
comme ci-dessous :
<script type="text/javascript">
//code JavaScript
var customers = new Array();
//code Razor/C#
@foreach(var customer in Model.Customers)
{
//code javascript + razor/c#
<text>
customers.push({
name: "@customer.Name",
firstname: "@customer.FirstName",
birth: "@customer.BirthDate"
});
</text>
}
$(document).ready(function(){
//ect...
});
</script>
Et voilà : simple, mais efficace !
A+
Julien
read more
10 Dec 2012 in
ASP.NET MVC
La gestion de l’upload de fichier dans un service ASP.NET Web API se fait à l’aide d’un MultipartFileStreamProvider. Il est possible de créer ses propres providers pour enregistrer un fichier d’une manière particulière, par exemple dans un blob azure ou une base de données SQL Server. C’est le deuxième exemple que j’ai choisi pour illustrer ce post.
Utilisation basique du MultipartFileStreamProvider
Pour cet exemple, on se place dans un ApiController tout ce qu’il y a de plus classique, dans une méthode appelée en POST :
[HttpPost]
public async Task<HttpResponseMessage> Post()
{
if (!Request.Content.IsMimeMultipartContent("form-data"))
return Request.CreateErrorResponse(HttpStatusCode.UnsupportedMediaType, "contenu non supporté");
//le multipart provider va télécharger les fichiers dans le répertoire temporaire
var multipartProvider = new MultipartFileStreamProvider(Path.GetTempPath());
var files = await Request.Content.ReadAsMultipartAsync(multipartProvider)
.ContinueWith(t =>
{
if (t.IsFaulted)
throw t.Exception;
//retourne la liste des fichiers qui ont été téléchargés sur le systeme de fichier local
//dans le répertoire temporaire
return t.Result.FileData.ToList();
});
foreach (var file in files)
{
//chemin du fichier en local :
string path = file.LocalFileName;
//nom du fichier envoyé :
string fileName = file.Headers.ContentDisposition.FileName;
//contentType du fichier
string contentType = file.Headers.ContentType.MediaType;
}
return Request.CreateResponse(HttpStatusCode.OK);
}
Il est d’abord nécessaire de vérifier que le POST a bien été fait avec un mime content en form-data. Si ce n’est pas le cas, on retourne en indiquant que le format du média n’est pas supporté.
Dans un second temps, il suffit d’instancier un MultipartFileStreamProvider en lui passant un répertoire de base pour télécharger les fichiers (ici un dossier temporaire) et d’appeler la méthode ReadAsMultipartAsync sur l’objet Request. Il est alors possible de récupérer les différents fichiers, leur chemin d’accès local, leur content type, leur nom… Il est alors ensuite possible d’appliquer n’importe quel traitement sur le fichier pour l’exploiter (envoie dans un blob azure, stockage dans une base de données…). Ce qui va devenir vraiment intéressant est de factoriser ces différents traitements dans des multipart providers dédiés
à ces tâches spécifiques !
Personnalisation d’un MultipartFileStreamProvider
Il est possible de dériver la classe MultipartFileStreamProvider afin de surcharger la méthode ExecutePostProcessingAsync, en charge de traiter les différents fichier qui sont envoyés sur le serveur. Dans le cas présent, cette méthode va être surchargée pour envoyer automatiquement les fichiers dans une base de données SQL Serveur.
Pour commencer, on créé un constructeur qui permet de passer la chaîne de connexion vers la base de données ainsi que le fournisseur à utiliser :
public class MultipartSqlFileStreamProvider : MultipartFileStreamProvider
{
private const string SQL = "INSERT INTO Files (FileId, ContentType, FileName, FileContent) VALUES (@FileId, @ContentType, @FileName, @FileContent)";
private readonly string _connectionString;
private readonly DbProviderFactory _dbProviderFactory;
public List<Guid> FileIDs{ get; set; }
public MultipartSqlFileStreamProvider(string connectionString, string providerName)
: base(Path.GetTempPath())
{
_connectionString = connectionString;
FileIDs = new List<Guid>();
_dbProviderFactory = DbProviderFactories.GetFactory(providerName);
}
}
Ensuite, on surcharge la méthode et on parcourt la liste de fichier afin de les enregistrer dans la base SQL :
public async override Task ExecutePostProcessingAsync()
{
using (var sqlConnection = _dbProviderFactory.CreateConnection())
{
sqlConnection.ConnectionString = _connectionString;
sqlConnection.Open();
foreach (var file in FileData)
{
using (var dbCommand = sqlConnection.CreateCommand())
{
dbCommand.CommandText = SQL;
Guid fileId = Guid.NewGuid();
var fileIdParameter = dbCommand.CreateParameter();
fileIdParameter.ParameterName = "FileId";
fileIdParameter.Value = fileId;
fileIdParameter.DbType = System.Data.DbType.Guid;
dbCommand.Parameters.Add(fileIdParameter);
var contentTypeParameter = dbCommand.CreateParameter();
contentTypeParameter.ParameterName = "ContentType";
contentTypeParameter.Value = file.Headers.ContentType.MediaType;
contentTypeParameter.DbType = System.Data.DbType.StringFixedLength;
dbCommand.Parameters.Add(contentTypeParameter);
var fileNameParameter = dbCommand.CreateParameter();
fileNameParameter.ParameterName = "FileName";
fileNameParameter.Value = file.Headers.ContentDisposition.FileName.Replace("\"","");
fileNameParameter.DbType = System.Data.DbType.StringFixedLength;
dbCommand.Parameters.Add(fileNameParameter);
var fileContentParameter = dbCommand.CreateParameter();
fileContentParameter.ParameterName = "FileContent";
fileContentParameter.Value = File.ReadAllBytes(file.LocalFileName);
fileContentParameter.DbType = System.Data.DbType.Binary;
dbCommand.Parameters.Add(fileContentParameter);
await dbCommand.ExecuteNonQueryAsync();
FileIDs.Add(fileId);
}
}
sqlConnection.Close();
}
}
Pour utiliser le multipart provider personnalisé, il suffit de l’instancier et de le passer à la méthode ReadAsMultipartAsync, comme vu en introduction de cet article.
var connectionString = WebConfigurationManager.ConnectionStrings["DataConnectionString"];
var multipartSqlProvider = new MultipartSqlFileStreamProvider(connectionString.ConnectionString, connectionString.ProviderName);
var fileIDs = await Request.Content.ReadAsMultipartAsync(multipartSqlProvider)
.ContinueWith(t =>
{
if (t.IsFaulted)
{
throw t.Exception;
}
var provider = t.Result;
return provider.OutputFileIDs.First().ToString();
}
);
Dès lors, les fichiers sont automatiquement envoyés dans la base de données et vous récupérez en output la liste des IDs des fichiers !
Enjoy
Julien
read more
07 Dec 2012 in
ASP.NET MVC
|
Microsoft Azure
Team Foundation Service (anciennement TFS Preview) est la version hébergée de Team Foundation Server. Pour en savoir plus sur ce service proposé par Microsoft, je vous invite à lire cet article et cet article sur le blog d’cet article !
Une des fonctionnalité très sympa lorsque l’on développe des applications destinées à être hébergées dans Windows Azure, est la possibilité d’associer automatiquement un projet d’équipe Team Foundation Service à un Cloud Service Azure. Cela permet de faire en sorte qu’à chaque check-in depuis Visual Studio, le code soit compilé et automatiquement déployé dans Azure.
Pour associer un projet d’équipe à un service de compute Azure, il faut se connecter sur l’interface de management Windows Azure puis se rendre sur le tableau de bord du service en question :
Cliquez sur Configurer la publication TFS. La popup qui s’ouvre vous permet soit d’utiliser un compte TFService déjà existant, soit de créer un compte sur visualstudio.com :
Saisissez le nom de votre compte de service si vous en avez déjà un. Si ce n’est pas le cas, cliquez sur Créez un compte TFS maintenant. La popup qui s’ouvre vous permet de créer un compte TFS Service :
Créez votre compte. Pour les utilisateur existant, cliquez sur le lien Autorisez maintenant.
Une fenêtre s’ouvre alors pour vous demander d’autoriser votre service Windows Azure à accéder à TFS, un peu comme cela pourrait être pour n’importe quel membre de l’équipe :
Si vous êtes d’accord, acceptez Vous pouvez à présent choisir le projet d’équipe à associer :
Patientez pendant la liaison du projet d’équipe à votre service Windows Azure :
Une fois ceci fait, ouvrez Visual Studio et connectez- vous à votre projet d’équipe. Dans le Team Explorer, affichez les définitions Builds configurées. Comme vous pouvez le constater, une nouvelle Build est présente. Elle porte le nom de votre service Cloud Azure, suffixé par _CD
pour Continuous Deployment :
Si vous ouvrez la définition de la build, vous pourrez voir que celle ci est configurée pour être exécuté à chaque check-in (Continuous Integration), dans l’onglet Trigger. Si vous allez dans l’onglet Process, vous constaterez que le process template utilisé est un spécifique à Windows Azure : AzureContinuousDeployment.11.xaml. En ouvrant le workflow de build, et en fouillant un peu dans les différentes activités, vous finirez par trouver la partie qui concerne le déploiement dans Azure :
Concrètement, vous n’avez rien à modifier pour que ça marche
Afin d’avoir la main sur le profil de publication qui doit être utilisé par la build lors du déploiement, vous devez en créer un (ou utiliser un existant, si vous en avez déjà un). Pour se faire, faites un clic droit sur votre projet Cloud dans Visual Studio et cliquez sur Publish…
Dans la fenêtre qui s’ouvre, choisissez votre souscription Azure :
Configurez ensuite les paramètres en choisissez votre Cloud Service, l’environnement sur lequel vous souhaitez déployer (Production / Staging), la build configuration et la service configuration à utiliser :
Sur la page de résumé, enregistrez le profile, mais ne cliquez pas sur Publish, cliquez sur Cancel pour quitter :
Visual Studio a créé un fichier XML qui représente ce profil, dans le dossier Profiles
du projet Windows Azure. Retournez dans la définition de la build, dans l’onglet Process et déroulez la section** 5. Publishing – Azure Cloud Service. **Modifiez le paramètre Alternate Publish Profile pour le faire pointer sur le fichier de profil que vous venez de créer :
Enregistrez les paramètres, et lancez la build. Le tour est joué.
Note : pour le moment le SDK 1.8 de Windows Azure n’est pas pris en charge par l’agent de build hosté sur Team Foundation Service, mais cela devrait arriver. En attendant, il est possible d’indiquer que la build doit s’exécuter sur un agent de build configuré on-premise, par vos soins.
Enjoy
Julien
read more