Categories: ASP.NET 2.0, DotNetHeute, German Posted by AlexanderZeitler on 6/19/2006 12:27 PM | Comments (2)

Mittels
<form id="form1" runat="server" defaultbutton="Button1">
kann man in ASP.NET 2.0 relativ einfach einen Default-Button (der Button, der durch Drücken der Return-Taste ausgelöst wird) für das aktuelle Formular definieren.

Allerdings funktioniert dies nur, wenn man nicht mit MasterPages arbeitet, d.h. den Default-Button nicht in einer Content-Seite (z.B. Default.aspx, welche auf die MasterPage verweist) definieren will.

Ähnlich gestaltet sich die Problematik bei Web User Controls. Entweder wird einfach der verkehrte Button ausgewählt, oder man erhält die Fehlermeldung:

The DefaultButton of 'form1' must be the ID of a control of type IButtonControl

Abhilfe kann man allerdings leicht mit ASP.NET 2.0 Bordmitteln schaffen, indem man ein ASP.NET Panel um den gewünschten Default-Button (+ den Controls, die den Button auslösen sollen, also z.B. TextBoxen etc.) setzt:

<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" runat="Server">
  <asp:Panel ID="Panel1" runat="server" DefaultButton="Button1" Height="50px" Width="125px">
    <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
    <asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Button" />
  </asp:Panel>
</asp:Content>

Wie man sieht, besitzt das ASP.NET Panel ebenfalls eine Eigenschaft DefaultButton über die man einen seitenweit geltenden Default-Button deklarieren kann.


	

Currently rated 1.1 by 15 people

  • Currently 1.133333/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Categories: Datenbanken, SQL Server 2005, Sql Server 2005 Express, DotNetHeute, German Posted by AlexanderZeitler on 5/21/2006 1:53 PM | Comments (2)

Thomas stand ja kürzlich vor dem Problem, eine CTE hierarchisch korrekt ausgeben zu wollen, was ihn zu Niels Berglund führte (Sorting Hierarchical CTE's).

Allerdings blieb ein Problem: Die Daten sind nun zwar hierarchisch sortiert - nicht jedoch alphabetisch innerhalb der Hierarchie.

Heute stand ich schließlich vor dem gleichen Problem - und ich glaube, ich habe eine Lösung gefunden ;-)

Ausgehend von einer Tabelle Kategorien, welche die Felder Name (nvarchar), ID (uniqueidentifier) und Parent (uniqueidentifier) besitzt, sollen also die Kategorien hierarchisch und alphabetisch dargestellt werden:

Korrekt wäre also z.B.:

Name ID Parent
Rohre und Formteile C55C8856-6205-4F76-A15A-6FCD4A68A831 00000000-0000-0000-0000-000000000000
Geschweißte Rohre und Formteile 9EEE0951-4E63-4494-BB18-88BCC1D4A3E5 C55C8856-6205-4F76-A15A-6FCD4A68A831
Rohrbögen geschweißt 8A137449-6108-47D2-8ED0-AE0EA4176EB2 9EEE0951-4E63-4494-BB18-88BCC1D4A3E5
Rohre geschweißt 085A0AA3-AB9D-4DD1-9739-77040E627445 9EEE0951-4E63-4494-BB18-88BCC1D4A3E5

Erhalten habe ich mit Niels' Lösung jedoch nur:

Name ID Parent
Rohre und Formteile C55C8856-6205-4F76-A15A-6FCD4A68A831 00000000-0000-0000-0000-000000000000
Geschweißte Rohre und Formteile 9EEE0951-4E63-4494-BB18-88BCC1D4A3E5 C55C8856-6205-4F76-A15A-6FCD4A68A831
Rohre geschweißt 085A0AA3-AB9D-4DD1-9739-77040E627445 9EEE0951-4E63-4494-BB18-88BCC1D4A3E5
Rohrbögen geschweißt 8A137449-6108-47D2-8ED0-AE0EA4176EB2 9EEE0951-4E63-4494-BB18-88BCC1D4A3E5

 

Nach einigem Experimentieren mit Views u.ä. bin ich auf folgende Lösung gekommen:

WITH CTE([Name], ID, ordercol, Parent)
AS
(
    SELECT [Name], ID, cast([Name] as varbinary(100)) ordercol, Parent

    FROM ProductCategory
    WHERE Parent= '{00000000-0000-0000-0000-000000000000}'
    UNION ALL

    SELECT    ProductCategory.[Name], 
        ProductCategory.ID, 
        cast(ordercol + CAST(ProductCategory.[Name] AS BINARY(4)) as varbinary(100)) ordercol, 
        ProductCategory.Parent

    FROM ProductCategory INNER JOIN

    CTE ON ProductCategory.Parent =
    CTE.ID
)

