Explorar o código

formation end!!!

Sylvain Reclus %!s(int64=8) %!d(string=hai) anos
pai
achega
e757b257b3
Modificáronse 29 ficheiros con 900 adicións e 67 borrados
  1. 1 1
      Formateur/NbVisiteurs.txt
  2. 27 0
      Formateur/SolutionANA/AppliDeWS/AppliDeWS.csproj
  3. 72 0
      Formateur/SolutionANA/AppliDeWS/ClientAjax.aspx
  4. 14 0
      Formateur/SolutionANA/AppliDeWS/ClientAjax.aspx.cs
  5. 24 0
      Formateur/SolutionANA/AppliDeWS/ClientAjax.aspx.designer.cs
  6. 1 0
      Formateur/SolutionANA/AppliDeWS/MonService.asmx
  7. 35 0
      Formateur/SolutionANA/AppliDeWS/MonService.asmx.cs
  8. 23 12
      Formateur/SolutionANA/AppliDeWS/Web.config
  9. 1 0
      Formateur/SolutionANA/AppliDeWS/packages.config
  10. 6 0
      Formateur/SolutionANA/AppliWebANA/AppliWebANA.csproj
  11. 32 3
      Formateur/SolutionANA/AppliWebANA/Controllers/AnnuaireController.cs
  12. 31 0
      Formateur/SolutionANA/AppliWebANA/Controllers/SecuriteController.cs
  13. BIN=BIN
      Formateur/SolutionANA/AppliWebANA/Scripts/_references.js
  14. 189 0
      Formateur/SolutionANA/AppliWebANA/Scripts/jquery.unobtrusive-ajax.js
  15. 18 0
      Formateur/SolutionANA/AppliWebANA/Scripts/jquery.unobtrusive-ajax.min.js
  16. 38 18
      Formateur/SolutionANA/AppliWebANA/Views/Annuaire/Index.cshtml
  17. 18 0
      Formateur/SolutionANA/AppliWebANA/Views/Annuaire/LigneEnEdition.cshtml
  18. 15 0
      Formateur/SolutionANA/AppliWebANA/Views/Annuaire/LigneEnLecture.cshtml
  19. 15 0
      Formateur/SolutionANA/AppliWebANA/Views/Securite/Index.cshtml
  20. 6 0
      Formateur/SolutionANA/AppliWebANA/Web.config
  21. 1 0
      Formateur/SolutionANA/AppliWebANA/packages.config
  22. 25 0
      mySolution/EmpForm/EmpForm/Controllers/AnnuaireController.cs
  23. 3 0
      mySolution/EmpForm/EmpForm/EmpForm.csproj
  24. 189 0
      mySolution/EmpForm/EmpForm/Scripts/jquery.unobtrusive-ajax.js
  25. 18 0
      mySolution/EmpForm/EmpForm/Scripts/jquery.unobtrusive-ajax.min.js
  26. 64 33
      mySolution/EmpForm/EmpForm/Views/Annuaire/Index.cshtml
  27. 18 0
      mySolution/EmpForm/EmpForm/Views/Annuaire/LigneEnEdition.cshtml
  28. 15 0
      mySolution/EmpForm/EmpForm/Views/Annuaire/LigneEnLecture.cshtml
  29. 1 0
      mySolution/EmpForm/EmpForm/packages.config

+ 1 - 1
Formateur/NbVisiteurs.txt

@@ -1 +1 @@
-78
+92

+ 27 - 0
Formateur/SolutionANA/AppliDeWS/AppliDeWS.csproj

@@ -44,6 +44,14 @@
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+      <HintPath>..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
+    <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+      <HintPath>..\packages\EntityFramework.6.1.3\lib\net45\EntityFramework.SqlServer.dll</HintPath>
+      <Private>True</Private>
+    </Reference>
     <Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <HintPath>..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.1.0.0\lib\net45\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
       <Private>True</Private>
@@ -78,12 +86,21 @@
     </None>
   </ItemGroup>
   <ItemGroup>
+    <Content Include="ClientAjax.aspx" />
     <Content Include="Default.aspx" />
     <Content Include="Global.asax" />
+    <Content Include="MonService.asmx" />
     <Content Include="Service1.svc" />
     <Content Include="Web.config" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="ClientAjax.aspx.cs">
+      <DependentUpon>ClientAjax.aspx</DependentUpon>
+      <SubType>ASPXCodeBehind</SubType>
+    </Compile>
+    <Compile Include="ClientAjax.aspx.designer.cs">
+      <DependentUpon>ClientAjax.aspx</DependentUpon>
+    </Compile>
     <Compile Include="Default.aspx.cs">
       <DependentUpon>Default.aspx</DependentUpon>
       <SubType>ASPXCodeBehind</SubType>
@@ -95,6 +112,10 @@
       <DependentUpon>Global.asax</DependentUpon>
     </Compile>
     <Compile Include="IService1.cs" />
+    <Compile Include="MonService.asmx.cs">
+      <DependentUpon>MonService.asmx</DependentUpon>
+      <SubType>Component</SubType>
+    </Compile>
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Service1.svc.cs">
       <DependentUpon>Service1.svc</DependentUpon>
@@ -104,6 +125,12 @@
     <Folder Include="App_Data\" />
     <Folder Include="Models\" />
   </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\DAL\DAL.csproj">
+      <Project>{1f4b556e-acae-4fac-b3d3-7c1b4ecad1af}</Project>
+      <Name>DAL</Name>
+    </ProjectReference>
+  </ItemGroup>
   <PropertyGroup>
     <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
     <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

+ 72 - 0
Formateur/SolutionANA/AppliDeWS/ClientAjax.aspx

