ASP.NET MVC Futures – Templates
Då det här gäller ASP.NET MVC Futures så innebär det att innehållet nedan kan komma att försvinna helt i framtiden. Det är möjligt att använda det nu, men använd det inte till skarpa projekt då det kan försvinna framöver.
En av de stora nyheterna i ASP.NET MVC 2 är templates för visning och editering av data. Det har tidigare funnits med för Dynamic Data, där det fanns liknande templates inbyggda. Dessa fungerar dock ej med ASP.NET MVC 2, utan då får man istället skapa nya som har samma funktionalitet.
I ASP.NET MVC RTM Futures så ingår dock ett antal templates, vilka kan användas direkt genom att kopiera och klistra in dem i ett projekt. De är inte hårt kopplade mot någon av ASP.NET MVC Futures-binärerna, utan kan användas i vilket ASP.NET MVC 2-projekt som helst.
För att testa det så behövs ASP.NET MVC Futures, vilket kan laddas ned här:
http://aspnet.codeplex.com/releases/view/41742
Om vi packar upp filen så kan vi hitta en mapp kallad ” DefaultTemplates”. Där finns alla templates. Kopiera innehållet i mappen till Views\Shared i ditt ASP.NET MVC 2-projekt så har du allt du behöver.
För att se hur de fungerar så behöver vi först en modell. Vi skapar upp en ny klass vid namn ”UberType”. Den kommer att ha properties som kan mappas upp mot alla nya templates.
Utseendet på klassen blir:
public class UberType
{
public int Id { get; set; }
public bool EnBoolean { get; set; }
public List<string> EnCollection { get; set; }
public Decimal EnDecimal { get; set; }
public string EnEmailAddress { get; set; }
public string EnHiddenInput { get; set; }
public string EnHtml { get; set; }
public Object EnObject { get; set; }
public string EnString { get; set; }
public string EnUrl { get; set; }
public string EnMultilineText { get; set; }
}
Vi skapar sedan en ny Controller, kallad DataController. Här har vi action-metoder för att lista, visa detaljer, visa ett redigeringsformulär samt en enkel metod som genererar lite dummy-data.
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using MvcFuturesWeb.Models;
namespace MvcFuturesWeb.Controllers
{
public class DataController : Controller
{
// GET: /Data/
public ActionResult Index()
{
List<UberType> ut = GetData();
return View(ut);
}
// GET: /Data/Details/5
public ActionResult Details(int id)
{
UberType ut = GetData().Where(d => d.Id == id).FirstOrDefault();
return View(ut);
}
// GET: /Data/Edit/5
public ActionResult Edit(int id)
{
UberType ut = GetData().Where(d => d.Id == id).FirstOrDefault();
return View(ut);
}
private List<UberType> GetData()
{
return new List<UberType>() {
new UberType()
{
Id = 1,
EnBoolean = true,
EnCollection = new List<string>() { "Mikael", "Bill", "Nisse" },
EnDecimal = 1.2M,
EnEmailAddress = "test@example.com",
EnHiddenInput = "Hemligt!",
EnHtml = "Texten är <b>fet</b> ibland, men det händer även att den är <i>kursiv</i>.",
EnMultilineText = "Flera\nrader\ntext!",
EnObject = (object)123,
EnString = "Lite text",
EnUrl = "http://www.example.com",
},
new UberType()
{
Id = 2,
EnBoolean = false,
EnCollection = new List<string>() { "Mikael", "Bill", "Nisse" },
EnDecimal = 10M,
EnEmailAddress = "test@example.com",
EnHiddenInput = "Hemligt!",
EnHtml = "Texten är <b>fet</b> ibland, men det händer även att den är <i>kursiv</i>.",
EnMultilineText = "Flera\nrader\ntext!",
EnObject = (object)"Text istället",
EnString = "Lite mer text",
EnUrl = "http://www.example.com",
}
};
}
}
}
Sedan behövs views för dessa, så högerklicka i metoderna och välj ”Add View”. Glöm inte att välja att ha UberType som modell, samt att välja rätt typ av template (List, Edit, Details).
För att få lite mindre kod i vyerna så ändrar vi vyerna för Edit och Details en aning.
Edit:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcFuturesWeb.Models.UberType>" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Edit</h2>
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Fields</legend>
<%= Html.EditorForModel() %>
<input type="submit" value="Save" />
</fieldset>
<% } %>
</asp:Content>
Details:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcFuturesWeb.Models.UberType>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Details
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Details</h2>
<%= Html.DisplayForModel() %>
<p>
<%=Html.ActionLink("Edit", "Edit", new { id=Model.Id }) %> |
<%=Html.ActionLink("Back to List", "Index") %>
</p>
</asp:Content>
DisplayForModel() och EditorForModel() renderar automatiskt alla fält med deras värden, vilket passar perfekt i det här fallet.
Om vi nu besöker sidan så har vi en vanlig sida med möjlighet att visa all data, detaljer för en viss entitet, samt möjlighet att ändra dem.
Problemet här är att alla fält hanteras likadant, oavsett vad de har för syfte. Länkar visas inte som länkar, textfält som skall finnas på flera rader visas bara i en vanlig text-ruta istället för i en textarea och så vidare.
För att lösa detta så kan vi skapa upp egna templates, vilket jag har skrivit om tidigare:
http://weblogs.asp.net/mikaelsoderstrom/archive/2009/09/24/introduktion-till-asp-net-mvc-2.aspx
Nu slipper vi dock skapa upp alla templates, utan kan istället använda oss utav de vi har fått med ASP.NET Futures.
För att ta nytta av dessa så behöver vi bara ändra i modellen, resten sköter sig självt.
Det vi behöver göra i modellen är att i första hand använda DataType-attributet, och om det inte finns där så kan vi använda UIHint-attributet.
Den slutliga modellen blir, efter ändringarna:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace MvcFuturesWeb.Models
{
public class UberType
{
[UIHint("HiddenInput")]
public int Id { get; set; }
[UIHint("Boolean")]
public bool EnBoolean { get; set; }
[UIHint("Collection")]
public List<string> EnCollection { get; set; }
[UIHint("Decimal")]
public Decimal EnDecimal { get; set; }
[DataType(DataType.EmailAddress)]
public string EnEmailAddress { get; set; }
[UIHint("HiddenInput")]
public string EnHiddenInput { get; set; }
[DataType(DataType.Html)]
public string EnHtml { get; set; }
[UIHint("Object")]
public Object EnObject { get; set; }
[DataType(DataType.Text)]
public string EnString { get; set; }
[DataType(DataType.Url)]
public string EnUrl { get; set; }
[DataType(DataType.MultilineText)]
public string EnMultilineText { get; set; }
}
}
Om vi ser hur Edit- och Details-sidorna ser ut nu så har de automatiskt använt templates på de ställen där vi vill ha det.
Edit:
Details:
Vi kan självklart modifiera dessa om vi vill ha dem annorlunda, samt även skapa helt nya som vi kan använda istället.