SELECT [Name], ID, Parent
FROM CTE
ORDER BY ordercol, [Name]

Damit erhielt ich o.g. gewünschtes hierarchisch und alphabetisch korrekt sortiertes Resultat. Außerdem funktioniert jetzt sogar die Änderung von ORDER BY auf [Name] DESC.

Currently rated 1.3 by 51 people

  • Currently 1.27451/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Categories: ASP.NET 2.0, DotNetHeute, German, System, VisualStudio 2005 Posted by AlexanderZeitler on 5/16/2006 10:50 AM | Comments (2)

Das ASP.NET 2.0 Web Site Administration Tool bietet eine komfortable Möglichkeit, ASP.NET 2.0 Webseiten zu administrieren - sei es, um die AppSettings zu konfigurieren oder auch User und Rollen zu verwalten.

Leider ist das Web Site Administration Tool seit Beta 2 nicht mehr via WebAdmin.axd für das jeweilige Web verfügbar, sondern nur noch via Visual Studio 2005 Menü "Website" / "ASP.NET Configuration" - Sicherheit ging vor.

Das Resultat war, dass man im Live-Betrieb (also ohne Visual Studio) div. Settings nun zwar noch via MMC-IIS-Manager vornehmen konnte, manche Einstellungen allerdings nur noch händisch via web.config oder gar per Code (Roles z.B.) - ein deutlicher Rückschritt also.

Deshalb habe ich mir heute mal die Frage gestellt: Wie bekomme ich mein Web Site Administration Tool ohne Visual Studio 2005 zum laufen? Nach einigem Fl/Suchen lief es schließlich...

Zunächst benötigen wir den "ASP.NET Development Server" auf dem Live-System. Hierzu muß man die beiden Dateien WebDev.WebServer.EXE und WebDev.WebServer.exe.manifest aus %WinDir%\Microsoft.NET\Framework\v2.0.50727 in das entsprechende .NET-Framework-Verzeichnis am Live-System kopieren, sofern dort nicht bereits vorhanden.

Weiterhin benötigen wir die WebDev.WebHost.dll, welche vermutlich auf dem lokalen System nur im GAC vorhanden sein dürfte. Um sie auf das Live-System zu bekommen, muß man sie per xcopy.exe auf der Kommandozeile (Windows-Explorer funktioniert hier nicht!!!) aus dem GAC kopieren.

Die WebDev.WebHost sollte sich im Normalfall hier befinden:

%WinDir%\assembly\GAC_32\WebDev.WebHost\8.0.0.0__b03f5f7f11d50a3a\WebDev.WebHost.dll

Nachdem man die Datei auf das Live-System kopiert hat, muß sie schließlich noch via

gacutil.exe /i WebDev.WebHost.dll

in den GAC des Live-Systems kopiert werden.

Der ASP.NET Development Server wird jetzt mit folgender Kommandozeile gestartet:

WebDev.WebServer.EXE /port:8080 /path:%WinDir%\Microsoft.NET\Framework\v2.0.50727\ASP.NETWebAdminFiles /vpath:/asp.netwebadminfiles

Wobei der Port nach Belieben gewählt, und im Gegensatz zum Aufruf aus Visual Studio 2005 somit auch manifestiert werden kann.

Um nun eine beliebige ASP.NET 2.0 Website oder ein virt. Verzeichnis administrieren zu können, fehlt noch der entsprechende Aufruf im Browser:

für Websites:

http://localhost:8080/asp.netwebadminfiles/default.aspx?applicationPhysicalPath=C:\Projects\MyWebsite\&applicationUrl=/

für virt. Verzeichnisse:

http://localhost:8080/asp.netwebadminfiles/default.aspx?applicationPhysicalPath=C:\Projects\MyWebsite\MyVirtDirectory\&applicationUrl=/MyVirtDirectory

Schließlich noch den Aufruf des Development Servers als Verknüpfung auf dem Desktop und den Link in den Favoriten gespeichert und einer einfachen Administration steht nichts mehr im Weg ;-)

Aus Sicherheitsgründen sollte man den Web Development Server natürlich nur starten, wenn man ihn auch benötigt.

