In diesem Blog wird gezeigt wie man in Minutenschnelle zu einem Web basierten Formular kommt.
Zunächst wird mit Visual Studio 2013 ein neues Web Projekt mit Web Forms erzeugt.
Dem Projekt werden per Nuget Paket Manager unter anderem das DynamicData Paket hinzugefügt. Dies wird dann für das Templating benötigt.
Weiters wird die JavaScript Erweiterung JQuery Mobile installiert.
Nuget erlaubt das aktualisieren aller installierten Paket wie Bootstrap oder JQuery. Das dauert am längsten.
Im nächsten Schritt wird ein Entity Framework Modell hinzugefügt. Dazu wird die Vorlage ADO.NET Entity Data Model benutzt.
Das Model wird aus einer im SQL Server vorhandenen Northwind Datenbank generiert.
Die Verbindung zum Datenbank Server muss konfiguriert werden. Nötige Parameter Server Name, Benutzer, Passwort. In diesem Screenshot wird die integrierte Authentifizierung verwendet.
Im nächsten Schritt wird definiert, das der Connection String dauerhaft in der Datei web.config abgelegt werden soll. Damit kann aus verschiedenen Stellen der Programmlogik darauf zugegriffen werden.
Im folgenden werden die Tabellen für das Modell ausgewählt. Im Beispiel die Tabellen Customers und Orders.
Das Modell wird gespeichert und das Projekt vorsichtshalber kompiliert. Im nächsten Schritt wir die ASPX Seite erzeugt bzw. dem Projekt hinzugefügt.
In den HTML Code der ASPX Seite wird ein FormView Control eingefügt. Mit Hilfe von Modelbinding wird zuerst (Zeile 3) der Itemtype definiert. Dann erzeugt Visual Studio beim erstellen von SelectMethod und UpdateMethod im Codebehind automatisch die Methodenrümpfe.
Besonderes Highlight ist das DynamicEntity Steuerelement das aus dem Datenmodell die Felder automatisch erzeugt.
1: <asp:FormView ID="FormView1" runat="server"
2: RenderOuterTable="false"
3: ItemType="WebApplication1Demo.Customers"
4: SelectMethod="FormView1_GetItem"
5: UpdateMethod="FormView1_UpdateItem"
6: DefaultMode="Edit"
7: DataKeyNames="CustomerID">
8: <EditItemTemplate>
9: <asp:DynamicEntity runat="server" Mode="Edit" />
10: </EditItemTemplate>
11: </asp:FormView>
Mit der Methode GetItem wird aus der URL der Parameter ausgelesen und damit auf dem Model in der Customers Tabelle der passende Schlüssel gesucht.
1: PublicFunction FormView1_GetItem(<FriendlyUrlSegments(0)> CustomerId AsString)
As WebApplication1Demo.Customers
2: Dim nw AsNew NorthwindEntities
3: Return nw.Customers.Find(CustomerId)
4: End Function
Man kann es kaum glauben, aber nach knapp 2 Minuten existiert ein funktionsfähiges Formular.
Sieht noch nicht gut aus. Die Benennung der Felder, die Reihenfolge und auch die Validierungsregeln lassen sich über Metadaten im Model vorgeben. Fachausdruck DataAnnotations. Um diese dauerhaft zu definieren erzeugt man eine partielle Klasse mit identen Namen. Der wiederum weist man eine Metadaten Klasse zu in der dann die Attribute definiert werden.
1: Imports System.ComponentModel.DataAnnotations
2:
3: PublicClass CustomersMetadata
4: <Editable(False)>
5: <Display(Name:="Kundennr")>
6: PublicProperty CustomerID AsString
7: <Required(ErrorMessage:="erforderlich")>
8: <Display(Name:="Firma")>
9: PublicProperty CompanyName AsString
10: <Display(Name:="Name")>
11: PublicProperty ContactName AsString
12: <Display(Name:="Titel")>
13: PublicProperty ContactTitle AsString
14: <Display(Name:="Adresse")>
15: PublicProperty Address AsString
16: <Display(Name:="Stadt")>
17: PublicProperty City AsString
18: <Display(Name:="Region")>
19: PublicProperty Region AsString
20: <MaxLength(5, ErrorMessage:="zu lang")>
21: <Display(Name:="PLZ")>
22: PublicProperty PostalCode AsString
23: <Required(ErrorMessage:="bitte füllen")>
24: <Display(Name:="Land")>
25: PublicProperty Country AsString
26: <Display(Name:="Telefon")>
27: PublicProperty Phone AsString
28: <Display(Name:="Telefax")>
29: PublicProperty Fax AsString
30: PublicProperty LastChange AsByte()
31:
32: PublicOverridableProperty Orders As ICollection(Of Orders) = New HashSet(Of Orders)
33: EndClass
34:
35: <MetadataType(GetType(CustomersMetadata))>
36: Partial PublicClass Customers
37:
38:
39: EndClass
Schon sieht das im Browser ganz gut aus. Die Kundennummer ist nicht mehr editierbar.
Jetzt fehlt nur noch die Möglichkeit die geänderten Daten auch zu speichern. Der Methodenrumpf für UpdateItem muss nur in Zeile 4-5 ergänzt werden und Zeile 14. Sekundenaufwand.
1: PublicSub FormView1_UpdateItem(ByVal CustomerID AsString)
2: Dim item As WebApplication1Demo.Customers = Nothing
3: ' Element hier laden, z. B. item = MyDataLayer.Find(id)
4: Dim nw = New NorthwindEntities
5: item = nw.Customers.Find(CustomerID)
6: If item IsNothingThen
7: ' Das Element wurde nicht gefunden.
8: ModelState.AddModelError("",
String.Format("Das Element mit der ID {0} wurde nicht gefunden.", id))
9: Return
10: EndIf
11: TryUpdateModel(item)
12: If ModelState.IsValid Then
13: ' Änderungen hier speichern, z. B. MyDataLayer.SaveChanges()
14: nw.SaveChanges()
15: EndIf
16: End Sub
Letztlich fehlt noch der deklarative Teil im Web Forms Control. Zwei Buttons übernehmen per Commandname die Funktion.
1: <fieldsetdata-role="controlgroup"data-type="horizontal">
2: <asp:Buttonrunat="server"ID="UpdateButton"
CommandName="Update"Text="Update"/>
3: <asp:Buttonrunat="server"ID="CancelButton"
CommandName="Cancel"Text="Cancel"CausesValidation="false"/>
4: </fieldset>
War ganz einfach. Und das editieren und speichern klappt nun auch.
Optisch fehlt noch ein wenig, aber dafür kommt nun JQM zum Einsatz. Im HTML Code werden nur geringfügige Ergänzungen vorgenommen. Das Form (Zeile 7) die data-role und das Theme. Zeile 8 den Content Bereich. Zeile 18 die ControlGroup.
1: <linkhref="/Content/jquery.mobile-1.4.0.css"rel="stylesheet"/>
2: <scriptsrc="/Scripts/jquery-2.1.0.js"></script>
3: <script src="/Scripts/jquery.mobile-1.4.0.js"></script>
4: </head>
5: <body>
6:
7: <formid="form1"runat="server"data-role="page"data-theme="a">
8: <divdata-role="content">
9: <asp:FormViewID="FormView1"runat="server"
10: RenderOuterTable="false"
11: ItemType="WebApplication1Demo.Customers"
12: SelectMethod="FormView1_GetItem"
13: UpdateMethod="FormView1_UpdateItem"
14: DefaultMode="Edit"
15: DataKeyNames="CustomerID">
16: <EditItemTemplate>
17: <asp:DynamicEntityrunat="server"Mode="Edit"/>
18: <fieldsetdata-role="controlgroup"data-type="horizontal">
19: <asp:Buttonrunat="server"
ID="UpdateButton"CommandName="Update"Text="Update"/>
20: <asp:Buttonrunat="server"
ID="CancelButton"CommandName="Cancel"Text="Cancel"CausesValidation="false"/>
21: </fieldset>
22: </EditItemTemplate>
23: </asp:FormView>
Sieht im Browser schon fast ganz fertig aus.
Problem entsteht wenn der Benutzer bei der Eingabe eine validierungsregel bricht. Der Benutzer sieht nur einen Stern und die Fehlermeldung nur wenn er die Maus über den Stern bewegt.
Ein ValidationSummary Control würde den Text anzeigen. Allerdings kann man auch in die DynamicData Templates eingreifen. Dafür sind sie eigentlich auch da. Der Ordner EntityTemplates wird vom DynamicEntity Control benutzt. Das DynamicControl nutzt dann wiederum abhängig vom Datentyp die UserControls aus dem Ordner Fieldtemplates.
Da es sich um ein Text im Edit Modus handelt, wird der VB.NET Code in der Datei text_edit.ascx.vb um die Zeilen 4-5 ergänzt.
1: SetUpValidator(RequiredFieldValidator1)
2: SetUpValidator(RegularExpressionValidator1)
3: SetUpValidator(DynamicValidator1)
4: RequiredFieldValidator1.Text = ""
5: RegularExpressionValidator1.Text = ""
6: DynamicValidator1.Text = ""
In diesem Walkthrough fehlen noch die Templates für Insert und die Funktionen für Delete und Insert. Diese sind aber analog sehr einfach zu realisieren.