Custom Model binder en ASP.NET MVC Beta

Après plusieurs semaines sans Internet à domicile, me revoici en ligne avec le reste du monde ;-).. J'en profite pour publier un article sur la gestion des "Binders" en ASP.NET MVC.

  1. BINDERS ? Kezako ?
  2. Il existe un mécanisme de binding qui offre la possibilité de passer un "objet métier" à une méthode d'un controlleur. L'objet "Binder" fera cette traduction entre ce qui se trouve dans l'objet Form ASP.NET et l'objet métier. La liaison se définit dans le fichier global.asax.
  3. Exemple visuel
    • Un formulaire basique d'insertion d'une facture

    • On ne donne pas le montant de la facture. Il s'agit d'une erreur "bloquante"

    • Le binding s'effectuera et remplira l'objet métier qui sera passé à la méthode du controlleur. De plus on affichera une erreur pour signaler que l'on a encodé une valeur erronnée
  4. Exemple de code
    • Implémentation du binding de la classe Invoice
    • public class InvoiceBinder : IModelBinder
      {
      #region IModelBinder Members

      public ModelBinderResult BindModel(ModelBindingContext bindingContext)
      {
      if (bindingContext == null)
      throw new ArgumentNullException("bindingContext");
      Invoice invoice = new Invoice();
      NameValueCollection values = bindingContext.HttpContext.Request.Form;
      invoice.CustomerName = values["CustomerName"];
      try
      {
      string totalAmount = values["TotalAmount"];
      if (string.IsNullOrEmpty(totalAmount))
      bindingContext.ModelState.AddModelError("TotalAmount",
      "Ce champ est obligatoire !");
      else
      invoice.TotalAmount = Convert.ToSingle(values["TotalAmount"]);
      }
      catch (Exception ex)
      {
      bindingContext.ModelState.AddModelError("TotalAmount", ex);
      }
      return new ModelBinderResult(invoice);
      }

      #endregion
      }
    • Déclaration du binding dans le Global.asax
    • protected void Application_Start()
      {
      ModelBinders.Binders[typeof(Invoice)] = new InvoiceBinder();
      ModelBinders.DefaultBinder = new DefaultModelBinder();
      RegisterRoutes(RouteTable.Routes);
      }

    • Implémentation du controlleur
    • [HandleError]
      public class HomeController : Controller
      {
      public ActionResult Index()
      {
      return RedirectToAction("Create");
      }

      [AcceptVerbs("GET")]
      public ActionResult Create()
      {
      return View(new Invoice());
      }

      [AcceptVerbs("POST")]
      public ActionResult Create(Invoice invoice)
      {
      return View(invoice);
      }
      }

    • Implémentation du formulaire
    • <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
      AutoEventWireup="true" CodeBehind="Create.aspx.cs"
      Inherits="DemoMVC.Views.Home.Create" %>

      <asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">
      <h2>
      Add invoice :
      </h2>
      <% Html.BeginForm("Create", "Home"); %>
      <table>
      <tr>
      <td>
      Customer Name :
      </td>
      <td>
      <%= Html.TextBox("CustomerName") %>
      </td>
      </tr>
      <tr>
      <td>
      Total amount :
      </td>
      <td>
      <%= Html.TextBox("TotalAmount") %>
      <%= Html.ValidationMessage("TotalAmount") %>
      </td>
      </tr>
      </table>
      <input type="submit" value="Click clack" />
      <% Html.EndForm(); %>
      </asp:Content>
  5. Conclusion
  6. Ce petit post se termine ici. Il ne se focalise pas trop sur les binders ... mais plutôt sur le couple ModelState + Binder. Il n'empêche ... ce mécanisme de binder offre de belles perspectives !

Ajouter un commentaire

Le code HTML est affiché comme du texte et les adresses web sont automatiquement transformées.

Fil des commentaires de ce billet

Page top