@@ -0,0 +1,72 @@
+<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ClientAjax.aspx.cs" Inherits="AppliDeWS.ClientAjax" %>
+
+<!DOCTYPE html>
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head runat="server">
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+	<title></title>
+
+	<script src="http://ajax.aspnetcdn.com/ajax/4.5.2/1/MicrosoftAjax.js"></script>
+	<script src="MonService.asmx/js"></script>
+
+
+
+</head>
+<body>
+	<form id="form1" runat="server">
+		<div>
+		<%--	<asp:ScriptManager runat="server">
+				<Services>
+					<asp:ServiceReference Path="~/MonService.asmx" />
+				</Services>
+			</asp:ScriptManager>--%>
+
+
+			n1 : <input type="text" id="n1" value="" /><br />
+			n1 : <input type="text" id="n2" value="" /><br />
+			<input type="button" value="+" onclick="additionner()" /><br />
+			<div id="resultat"></div>
+			<hr />
+
+			recherche : <input type="text" id="recherche" value="" /><br />
+			<input type="button" value="+" onclick="rechercher()" /><br />
+			<pre id="personnes"></pre>
+
+
+			<script type="text/javascript">
+				function rechercher() {
+					AppliDeWS.MonService.Rechercher($get("recherche").value,
+						function (personnes) {
+							///<param name="personnes" value="[{Nom: '', Prenom: '', Civilite: ''}]" />
+							var sb = new Sys.StringBuilder();
+							for (var i = 0; i < personnes.length; i++) {
+								sb.appendLine(String.format( "{0} {1} {2}", personnes[i].Civilite, personnes[i].Prenom, personnes[i].Nom.toUpperCase() ))
+							}
+							$get('personnes').innerText = sb.toString();
+						},
+						function (wse) {
+							$get("personnes").innerHTML = String.format("ERREUR {0} : {1}", wse.get_exceptionType(), wse.get_message());
+						}
+					);
+				}
+
+				function additionner() {
+					AppliDeWS.MonService.Additionner($get("n1").value, $get("n2").value,
+						function (resultat) {
+							$get("resultat").innerHTML = String(resultat);
+						},
+						function (wse) {
+							$get("resultat").innerHTML = String.format("ERREUR {0} : {1}", wse.get_exceptionType(), wse.get_message());
+						}
+					);
+				}
+
+			</script>
+
+
+
+		</div>
+	</form>
+</body>
+</html>

+ 14 - 0
Formateur/SolutionANA/AppliDeWS/ClientAjax.aspx.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.UI;
+using System.Web.UI.WebControls;
+
+namespace AppliDeWS {
+	public partial class ClientAjax : System.Web.UI.Page {
+		protected void Page_Load( object sender, EventArgs e ) {
+
+		}
+	}
+}

+ 24 - 0
Formateur/SolutionANA/AppliDeWS/ClientAjax.aspx.designer.cs

@@ -0,0 +1,24 @@
+//------------------------------------------------------------------------------
+// <généré automatiquement>
+//     Ce code a été généré par un outil.
+//
+//     Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si
+//     le code est régénéré.
+// </généré automatiquement>
+//------------------------------------------------------------------------------
+
+namespace AppliDeWS {
+    
+    
+    public partial class ClientAjax {
+        
+        /// <summary>
+        /// Contrôle form1.
+        /// </summary>
+        /// <remarks>
+        /// Champ généré automatiquement.
+        /// Pour modifier, déplacez la déclaration de champ du fichier de concepteur dans le fichier code-behind.
+        /// </remarks>
+        protected global::System.Web.UI.HtmlControls.HtmlForm form1;
+    }
+}

+ 1 - 0
Formateur/SolutionANA/AppliDeWS/MonService.asmx

@@ -0,0 +1 @@
+<%@ WebService Language="C#" CodeBehind="MonService.asmx.cs" Class="AppliDeWS.MonService" %>

+ 35 - 0
Formateur/SolutionANA/AppliDeWS/MonService.asmx.cs

@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Services;
+
+namespace AppliDeWS {
+	/// <summary>
+	/// Description résumée de MonService
+	/// </summary>
+	[WebService( Namespace = "http://tempuri.org/" )]
+	[WebServiceBinding( ConformsTo = WsiProfiles.BasicProfile1_1 )]
+	[System.ComponentModel.ToolboxItem( false )]
+	[System.Web.Script.Services.ScriptService]
+	public class MonService : System.Web.Services.WebService {
+
+		[WebMethod]
+		public int Additionner( int i1, int i2 ) {
+			return i1 + i2;
+		}
+		[WebMethod]
+		public object Rechercher( string nomOuPrenom ) {
+			using( DAL.AnnuaireEntities dc = new DAL.AnnuaireEntities() ) {
+				return dc.Personnes
+					.Where( p => p.Nom.Contains( nomOuPrenom ) || p.Prenom.Contains( nomOuPrenom ) )
+					.Select( p => new {
+						p.Nom,
+						p.Prenom,
+						p.Titre.Civilite
+					} ).ToList();
+			}
+			
+		}
+	}
+}

+ 23 - 12
Formateur/SolutionANA/AppliDeWS/Web.config

@@ -1,21 +1,27 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <!--
   Pour plus d'informations sur la configuration de votre application ASP.NET, consultez
   http://go.microsoft.com/fwlink/?LinkId=169433
   -->
 <configuration>
-  <system.web>
-    <compilation debug="true" targetFramework="4.6.1"/>
-    <httpRuntime targetFramework="4.6.1"/>
+  <configSections>
+    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
+    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+  </configSections>
+
+	<connectionStrings>
+		<add name="AnnuaireEntities" connectionString="metadata=res://*/ModeleAnnuaire.csdl|res://*/ModeleAnnuaire.ssdl|res://*/ModeleAnnuaire.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.\sqlexpress;initial catalog=Annuaire;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
+	</connectionStrings>
+
+
+	<system.web>
+    <compilation debug="true" targetFramework="4.6.1" />
+    <httpRuntime targetFramework="4.6.1" />
   </system.web>
   <system.codedom>
     <compilers>
-      <compiler language="c#;cs;csharp" extension=".cs"
-        type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
-        warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701"/>
-      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb"
-        type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
-        warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+"/>
+      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701" />
+      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
     </compilers>
   </system.codedom>
   <system.serviceModel>
@@ -27,7 +33,12 @@
         </behavior>
       </serviceBehaviors>
     </behaviors>
-    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
-      multipleSiteBindingsEnabled="true" />
+    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
   </system.serviceModel>
+  <entityFramework>
+    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
+    <providers>
+      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
+    </providers>
+  </entityFramework>
 </configuration>