Hier noch ein Blick auf den Lohn der Mühen:

Currently rated 1.3 by 16 people

  • Currently 1.25/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Categories: ASP.NET 2.0, DotNetHeute, German Posted by AlexanderZeitler on 4/20/2006 6:08 PM | Comments (0)

Thomas' Problem mit DropDownLists und DataBinding von Null-Werten löse ich wie folgt:

Ausgehend von der Problemstellung, dass 0-(Null-)Werte an eine DropDownList innerhalb einer Grid-/Form-/Details-View gebunden werden sollen, habe ich in der Datentabelle für ein Menü (z.B. für ein CMS, das dann über die FormView/DropDownList verwaltet werden soll) ein Feld "IsChildOf", welches auf die ID derselben Tabelle verweist, jedoch NULL-Werte zulässt:

´

Die Datenansicht der Tabelle könnte dann z.B. so aussehen:

In der Seite (bzw. dem .ascx) existiert nun eine SqlDataSource (hier SqlDataSource1 - der Einfachheit wegen nicht über ObjectDataSource), die die jeweilige SeitenID aus dem QueryString liest und anhand derer die Seite aus der Datenbank holt:

Die übergeordneten Seiten sind in einer  DropDownList (hier DropDownList1) dargestellt, so dass man leicht über den Klartext auswählen kann, welches eben die übergeordnete Seite ist.

Alle Seiten werden über die SqlDataSource "AllPagesDataSource" gelesen und an DropDownList1 gebunden.

Die Vorauswahl der aktuell eingestellten übergeordneten Seite geschieht über das DataBinding des SelectedValue der DropDownList an das Feld "IsChildOf":

Würde nun z.B. die Seite mit der ID 73 zur Bearbeitung geöffnet, würde man zu Laufzeit die Fehlermeldung erhalten, dass der Wert (in diesem Fall 0) für SelectedValue der DropDownList1 nicht existiert - was auch korrekt ist.

Diese Problem lässt sich nun leicht umgehen, indem man ein fixes Item zur DropDownList hinzufügt, dessen Value "0" ist und z.B. den Wert "Hauptseite" hat:

Nun muß man noch die Eigenschaft AppendDataBoundItems auf True setzen, damit die Items aus der SqlDataSource an das fixe Item angehängt werden.

Das Resultat im Browser:

Jetzt hoffe ich nur noch, dass ich Thomas' Problem richtig interpretiert habe ;-)

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Categories: ASP.NET 2.0, DotNetHeute, German Posted by AlexanderZeitler on 3/10/2006 5:08 PM | Comments (3)

Das ist ASP.NET 2.0 Menu-Control ist bereits sehr mächtig - insbesondere in Verbindung mit den .SiteMap-Files.

Nichtsdestotrotz hat man unter Umständen Kriterien, bei deren Eintreten man bestimmte Menü-Items nicht anzeigen möchte.

Generell erledigt man dies am einfachsten im ItemDataBound-Event des Menu-Controls - allerdings hat e.Item keine Eigenschaft .Visible oder gar eine .Remove-Methode. Der folgende Code zeigt (am Beispiel von Rollen via XmlDataSource, via SiteMap natürlich einfacher zu lösen - aber es geht um das Prinzip ;-)) , wie man das Problem trotzdem leicht lösen kann:

protected void Menu1_MenuItemDataBound(object sender, MenuEventArgs e) {
    System.Xml.XmlElement menuItem = (System.Xml.XmlElement)e.Item.DataItem;
    foreach (XmlAttribute att in menuItem.Attributes) {
        if (att.Name.ToLower() == "roles") {
            string roles = att.Value;
            string[] arrRoles = roles.Split(",".ToCharArray());
            for (int count = 0; count <= arrRoles.Length - 1; count++) {
                if (!Page.User.IsInRole(arrRoles[count])) {
                    Menu1.Items.Remove(e.Item);
                }
            }
        }
    } 
}

Das entsprechende Xml-File (vereinfacht):

<?xml version="1.0" encoding="utf-8"?>
<Menu>
    <Entry Text="Home" URL="~/default.aspx" />
    <Entry Text="Registrieren" URL="~/register.aspx" />
    <Entry Text="Seiten bearbeiten" URL="~/content.aspx" roles="Administrators" />
    <Entry Text="Benutzerprofil" URL="~/profile.aspx" />
    <Entry Text="Benutzerverwaltung" URL="~/users.aspx" roles="Administrators" />
<Menu>

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5