Erster Eindruck von ASP.NET MVC mit dem Visual Web Developer Express

Die ASP.NET Extension CTP ist schon eine kleine Weile verfügbar, jedoch bin ich erst heute dazu gekommen, mir dies mal anzuschauen.

Da ich auf meinem privat Notebook kein Visual Studio 2008 Standard (oder höher) hab, benutze ich den Visual Web Developer 2008 (was wahrscheinlich bei vielen Leuten zutrifft).

Vorbereitung: 

ASP.NET 3.5 Extensions installieren und Visual Web Developer Web Site “MVC tauglich” machen

Nachdem man die CTP installiert hat, findet man im Visual Web Developer zwar eine Vorlage für “ASP.NET 3.5 Extensions Web Site”, allerdings unterstützt die CTP momentan nur Web Projects – daher nützt uns das nur sehr wenig.

Eine Installationsanleitung befindet sich hier. Insbesondere muss man da auch die Kommentare lesen, dann wird es klarer. Aber nochmal zusammengefasst:

  • web.config unter dem Punkt “system.web”-”pages” anpassen:
         <namespaces>
            <add namespace="System.Web.Mvc"/>
            <add namespace="System.Linq"/>
         </namespaces>

(warum weiß ich auch noch nicht so genau, das bekommen wir bestimmt noch raus ;) )

  • global.asax und Default Routing unter “Application_Start()” hinzufügen:
    void Application_Start(object sender, EventArgs e) 
    {
        RouteTable.Routes.Add(new Route
        {
            Url = "[controller]/[action]/[id]",
            Defaults = new { action = "Index", id = (string)null },
            RouteHandler = typeof(MvcRouteHandler)
        }); 

    }
  • Ordnersturktur anpassen:

image

Erklärung: Unter “App_Code” befinden sich unsere Controller und Models, die Views kommen ins Root Verzeichnis.

Die Default.aspx im Rootverzeichnis ist komplett leer.

Der Ordner “Shared” ist für Masterpages, User Controls etc. gedacht.

Mein .ASPX Seiten haben kein Codefile mehr, sondern erben direkt von “System.Web.Mvc.ViewPage”, z.B.:

<%@ Page Language="C#" 
MasterPageFile="~/Views/Shared/Site.master"
AutoEventWireup="true"
Inherits="System.Web.Mvc.ViewPage"
Title="Bookstorage | Search" %>

Die Masterseite ist normal, enthält aber kein “form” Tag und auch keinen ScriptManager für ASP.NET AJAX – da müsste man nochmal genau nachschauen wie  man das geschickt macht (darauf komme ich später nochmal).

Die Webapplikation strukturieren

Insgesamt ist die Website sehr simpel gehalten, daher bitte nicht wundern.

Das Model

Es gibt eine einfache “Book” Klasse sowie eine Klasse “BookCollection”, welche von “List<Book>” erbt.
Der “BookCollectionManager” hat eine Methode “GetBookCollection”, welche einfach so eine Collection zurückgibt.

Die Controller

Der HomeController macht nix großes bzw. sieht man das auch gut am SearchController wie ich diesen aufgebaut habe:

public class SearchController : Controller
{

    [ControllerAction]
    public void Index()
    {
        RenderView("Index");
    }

    [ControllerAction]
   public void Results(string query)
   {
        BookCollectionManager man = new BookCollectionManager();
        BookCollection data = man.GetBookCollection(query, 1);
        ViewData["BookCollection"] = data;
        RenderView("Results");
   }
}

In dem Controller geibts einmal den Index (der laut unserer Routingtabelle in der globals.asax der Default Controller ist) und sagt nur, dass er den View “Index(.aspx)” Rendern soll. Dabei sucht er genau in dieser Ordnerstruktur nach “Search” etc.

Unsere “Results” Methode ist eigentlich unsere Suchmethode und spricht unser Backend (was einfach nur eine Collection an 25 Einträgen zurück gibt) an. Die Daten werden dann in ViewData gespeichert und autoamtisch übergeben. Scott hat auch noch andere Methoden beschrieben – dies war erstmal die Einfachste. Dannach wird der View “Results” gerendert.

Daten an den Controller übergeben

Zwar haben wir jetzt unseren Controller, aber wie übergeben wir diesem was?

Ganz einfach über ein HTML Formular:

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolderContent" Runat="Server">
<form id="searchform" action="/Intro/Search/Results" method="post">
    <span>Search:</span>
    <input type="text" name="query" />
    <button type="submit">Suchen</button>
</form>

</asp:Content>

Die Form verweisst auf unsere “Results” Methode – wichtig dabei ist, dass der name des übergebenen Parameter mit dem der Methode übereinstimmt. Dies stößt unseren Controller an, welcher dann wiederrum den View rendert.

Problem mit ASP.NET AJAX:
Hier will ich nochmal kurz mein Problem mit dem ScriptManager erläutern. Da ich in der Masterpage kein “form” hab (wie im normalen ASP.NET) üblich, sondern es nur dort einsetzen möchte, wo ich es für sinnvoll halte (wie z.B. hier) und die action URL je nachdem darauf ausrichten möchte, gibt es leider ein Problem mit ASP.NET AJAX.
Dadurch kann man den ScriptManager nur unschön in die MasterPage hinzufügen, da dieser ein “<form runat=”server”>… verlangt. Eine Lösung gibt es bestimmt (vielleicht über das MVCToolkit) oder man fügt den ScriptManager auf den Seiten hinzu, wo man ihn benötigt. 2 Formuale (eine in der Masterpage & eine auf der Contentpage) ist irgendwie “unschön”, aber da müsste man nochmal nachschauen. Microsoft macht sich selbst auch Gedanken und ich denke, da kommt noch eine bessere Integration insgesamt, weil man zwar den ScriptManager einsetzen könnte, aber dann wiederrum die Controller etc. übergeht – und das ist ja nicht Sinn der Sache.