+ 1 - 0
Formateur/SolutionANA/AppliDeWS/packages.config

@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
+  <package id="EntityFramework" version="6.1.3" targetFramework="net461" />
   <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.0" targetFramework="net461" />
   <package id="Microsoft.Net.Compilers" version="1.0.0" targetFramework="net461" developmentDependency="true" />
 </packages>

+ 6 - 0
Formateur/SolutionANA/AppliWebANA/AppliWebANA.csproj

@@ -172,6 +172,7 @@
     <Compile Include="Controllers\CompteursController.cs" />
     <Compile Include="Controllers\EmployeController.cs" />
     <Compile Include="Controllers\MessagerieController.cs" />
+    <Compile Include="Controllers\SecuriteController.cs" />
     <Compile Include="Global.asax.cs">
       <DependentUpon>Global.asax</DependentUpon>
     </Compile>
@@ -217,6 +218,8 @@
     <Content Include="Scripts\jquery-3.1.1.slim.js" />
     <Content Include="Scripts\jquery-3.1.1.slim.min.js" />
     <None Include="Scripts\jquery.validate-vsdoc.js" />
+    <Content Include="Scripts\jquery.unobtrusive-ajax.js" />
+    <Content Include="Scripts\jquery.unobtrusive-ajax.min.js" />
     <Content Include="Scripts\jquery.validate.js" />
     <Content Include="Scripts\jquery.validate.min.js" />
     <Content Include="Scripts\jquery.validate.unobtrusive.js" />
@@ -247,6 +250,9 @@
     <Content Include="Views\Articles\UneLigneArticle.cshtml" />
     <Content Include="Views\Employe\Index.cshtml" />
     <Content Include="Views\Annuaire\Index.cshtml" />
+    <Content Include="Views\Annuaire\LigneEnEdition.cshtml" />
+    <Content Include="Views\Annuaire\LigneEnLecture.cshtml" />
+    <Content Include="Views\Securite\Index.cshtml" />
   </ItemGroup>
   <ItemGroup>
     <Folder Include="App_Data\" />

+ 32 - 3
Formateur/SolutionANA/AppliWebANA/Controllers/AnnuaireController.cs

@@ -8,6 +8,7 @@ using System.Web.Caching;
 using System.Web.Mvc;
 
 namespace AppliWebANA.Controllers {
+	[Authorize]
 	public class AnnuaireController : Controller {
 
 		private AnnuaireEntities _DC = null;
@@ -31,7 +32,7 @@ namespace AppliWebANA.Controllers {
 			string clé = Request.Url.Query.Replace( " ", string.Empty ).ToUpper();
 			var resultats = (IEnumerable<Personne>)HttpContext.Cache[clé];
 			if( resultats == null ) {
-				var requete = DC.Personnes.AsQueryable();
+				IQueryable<Personne> requete = DC.Personnes.AsNoTracking();
 				if( titreId.HasValue )
 					requete = requete.Where( p => p.TitreId == titreId.Value );
 				if( !string.IsNullOrWhiteSpace( filtre.Nom ) ) {
@@ -47,7 +48,7 @@ namespace AppliWebANA.Controllers {
 					requete = requete.Where( p => p.Telephone.Contains( filtre.Telephone ) );
 				}
 				resultats = requete.ToList();
-				HttpContext.Cache.Add( clé, resultats, null, DateTime.Now.AddMinutes(10), Cache.NoSlidingExpiration, CacheItemPriority.Default, null );
+				HttpContext.Cache.Add( clé, resultats, null, DateTime.Now.AddMinutes( 10 ), Cache.NoSlidingExpiration, CacheItemPriority.Default, null );
 				ViewBag.Message = "Requête exécutée";
 			}
 			else
@@ -55,9 +56,37 @@ namespace AppliWebANA.Controllers {
 
 			ViewBag.personnes = resultats;
 			ViewBag.Titres = Utilitaires.Titres;
-			return View("Index");
+			return View( "Index" );
 		}
 
+		public PartialViewResult Edition( Guid id ) {
+			if( Request.Form.AllKeys.Contains( "Edit" ) ) { // Bt pour passer une ligne en mode édition
+				var personne = DC.Personnes.First( p => p.Id == id );
+				ViewBag.Titres = Utilitaires.Titres.Values;
+				return PartialView( "LigneEnEdition", personne );
+			}
+			else if( Request.Form.AllKeys.Contains( "Cancel" ) ) {
+				var personne = DC.Personnes.First( p => p.Id == id );
+				ViewBag.Titres = Utilitaires.Titres;
+				return PartialView( "LigneEnLecture", personne );
+			}
+			else if( Request.Form.AllKeys.Contains( "Update" ) ) {
+				Personne maj = new Personne();
+				if( TryUpdateModel( maj ) ) {
+					DC.Entry( maj ).State = System.Data.Entity.EntityState.Modified;
+					DC.SaveChanges();
+					ViewBag.Titres = Utilitaires.Titres;
+					return PartialView( "LigneEnLecture", maj );
+				}
+				else {
+					ViewBag.Titres = Utilitaires.Titres.Values;
+					return PartialView( "LigneEnEdition", maj );
+				}
+			}
+			throw new ArgumentException( "Hein ? Kéchécha ?" );
+		}
+
+
 		protected override void Dispose( bool disposing ) {
 			if( _DC != null ) {
 				_DC.Dispose();

+ 31 - 0
Formateur/SolutionANA/AppliWebANA/Controllers/SecuriteController.cs

@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Web;
+using System.Web.Mvc;
+using System.Web.Security;
+
+namespace AppliWebANA.Controllers {
+	public class SecuriteController : Controller {
+		[HttpGet]
+		public ActionResult Index() {
+			return View();
+		}
+		[HttpPost]
+		public ActionResult Index(string nom, string mdp, string returnUrl) {
+			if( Request.Form.AllKeys.Contains( "creer" ) ) {
+				MembershipCreateStatus status;
+				Membership.CreateUser( nom, mdp, "ezeze@zeze.com", "q", "r", true, out status );
+				return View();
+			}
+			else {
+				if( Membership.ValidateUser( nom, mdp ) ) {
+					FormsAuthentication.SetAuthCookie( nom, false );
+					return Redirect( returnUrl );
+				}
+				else
+					return View();
+			}
+		}
+	}
+}

BIN=BIN
Formateur/SolutionANA/AppliWebANA/Scripts/_references.js


+ 189 - 0
Formateur/SolutionANA/AppliWebANA/Scripts/jquery.unobtrusive-ajax.js

@@ -0,0 +1,189 @@
+/* NUGET: BEGIN LICENSE TEXT
+ *
+ * Microsoft grants you the right to use these script files for the sole
+ * purpose of either: (i) interacting through your browser with the Microsoft
+ * website or online service, subject to the applicable licensing or use
+ * terms; or (ii) using the files as included with a Microsoft product subject
+ * to that product's license terms. Microsoft reserves all other rights to the
+ * files not expressly granted by Microsoft, whether by implication, estoppel
+ * or otherwise. Insofar as a script file is dual licensed under GPL,
+ * Microsoft neither took the code under GPL nor distributes it thereunder but
+ * under the terms set out in this paragraph. All notices and licenses
+ * below are for informational purposes only.
+ *
+ * NUGET: END LICENSE TEXT */
+/*!
+** Unobtrusive Ajax support library for jQuery
+** Copyright (C) Microsoft Corporation. All rights reserved.
+*/
+
+/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
+/*global window: false, jQuery: false */
+
+(function ($) {
+    var data_click = "unobtrusiveAjaxClick",
+        data_target = "unobtrusiveAjaxClickTarget",
+        data_validation = "unobtrusiveValidation";
+
+    function getFunction(code, argNames) {
+        var fn = window, parts = (code || "").split(".");
+        while (fn && parts.length) {
+            fn = fn[parts.shift()];
+        }
+        if (typeof (fn) === "function") {
+            return fn;
+        }
+        argNames.push(code);
+        return Function.constructor.apply(null, argNames);
+    }
+
+    function isMethodProxySafe(method) {
+        return method === "GET" || method === "POST";
+    }
+
+    function asyncOnBeforeSend(xhr, method) {
+        if (!isMethodProxySafe(method)) {
+            xhr.setRequestHeader("X-HTTP-Method-Override", method);
+        }
+    }
+
+    function asyncOnSuccess(element, data, contentType) {
+        var mode;
+
+        if (contentType.indexOf("application/x-javascript") !== -1) {  // jQuery already executes JavaScript for us
+            return;
+        }
+
+        mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase();
+        $(element.getAttribute("data-ajax-update")).each(function (i, update) {
+            var top;
+
+            switch (mode) {
+            case "BEFORE":
+                top = update.firstChild;
+                $("<div />").html(data).contents().each(function () {
+                    update.insertBefore(this, top);
+                });
+                break;
+            case "AFTER":
+                $("<div />").html(data).contents().each(function () {
+                    update.appendChild(this);
+                });
+                break;
+            case "REPLACE-WITH":
+                $(update).replaceWith(data);
+                break;
+            default:
+                $(update).html(data);
+                break;
+            }
+        });
+    }
+
+    function asyncRequest(element, options) {
+        var confirm, loading, method, duration;
+
+        confirm = element.getAttribute("data-ajax-confirm");
+        if (confirm && !window.confirm(confirm)) {
+            return;
+        }
+
+        loading = $(element.getAttribute("data-ajax-loading"));
+        duration = parseInt(element.getAttribute("data-ajax-loading-duration"), 10) || 0;
+
+        $.extend(options, {
+            type: element.getAttribute("data-ajax-method") || undefined,
+            url: element.getAttribute("data-ajax-url") || undefined,
+            cache: !!element.getAttribute("data-ajax-cache"),
+            beforeSend: function (xhr) {
+                var result;
+                asyncOnBeforeSend(xhr, method);
+                result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(element, arguments);
+                if (result !== false) {
+                    loading.show(duration);
+                }
+                return result;
+            },
+            complete: function () {
+                loading.hide(duration);
+                getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments);
+            },
+            success: function (data, status, xhr) {
+                asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html");
+                getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(element, arguments);
+            },
+            error: function () {
+                getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]).apply(element, arguments);
+            }
+        });
+
+        options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });
+
+        method = options.type.toUpperCase();
+        if (!isMethodProxySafe(method)) {
+            options.type = "POST";
+            options.data.push({ name: "X-HTTP-Method-Override", value: method });
+        }
+
+        $.ajax(options);
+    }
+
+    function validate(form) {
+        var validationInfo = $(form).data(data_validation);
+        return !validationInfo || !validationInfo.validate || validationInfo.validate();
+    }
+
+    $(document).on("click", "a[data-ajax=true]", function (evt) {
+        evt.preventDefault();
+        asyncRequest(this, {
+            url: this.href,
+            type: "GET",
+            data: []
+        });
+    });
+
+    $(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) {
+        var name = evt.target.name,
+            target = $(evt.target),
+            form = $(target.parents("form")[0]),
+            offset = target.offset();
+
+        form.data(data_click, [
+            { name: name + ".x", value: Math.round(evt.pageX - offset.left) },
+            { name: name + ".y", value: Math.round(evt.pageY - offset.top) }
+        ]);
+
+        setTimeout(function () {
+            form.removeData(data_click);
+        }, 0);
+    });
+
+    $(document).on("click", "form[data-ajax=true] :submit", function (evt) {
+        var name = evt.currentTarget.name,
+            target = $(evt.target),
+            form = $(target.parents("form")[0]);
+
+        form.data(data_click, name ? [{ name: name, value: evt.currentTarget.value }] : []);
+        form.data(data_target, target);
+
+        setTimeout(function () {
+            form.removeData(data_click);
+            form.removeData(data_target);
+        }, 0);
+    });
+
+    $(document).on("submit", "form[data-ajax=true]", function (evt) {
+        var clickInfo = $(this).data(data_click) || [],
+            clickTarget = $(this).data(data_target),
+            isCancel = clickTarget && clickTarget.hasClass("cancel");
+        evt.preventDefault();
+        if (!isCancel && !validate(this)) {
+            return;
+        }
+        asyncRequest(this, {
+            url: this.action,
+            type: this.method || "GET",
+            data: clickInfo.concat($(this).serializeArray())
+        });
+    });
+}(jQuery));

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 18 - 0
Formateur/SolutionANA/AppliWebANA/Scripts/jquery.unobtrusive-ajax.min.js