Die übergebenen Daten darstellen

In jedem View benutze ich meine simple Masterpage, daher ist dies der wesentliche Code in der “Result.aspx”:

<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolderContent" Runat="Server">
Search Results:

<table>
<%foreach (var returnBook in (BookCollection)ViewData["BookCollection"])  { %>
<tr>
    <td><%= returnBook.Title %></td>
    <td><%= returnBook.Description %></td>
    <td><%= returnBook.PicUrl %></td>
</tr>
<% } %>
</table>
</asp:Content>

Über “ViewData["BookCollection"]” greife ich auf meine Daten zu und gebe sie einfach so aus. Ob nun “var” (also ein anonymer Typ) da richtig ist, weiß ich noch nicht ganz ;) , es funktioniert jedenfalls:

image

Das Demoprojekt testen/download & Fazit

Startet nicht das Projekt wenn ihr gerade die ASPX Seiten geöffnet habt, da dann z.B. bei der Result.aspx eine Exception geworfen wird ;) – öffnet die leere Default.aspx und gebt dann manuell die jeweiligen URLs (siehe oben) ein.

Wenn man sich erstmal eingearbeitet hat, macht es sehr viel Freude, zu sehen, dass man diesmal volle Kontrolle über den HTML Code hat und es (jedenfalls für mich) klarer ist, wie man bestimmte HTML Elemente dynamisch rendert. Das es noch hier und da (ASP.NET AJAX) Schwierigkeiten gibt, ist natürlich bei so einer Preview verständlich.
Dies waren auch nur meine ersten Schritte, sodass ich wahrscheinlich noch nicht alles optimal gemacht habe ;)

[ Download Source Code ]

Wenn dir der Blogpost gefallen hat, dann hinterlasse doch einen Kommentar. Wenn du auf dem Laufenden bleiben willst, abonniere unseren RSS Feed oder folge uns auf Twitter.

About the author

Written by

Hi, ich bin Robert Mühsig und bin Webentwickler und beschäftige mich mit Web-Frameworks auf dem Microsoft Web Stack und scheue mich auch nicht vor Javascript. Der Blog begann als "Problemsammelstelle und Lösungshilfe" und seitdem schreibe ich hier alles auf. Seit 2008 bin ich Microsoft MVP für ASP.NET. Treffen kann man mich online via Twitter (@robert0muehsig) oder hier.

4 Responses

  1. War riesig hilfreich, vielen Dank! Funzt super!

    Reply

Comment on this post

Letzte Posts

  • image.png
    Azure AppInsights: Ein mini Google Analytics für Websites

    Seit der Build Konferenz ist das neue Azure Portal für alle freigeschaltet. Durch das neue Portal ist mir ein “Dienst” aufgefallen, den ich bisher nicht gesehen hatte: Azure Application Insights Viel weiss ich nicht über den Dienst, aber wer eine Azure Website hat der sollte mal die “Analytics” Box öffnen. Im Grunde handelt es sich […]

  • image.png
    Source Code veröffentlichen – aber bitte mit Lizenz

    Seit es den Blog gibt wird auch meist der gesamte Demo Source Code mit veröffentlicht. Das Ganze hatte ich am Anfang noch als .zip verteilt, später lag es mal auf Google Code und nun liegen alle Samples und sonstige Sachen auf GitHub. Beim letzten User Group Treffen in Zürich mit dem Titel “Open Source: Get […]

  • Fix: Cannot convert from ‘CConnectProxy::_ComMapClass *’ to ‘AddInDesignerObjects::IDTExtensibility2 *’

    Mal einen etwas esoterischer Blogpost, welcher auftaucht wenn man zu viel mit Office Addins rumspielt. Der Fehler passiert beim Bauen von C++ Projekten, welchen diesen Typ benötigen. Lösung (auf 64bit Systemen): C:\Program Files (x86)\Common Files\DESIGNER>regsvr32 MSADDNDR.DLL And Rebuild. Meine lieben Kollegen hatte mir dies schon mehrfach gesagt, allerdings hatte ich es immer wieder vergessen Das […]

  • Gegen das Gesetz verstoßen: X Jahre Haft. Gegen die Terms of Use verstoßen: Bann auf Lebenszeit. Danke Google & co.

    Bei fast allen Diensten die man im Internet nutzen kann muss man den “Terms of use” zustimmen. Völlig logisch dass da natürlich drin steht was erlaubt und was nicht. Wenn man gegen diese Regelungen verstößt hat das Unternehmen natürlich das Recht etwas dagegen zu unternehmen. In der heutigen Welt beherrschen einige wenige Unternehmen die digitale […]

  • image.png
    RSS Feed samt Kommentaranzahl und andere nicht Standard Elemente mit dem SyndicationFeed auslesen

    Jetzt mal ein Blogpost ohne ein fancy NuGet Package: Seit .NET 3.5 gibt es die SyndicationFeed Klasse. Eine schon etwas ältere API, reicht aber aus um Atom bzw. RSS Feeds zu lesen. In diversen RSS Feeds gibt es aber Erweiterungen, welche man natürlich auch auslesen möchte. So gibt WordPress z.B. auch die Anzahl der geposteten […]

Amazon Shop

Facebook