+ 38 - 18
Formateur/SolutionANA/AppliWebANA/Views/Annuaire/Index.cshtml

@@ -12,7 +12,7 @@
 
 }
 
-<h2>@title</h2>
+<h2>@title - @User.Identity.Name</h2>
 
 @using( Html.BeginForm( "Rechercher", "Annuaire", FormMethod.Get, new { @class = "form-horizontal", role = "form" } ) ) {
 
@@ -56,24 +56,44 @@
 
 	<hr />
 	<p>@message</p>
-	<table class="table table-bordered table-condensed table-striped">
-		<tr>
-			<th>Actions</th>
-			<th>@Html.DisplayNameFor( m => m.TitreId ) </th>
-			<th>@Html.DisplayNameFor( m => m.Prenom ) </th>
-			<th>@Html.DisplayNameFor( m => m.Nom ) </th>
-			<th>@Html.DisplayNameFor( m => m.Telephone ) </th>
-		</tr>
-		@foreach( var p in personnes ) {
+
+	using( Ajax.BeginForm( "Edition", new AjaxOptions() { HttpMethod = "POST", UpdateTargetId = "LigneEnEdition", InsertionMode = InsertionMode.ReplaceWith } ) ) {
+
+		<input type="hidden" name="id" value="" id="idPersonneAEditer" />
+
+		<table class="table table-bordered table-condensed table-striped">
 			<tr>
-				<td>-</td>
-				<td>@dicoTitres[p.TitreId].Civilite</td>
-				<td>@p.Prenom</td>
-				<td>@p.Nom</td>
-				<td>@p.Telephone</td>
+				<th>Actions</th>
+				<th>@Html.DisplayNameFor( m => m.TitreId ) </th>
+				<th>@Html.DisplayNameFor( m => m.Prenom ) </th>
+				<th>@Html.DisplayNameFor( m => m.Nom ) </th>
+				<th>@Html.DisplayNameFor( m => m.Telephone ) </th>
 			</tr>
-		}
-	</table>
-
+			@foreach( var p in personnes ) {
+				<tr>
+					<td>
+						<input type="submit" name="Edit" value="Éditer" class="btn btn-default"
+									 onclick="preparerEdition(this)" data-id="@p.Id" />
+					</td>
+					<td>@dicoTitres[p.TitreId].Civilite</td>
+					<td>@p.Prenom</td>
+					<td>@p.Nom</td>
+					<td>@p.Telephone</td>
+				</tr>
+			}
+		</table>
+	}
 }
 
+@section scripts {
+
+	<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
+
+	<script type="text/javascript">
+		function preparerEdition(btEdition) {
+			var $ligneDuBouton = $(btEdition).closest("tr");
+			$ligneDuBouton.prop("id", "LigneEnEdition");
+			$("#idPersonneAEditer").val($(btEdition).attr( "data-id" ));
+		}
+	</script>
+}

+ 18 - 0
Formateur/SolutionANA/AppliWebANA/Views/Annuaire/LigneEnEdition.cshtml

@@ -0,0 +1,18 @@
+@model DAL.Personne
+@{ 
+	IEnumerable<DAL.Titre> titres = ViewBag.Titres;
+}
+<tr id="LigneEnEdition">
+	<td>
+		<input type="submit" name="Update" value="OK" class="btn btn-success" />
+		<input type="submit" name="Cancel" value="KO" class="btn btn-warning" />
+		@Html.ValidationSummary()
+	</td>
+	<td>@Html.DropDownListFor( m => m.TitreId, titres.Select( t => new SelectListItem() { Text = t.Civilite, Value = t.Id.ToString() } ), new { @class = "form-control" } )</td>
+	<td>@Html.TextBoxFor( m => m.Prenom, new { @class = "form-control" } )</td>
+	<td>@Html.TextBoxFor( m => m.Nom, new { @class = "form-control" } )</td>
+	<td>
+		@Html.TextBoxFor( m => m.Telephone, new { @class = "form-control" } )
+		@Html.AllValidationMessagesTooltipFor( m => m.Telephone )
+	</td>
+</tr>

+ 15 - 0
Formateur/SolutionANA/AppliWebANA/Views/Annuaire/LigneEnLecture.cshtml

@@ -0,0 +1,15 @@
+@model DAL.Personne
+@{ 
+	IDictionary<short, DAL.Titre> dicoTitres = ViewBag.Titres;
+}
+
+<tr>
+	<td>
+		<input type="submit" name="Edit" value="Éditer" class="btn btn-default"
+					 onclick="preparerEdition(this)" data-id="@Model.Id" />
+	</td>
+	<td>@dicoTitres[Model.TitreId].Civilite</td>
+	<td>@Model.Prenom</td>
+	<td>@Model.Nom</td>
+	<td>@Model.Telephone</td>
+</tr>

+ 15 - 0
Formateur/SolutionANA/AppliWebANA/Views/Securite/Index.cshtml

@@ -0,0 +1,15 @@
+
+@{
+    ViewBag.Title = "Login";
+}
+
+<h2>@ViewBag.Title</h2>
+
+@using( Html.BeginForm() ) {
+	<p>Nom : @Html.TextBox( "nom" )</p>
+	<p>Mdp : @Html.TextBox( "mdp" )</p>
+	<p><input type="submit" value="Entrer" /></p>
+	<p><input type="submit" name="creer" value="Créer" /></p>
+}
+
+

+ 6 - 0
Formateur/SolutionANA/AppliWebANA/Web.config

@@ -18,11 +18,17 @@
   </appSettings>
 
 	<connectionStrings>
+		<remove name="LocalSqlServer"/>
+		<add name="LocalSqlServer" connectionString="data source=.\sqlexpress;initial catalog=Annuaire;integrated security=True;"/>
 		<add name="AnnuaireEntities" connectionString="metadata=res://*/ModeleAnnuaire.csdl|res://*/ModeleAnnuaire.ssdl|res://*/ModeleAnnuaire.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.\sqlexpress;initial catalog=Annuaire;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
 	</connectionStrings>
 
 
 	<system.web>
+		<authentication mode="Forms">
+			<forms loginUrl="~/Securite">				
+			</forms>
+		</authentication>
     <compilation debug="true" targetFramework="4.6.1" />
     <httpRuntime targetFramework="4.6.1" />
     <httpModules>

+ 1 - 0
Formateur/SolutionANA/AppliWebANA/packages.config

@@ -29,6 +29,7 @@
   <package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net461" />
   <package id="Microsoft.AspNet.WebPages.fr" version="3.2.3" targetFramework="net461" />
   <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.3" targetFramework="net461" />
+  <package id="Microsoft.jQuery.Unobtrusive.Ajax" version="3.2.3" targetFramework="net461" />
   <package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.3" targetFramework="net461" />
   <package id="Microsoft.Net.Compilers" version="2.0.1" targetFramework="net461" developmentDependency="true" />
   <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net461" />

+ 25 - 0
mySolution/EmpForm/EmpForm/Controllers/AnnuaireController.cs

@@ -54,6 +54,31 @@ namespace EmpForm.Controllers {
 			ViewBag.Titres = Utilitaires.Titres;
 			return View("Index");
 		}
+		public PartialViewResult Edition(Guid id) {
+			if (Request.Form.AllKeys.Contains("Edit")) { //Bt pour passer une ligne en mode edition
+				var personne = DC.Personnes.First(p => p.Id == id);
+				ViewBag.Titres = Utilitaires.Titres.Values;
+				return PartialView("LigneEnEdition", personne);
+			} else if (Request.Form.AllKeys.Contains("Cancel")) {
+				var personne = DC.Personnes.First(p => p.Id == id);
+				ViewBag.Titres = Utilitaires.Titres;
+				return PartialView("LigneEnLecture", personne);
+			} else if (Request.Form.AllKeys.Contains("Update")) {
+				Personne maj = new Personne();
+				if (TryValidateModel(maj)) {
+					DC.Entry(maj).State = System.Data.Entity.EntityState.Modified;
+					DC.SaveChanges();
+					ViewBag.Titres = Utilitaires.Titres;
+					return PartialView("LigneEnLecture", maj);
+				}
+				else {
+					ViewBag.Titres = Utilitaires.Titres.Values;
+					return PartialView("LigneEnEdition", maj);
+				}
+			}
+			throw new ArgumentException("Hein ? Kéchécha ?");
+		}
+
 		protected override void Dispose(bool disposing) {
 			if (_DC != null) {
 				_DC.Dispose();

+ 3 - 0
mySolution/EmpForm/EmpForm/EmpForm.csproj

@@ -146,6 +146,8 @@
     <Content Include="Scripts\jquery-1.10.2.js" />
     <Content Include="Scripts\jquery-1.10.2.min.js" />
     <None Include="Scripts\jquery.validate-vsdoc.js" />
+    <Content Include="Scripts\jquery.unobtrusive-ajax.js" />
+    <Content Include="Scripts\jquery.unobtrusive-ajax.min.js" />
     <Content Include="Scripts\jquery.validate.js" />
     <Content Include="Scripts\jquery.validate.min.js" />
     <Content Include="Scripts\jquery.validate.unobtrusive.js" />
@@ -154,6 +156,7 @@
     <Content Include="Web.config" />
     <Content Include="Views\Employe\Index.cshtml" />
     <Content Include="Views\Annuaire\Index.cshtml" />
+    <Content Include="Views\Annuaire\LigneEnEdition.cshtml" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="App_Start\BundleConfig.cs" />

+ 189 - 0
mySolution/EmpForm/EmpForm/Scripts/jquery.unobtrusive-ajax.js

@@ -0,0 +1,189 @@
+/* NUGET: BEGIN LICENSE TEXT
+ *
+ * Microsoft grants you the right to use these script files for the sole
+ * purpose of either: (i) interacting through your browser with the Microsoft
+ * website or online service, subject to the applicable licensing or use
+ * terms; or (ii) using the files as included with a Microsoft product subject
+ * to that product's license terms. Microsoft reserves all other rights to the
+ * files not expressly granted by Microsoft, whether by implication, estoppel
+ * or otherwise. Insofar as a script file is dual licensed under GPL,
+ * Microsoft neither took the code under GPL nor distributes it thereunder but
+ * under the terms set out in this paragraph. All notices and licenses
+ * below are for informational purposes only.
+ *
+ * NUGET: END LICENSE TEXT */
+/*!
+** Unobtrusive Ajax support library for jQuery
+** Copyright (C) Microsoft Corporation. All rights reserved.
+*/
+
+/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
+/*global window: false, jQuery: false */
+
+(function ($) {
+    var data_click = "unobtrusiveAjaxClick",
+        data_target = "unobtrusiveAjaxClickTarget",
+        data_validation = "unobtrusiveValidation";
+
+    function getFunction(code, argNames) {
+        var fn = window, parts = (code || "").split(".");
+        while (fn && parts.length) {
+            fn = fn[parts.shift()];
+        }
+        if (typeof (fn) === "function") {
+            return fn;
+        }
+        argNames.push(code);
+        return Function.constructor.apply(null, argNames);
+    }
+
+    function isMethodProxySafe(method) {
+        return method === "GET" || method === "POST";
+    }
+
+    function asyncOnBeforeSend(xhr, method) {
+        if (!isMethodProxySafe(method)) {
+            xhr.setRequestHeader("X-HTTP-Method-Override", method);
+        }
+    }
+
+    function asyncOnSuccess(element, data, contentType) {
+        var mode;
+
+        if (contentType.indexOf("application/x-javascript") !== -1) {  // jQuery already executes JavaScript for us
+            return;
+        }
+
+        mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase();
+        $(element.getAttribute("data-ajax-update")).each(function (i, update) {
+            var top;
+
+            switch (mode) {
+            case "BEFORE":
+                top = update.firstChild;
+                $("<div />").html(data).contents().each(function () {
+                    update.insertBefore(this, top);
+                });
+                break;
+            case "AFTER":
+                $("<div />").html(data).contents().each(function () {
+                    update.appendChild(this);
+                });
+                break;
+            case "REPLACE-WITH":
+                $(update).replaceWith(data);
+                break;
+            default:
+                $(update).html(data);
+                break;
+            }
+        });
+    }
+
+    function asyncRequest(element, options) {
+        var confirm, loading, method, duration;
+
+        confirm = element.getAttribute("data-ajax-confirm");
+        if (confirm && !window.confirm(confirm)) {
+            return;
+        }
+
+        loading = $(element.getAttribute("data-ajax-loading"));
+        duration = parseInt(element.getAttribute("data-ajax-loading-duration"), 10) || 0;
+
+        $.extend(options, {
+            type: element.getAttribute("data-ajax-method") || undefined,
+            url: element.getAttribute("data-ajax-url") || undefined,
+            cache: !!element.getAttribute("data-ajax-cache"),
+            beforeSend: function (xhr) {
+                var result;
+                asyncOnBeforeSend(xhr, method);
+                result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(element, arguments);
+                if (result !== false) {
+                    loading.show(duration);
+                }
+                return result;
+            },
+            complete: function () {
+                loading.hide(duration);
+                getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments);
+            },
+            success: function (data, status, xhr) {
+                asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html");
+                getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(element, arguments);
+            },
+            error: function () {
+                getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]).apply(element, arguments);
+            }
+        });
+
+        options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });
+
+        method = options.type.toUpperCase();
+        if (!isMethodProxySafe(method)) {
+            options.type = "POST";
+            options.data.push({ name: "X-HTTP-Method-Override", value: method });
+        }
+
+        $.ajax(options);
+    }
+
+    function validate(form) {
+        var validationInfo = $(form).data(data_validation);
+        return !validationInfo || !validationInfo.validate || validationInfo.validate();
+    }
+
+    $(document).on("click", "a[data-ajax=true]", function (evt) {
+        evt.preventDefault();
+        asyncRequest(this, {
+            url: this.href,
+            type: "GET",
+            data: []
+        });
+    });
+
+    $(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) {
+        var name = evt.target.name,
+            target = $(evt.target),
+            form = $(target.parents("form")[0]),
+            offset = target.offset();
+
+        form.data(data_click, [
+            { name: name + ".x", value: Math.round(evt.pageX - offset.left) },
+            { name: name + ".y", value: Math.round(evt.pageY - offset.top) }
+        ]);
+
+        setTimeout(function () {
+            form.removeData(data_click);
+        }, 0);
+    });
+
+    $(document).on("click", "form[data-ajax=true] :submit", function (evt) {
+        var name = evt.currentTarget.name,
+            target = $(evt.target),
+            form = $(target.parents("form")[0]);
+
+        form.data(data_click, name ? [{ name: name, value: evt.currentTarget.value }] : []);
+        form.data(data_target, target);
+
+        setTimeout(function () {
+            form.removeData(data_click);
+            form.removeData(data_target);
+        }, 0);
+    });
+
+    $(document).on("submit", "form[data-ajax=true]", function (evt) {
+        var clickInfo = $(this).data(data_click) || [],
+            clickTarget = $(this).data(data_target),
+            isCancel = clickTarget && clickTarget.hasClass("cancel");
+        evt.preventDefault();
+        if (!isCancel && !validate(this)) {
+            return;
+        }
+        asyncRequest(this, {
+            url: this.action,
+            type: this.method || "GET",
+            data: clickInfo.concat($(this).serializeArray())
+        });
+    });
+}(jQuery));

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 18 - 0
mySolution/EmpForm/EmpForm/Scripts/jquery.unobtrusive-ajax.min.js


+ 64 - 33
mySolution/EmpForm/EmpForm/Views/Annuaire/Index.cshtml

@@ -2,67 +2,98 @@
 @model Personne
 @{
 	string title = "Annuaire";
-	ViewBag.Title = "Index";
+	ViewBag.Title = title;
 	string message = ViewBag.Message;
+
 	IDictionary<short, Titre> dicoTitres = ViewBag.Titres;
-	var titreItems = dicoTitres.Values.Select(t => new SelectListItem() { Text = t.Civilite, Value = t.Id.ToString() });
+	var titreItems = dicoTitres.Values.Select( t => new SelectListItem() { Text = t.Civilite, Value = t.Id.ToString() } );
 
 	IEnumerable<Personne> personnes = ViewBag.Personnes;
+
 }
 
-<h2>Index</h2>
+<h2>@title</h2>
+
+@using( Html.BeginForm( "Rechercher", "Annuaire", FormMethod.Get, new { @class = "form-horizontal", role = "form" } ) ) {
 
-@using (Html.BeginForm("Rechercher", "Annuaire", FormMethod.Get, new { role = "form", @class = "form-horizontal" })) {
 	<div class="form-group">
-		<label class="col-sm-2 control-label" for="TitreId">@Html.NameFor(m => m.TitreId)</label>
+		<label class="col-sm-2 control-label" for="TitreId">@Html.DisplayNameFor( m => m.TitreId )</label>
 		<div class="col-sm-10">
-			@Html.DropDownListFor(m => m.TitreId, titreItems, string.Empty, new { @class = "form-control" })
+			@Html.DropDownListFor( m => m.TitreId, titreItems, string.Empty, new { @class = "form-control" } )
 		</div>
 	</div>
+
 	<div class="form-group">
-		<label class="col-sm-2 control-label" for="Prenom">@Html.NameFor(m => m.Prenom)</label>
+		<label class="col-sm-2 control-label" for="Prenom">@Html.DisplayNameFor( m => m.Prenom )</label>
 		<div class="col-sm-10">
-			@Html.TextBoxFor(m => m.Prenom, new { @class = "form-control" })
+			@Html.TextBoxFor( m => m.Prenom, new { @class = "form-control" } )
 		</div>
 	</div>
+
 	<div class="form-group">
-		<label class="col-sm-2 control-label" for="Nom">@Html.NameFor(m => m.Nom)</label>
+		<label class="col-sm-2 control-label" for="Nom">@Html.DisplayNameFor( m => m.Nom )</label>
 		<div class="col-sm-10">
-			@Html.TextBoxFor(m => m.Nom, new { @class = "form-control" })
+			@Html.TextBoxFor( m => m.Nom, new { @class = "form-control" } )
 		</div>
 	</div>
+
 	<div class="form-group">
-		<label class="col-sm-2 control-label" for="Telephone">@Html.NameFor(m => m.Telephone)</label>
+		<label class="col-sm-2 control-label" for="Telephone">@Html.DisplayNameFor( m => m.Telephone )</label>
 		<div class="col-sm-10">
-			@Html.TextBoxFor(m => m.Telephone, new { @class = "form-control" })
+			@Html.TextBoxFor( m => m.Telephone, new { @class = "form-control" } )
 		</div>
 	</div>
 
 	<div class="form-group">
 		<div class="col-sm-offset-2 col-sm-10">
-			<input type="submit" value="Rechercher" class="btn btn-primary"/>
+			<input type="submit" value="Rechercher" class="btn btn-primary" />
 		</div>
 	</div>
+
 }
-@if (personnes != null) {
-<hr/>
+
+@if( personnes != null ) {
+
+	<hr />
 	<p>@message</p>
-<table class="table table-bordered table-condensed table-striped">
-	<tr>
-		<th>Actions</th>
-		<th>@Html.DisplayNameFor(m => m.TitreId)</th>
-		<th>@Html.DisplayNameFor(m => m.Prenom)</th>
-		<th>@Html.DisplayNameFor(m => m.Nom)</th>
-		<th>@Html.DisplayNameFor(m => m.Telephone)</th>
-	</tr>
-	@foreach (var p in personnes) {
-		<tr>
-			<td><input type="button" class="btn btn-primary" onclick=""/>-</td>
-			<td>@dicoTitres[p.TitreId].Civilite</td>
-			<td>@p.Prenom</td>
-			<td>@p.Nom</td>
-			<td>@p.Telephone</td>
-		</tr>
+
+	using( Ajax.BeginForm( "Edition", new AjaxOptions() { HttpMethod = "POST", UpdateTargetId = "LigneEnEdition", InsertionMode = InsertionMode.ReplaceWith } ) ) {
+
+		<input type="hidden" name="id" value="" id="idPersonneAEditer" />
+
+		<table class="table table-bordered table-condensed table-striped">
+			<tr>
+				<th>Actions</th>
+				<th>@Html.DisplayNameFor( m => m.TitreId ) </th>
+				<th>@Html.DisplayNameFor( m => m.Prenom ) </th>
+				<th>@Html.DisplayNameFor( m => m.Nom ) </th>
+				<th>@Html.DisplayNameFor( m => m.Telephone ) </th>
+			</tr>
+			@foreach( var p in personnes ) {
+				<tr>
+					<td>
+						<input type="submit" name="Edit" value="Éditer" class="btn btn-default"
+									 onclick="preparerEdition(this)" data-id="@p.Id" />
+					</td>
+					<td>@dicoTitres[p.TitreId].Civilite</td>
+					<td>@p.Prenom</td>
+					<td>@p.Nom</td>
+					<td>@p.Telephone</td>
+				</tr>
+			}
+		</table>
 	}
-</table>
-}
+}
+
+@section scripts {
+
+	<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
+
+	<script type="text/javascript">
+		function preparerEdition(btEdition) {
+			var $ligneDuBouton = $(btEdition).closest("tr");
+			$ligneDuBouton.prop("id", "LigneEnEdition");
+			$("#idPersonneAEditer").val($(btEdition).attr( "data-id" ));
+		}
+	</script>
+}

+ 18 - 0
mySolution/EmpForm/EmpForm/Views/Annuaire/LigneEnEdition.cshtml

@@ -0,0 +1,18 @@
+@model DAL.Personne
+@{ 
+	IEnumerable<DAL.Titre> titres = ViewBag.Titres;
+}
+<tr id="LigneEnEdition">
+	<td>
+		<input type="submit" name="Update" value="OK" class="btn btn-success" />
+		<input type="submit" name="Cancel" value="KO" class="btn btn-warning" />
+		@Html.ValidationSummary()
+	</td>
+	<td>@Html.DropDownListFor( m => m.TitreId, titres.Select( t => new SelectListItem() { Text = t.Civilite, Value = t.Id.ToString() } ), new { @class = "form-control" } )</td>
+	<td>@Html.TextBoxFor( m => m.Prenom, new { @class = "form-control" } )</td>
+	<td>@Html.TextBoxFor( m => m.Nom, new { @class = "form-control" } )</td>
+	<td>
+		@Html.TextBoxFor( m => m.Telephone, new { @class = "form-control" } )
+		@Html.AllValidationMessagesTooltipFor( m => m.Telephone )
+	</td>
+</tr>

+ 15 - 0
mySolution/EmpForm/EmpForm/Views/Annuaire/LigneEnLecture.cshtml

@@ -0,0 +1,15 @@
+@model DAL.Personne
+@{ 
+	IDictionary<short, DAL.Titre> dicoTitres = ViewBag.Titres;
+}
+
+<tr>
+	<td>
+		<input type="submit" name="Edit" value="Éditer" class="btn btn-default"
+					 onclick="preparerEdition(this)" data-id="@Model.Id" />
+	</td>
+	<td>@dicoTitres[Model.TitreId].Civilite</td>
+	<td>@Model.Prenom</td>
+	<td>@Model.Nom</td>
+	<td>@Model.Telephone</td>
+</tr>

+ 1 - 0
mySolution/EmpForm/EmpForm/packages.config

@@ -10,6 +10,7 @@
   <package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net461" />
   <package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net461" />
   <package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.0" targetFramework="net461" />
+  <package id="Microsoft.jQuery.Unobtrusive.Ajax" version="3.2.3" targetFramework="net461" />
   <package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.3" targetFramework="net461" />
   <package id="Microsoft.Net.Compilers" version="1.0.0" targetFramework="net461" developmentDependency="true" />
   <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net461" />

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio