vrijdag 31 oktober 2008

Verbergen van Next / Previous controls in ASP.NET WizardControl

Vandaag had ik een probleem met het verbergen van de Next / Previous links/buttons van een ASP.NET WizardControl.

Hierbij liep ik tegen 2 problemen aan:
  1. Middels de standaard methode FindControl op het WizardControl object kan de betreffende LinkButton niet gevonden worden. Hiervoor het ik zelf een FindControl methode gemaakt, welke hieronder is bijgevoegd
  2. Het aanpassen van de eigenschap [LinkButton].Visible naar False blijkt niet te werken. Waarschijnlijk negeert het WizardControl deze eigenscap in de eigen Render methode. In plaats van de Visible eigenschap kan je de Style eigenschap gebruiken:
    [LinkButton].Style["display"] = "none";

De code behorende bij punt 1 (deze methode zoek recursief, binnen een container control, naar het control met het betreffence ID):

public static Control FindControl(string controlID, Control container) 
{
foreach (Control ctrl in container.Controls)
{
if (ctrl.ID != null && ctrl.ID.Equals(controlID))
return ctrl;
if (ctrl.HasControls())
{
Control c = FindControl(controlID, ctrl);
if (c != null) return c;
}
}
return null;
}

Een voorbeeld van het verbergen van de Next link op de eerste Wizard Step:

WebControl = FindControl("StartNextLinkButton", this.wizardControl1) as WebControl;
nextLink.Style["display"] = "none";

Bronnen: Microsoft MSDN

dinsdag 23 september 2008

Dynamic Data integreren in bestaande web applicatie

Één na de nieuwe features in Visual Studio 2008 SP1 is de Dynamic Data Web Application. Een heel handige feature die het mogelijk maakt om je databronnen middels een website te bekijken of te muteren.

Als je een nieuw project in Visual Studio 2008 aanmaakt bestaat de Dynamic Data Web Application uit één van de vele mogelijkheden die Visual Studio tegenwoordig biedt. Indien je deze keuze maakt wordt een complete web applicatie voor je gegenereerd en hoef je eigenlijk alleen maar een 'LINQ to SQL classes' diagram toe te voegen; de benodigde tabellen op het diagram te slepen en de gecreëerde DataContext toe te voegen aan de MetaModel instantie in global.asax.cs en je bent klaar.

Wat nu als je deze functionaliteit wilt integreren in een bestaande web applicatie?
Ik heb wat zitten vogelen met deze functionaliteit en heb deze zo aangepast dat het relatief eenvoudig is om te integreren in een bestaande web applicatie. Hiervoor moet je het volgende doen:
  1. Download dit zip bestand en importeer de folder uit de zip in je web applicatie. De zip bevat een 'LINQ to SQL classes' diagram welke als voorbeeld is toegevoegd. Deze kan gewoon verwijderd worden!
  2. Voeg de volgende references toe aan je project:
    System.Web.DynamicData
    System.Web.Routing
  3. Voeg een 'LINQ to SQL classes' diagram toe aan je project en sleep de benodigde tabellen op het diagram
  4. Registreer de DataContext, van bovenstaand diagram, middels de model.RegisterContext functie van de RegisterRoutes methode in de DynamicDataModule klasse
  5. Wijzig de DynamicDataApplicationName constante in de DynamicDataMaster klasse naar je eigen applicatienaam

    == Web.config aanpassingen ==
  6. Voeg in de sectie de volgende assemblies toe:
    <add assembly="System.Web.Abstractions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    <add assembly="System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    <add assembly="System.ComponentModel.DataAnnotations, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    <add assembly="System.Web.DynamicData, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
  7. Voeg in de / sectie de volgende tag prefix toe:
    <add tagPrefix="asp" namespace="System.Web.DynamicData" assembly="System.Web.DynamicData, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
  8. Activeer ASP.NET Routing
       IIS5/IIS6 : voeg de module toe aan de httpModules sectie:
    <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
       IIS7 - deel 1: voeg de module toe aan de / sectie:
    <remove name="UrlRoutingModule" />
    <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
       IIS7 - deel 2 : voeg de handler toe aan de / sectie:
    <add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
  9. Voeg de DynamicDataModule aan de modules sectie toe (wijzig [WebApplitionName] in de naam van je assembly):
    <add name="DynamicDataModule" type="DynamicDataModule, [WebApplitionName]"/>

Als je nu de pagina DynamicData\Default.aspx opstart zou de Dynamic Data feature moeten werken.

Succes ermee !!!

donderdag 4 september 2008

Google Chrome foutmelding "The application failed to initialize properly (0xc0000005)”

Ik heb net Google Chrome gedownload en geïnstalleerd. Helaas kreeg ik bij het opstarten meteen de volgende foutmelding: "The application failed to initialize properly (0xc0000005)”.

Er zijn twee mogelijke oplossingen voor dit probleem:
1. Pas de registry aan:
  • Start de registry editor door op Start \ Uitvoeren de klikken en regedit.exe gevolgd door ENTER in te toetsen.
  • Ga in de boomstructuur HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\SysPlant.
    Indien deze sleutel niet aanwezig is, dient deze aangemaakt te worden.
  • Open de 'Start' waarde of voeg deze toe (type is DWORD)
  • Wijzig de waardegegevens van de 'Start' waarde naar 4 om drivers uit te schakelen
  • Herstart de computer
2. Start Google Chrome met het "--no-sandbox" argument.
  • Klik met de rechter muisknop op de Google Chrome snelkoppeling
  • Voeg de tekst "–no-sandbox" (zonder de aanhalingstekens) toe aan het Doel veld.
In mijn geval werkte oplossing 1 al en was oplossing 2 niet meer noodzakelijk.

Mijn ervaringen met Google Chrome zijn tot nu toe erg goed. Ik heb nog nooit een webbrowser gehad die zo snel opstartte en zo snel naar een website surfte.

dinsdag 1 juli 2008

Één ItemTemplate voor Item en AlternatingItem in ASP.NET ListView control

In het ListView control in ASP.NET 3.x is het mogelijk om een ItemTemplate én een AlternatingItemTemplate te definiëren. Veelal wordt dit gebruikt om alleen maar een andere Style of CssClass te gebruiken voor het alternating item, zodat een mooier (subjectief natuurlijk ;-)) grid wordt gecreëerd.

In plaats van twee (bijna) identieke item templates te creëren is er een eenvoudigere oplossing mogelijk:
*** ASPX ***
<ItemTemplate>
   <tr class="<%# GetListItemCssName(Container) %>">
      <td>...</td>
   <tr>
</ItemTemplate>


*** CS ***
.protected string GetListItemCssName(object container)
{
   if (container is ListViewDataItem)
   {
      if (((ListViewDataItem)container).DisplayIndex % 2 == 0)
         return "Item";
      else
         return "AlternatingItem";
   }
   return null;
}

Zoals je ziet maak ik maar één template aan, nl. het ItemTemplate. Daar waar de variatie tussen een item en alternating item toegepast moet worden (in dit geval de class attribuut van de tabel regel) roep ik een methode in mijn code-behind aan.
De methode in de code-behind bepaalt aan de hand van de DisplayIndex of het om een even of oneven regel gaat en geeft de juiste class name terug.

dinsdag 3 juni 2008

Silverlight 2 diagrammen

Momenteel ben ik veel bezig met het ontwikkelen in Silverlight 2. Toevallig kwam ik onderstaande diagrammen tegen die wel erg handig zijn voor de beginnende Silverlight ontwikkelaar.



Download het originele bestand hier



Download het originele bestand hier


Bron:
Mike Taulty's Blog

vrijdag 9 mei 2008

PSV.tv op Windows Media Center

Als voetbalfan leek het me wel leuk op de beelden van PSV.tv, Ajax.tv, Feyenoord.tv, enz. via mijn Windows Media Center te kunnen bekijken. Ik dacht: zal ik daar een apart programma voor ontwikkelen of probeer ik gebruik te maken van wat er al is? Meestal probeer ik voor de 2e optie te gaan, wat nu ook het geval was.

Wat er al is: de Media Center RSS Reader van OABsoftware voor Windows XP en Vista. Deze software is gratis te gebruiken. Alleen moet het wel geactiveerd worden, wat je kan doen door je te registreren.

Wat moet ik dan nog ontwikkelen: een programmaatje om intelligent de HTML van deze TV sites te verwerken tot RSS feeds, waar deze software goed mee om kan gaan. En dit is gelukt... helaas niet voor Feyenoord.tv want daar moet je je aanmelden om de beelden te mogen bekijken.
Iedereen die gebruik wil maken van mijn RSS feeds kan deze vinden op:
- PSV.tv
- Ajax.tv

Als je nog meer ideeën hebt voor het verwerken van dit soort webpagina's tot RSS feeds, dan laat je maar een berichtje achter op deze blog.

donderdag 8 mei 2008

Active Directory benaderen in .Net 3.5

Microsoft heeft in het .Net framework versie 3.5 de assembly System.DirectoryServices.AccountManagement toegevoegd, welke mogelijkheden biedt om redelijk eenvoudig de Active Directory (of de accountdatabase (SAM) op een lokale PC) te benaderen en te wijzigingen. In deze blog richt ik me alleen op de Active Directory (AD).

Je maakt hierbij gebruik van de PrincipalContext klasse. Hieronder een voorbeeld hoe deze klasse te instanciëren:
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "MijnDomein");
Hierbij word een 'context' gecreëerd wat de basis is voor alle acties die in de AD uitgevoerd zullen gaan worden. Er wordt daardwerkelijk een verbinding met de directory ('MijnDomein') gemaakt.

Hierna kan je eenvoudig een User of Group ophalen en eventueel wijzigen. De basis klasse die hiervoor gebruikt wordt is de Principal klasse. Hieronder een voorbeeld hoe je een User of Group ophaalt:
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "Danny");
en
GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, "Administrators");
Met behulp van de Save methode kunnen wijzigingen op de principals doorgevoerd worden.

Een gebruiker kan ook gevalideerd worden (op bestaandheid én op correct wachtwoord). De ValidateCredentials(string userName, string password) methode van de PrincipalContext klasse kan hiervoor gebruikt worden.

Dankzij de PrincipalSearcher klasse en LINQ is het mogelijk ook relatief eenvoudig te zoeken naar Members (Users en Groups) in de Active Directory. In het voorbeeld hieronder wordt gezocht naar alle Users, welke de voornaam 'Danny' hebben:
//Creëer de context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "MijnDomein");

//Creëer een UserPrincipal om te gebruiken voor de Query
UserPrincipal u = new UserPrincipal(ctx);
//Zet de eigenschappen om naar te zoeken
u.GivenName = "Danny";

//Creëer de PrincipalSearcher om mee te zoeken
PrincipalSearcher ps = new PrincipalSearcher(u);
// Voer de Query uit
PrincipalSearchResult results = ps.FindAll();

De FindAll methode in de PrincipalSearcher klasse geeft een PrincipalSearchResult terug, welke de mogelijkheid biedt om met behulp van LINQ queries op het resultaat uit te voeren.

Ik heb zelf wat onderzoek gedaan naar de System.DirectoryServices.AccountManagement namespace, omdat ik een lijst met gebruikers op wil vragen uit een specifieke groep in de AD. De standaard methodieken hiervoor bieden helaas alleen de mogelijkheid om de gebruikers die in de groep zelf zitten te bepalen, maar niet om recursief (groepen in groepen) te zoeken naar de gebruikers. Hieronder de code die ik heb ontwikkelt, welke dit wel mogelijk maakt:
public static List GetGroupUsers(string domainName, string groupName, bool recursive)
{
//Creëer de context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domainName);
//Haal de AD Group op
using (GroupPrincipal groupPrincipal = GroupPrincipal.FindByIdentity(ctx, groupName))
{
//Loop door de Members om de Users te bepalen
List result = new List();
foreach (Principal principal in groupPrincipal.Members)
{
if (principal is UserPrincipal)
result.Add(principal);
}
//Loop door de Members om de Groups recursief te benaderen
if (recursive)
{
foreach (Principal principal in groupPrincipal.Members)
{
//Controleer of de member een Group is
if (principal is GroupPrincipal)
{
//Roep deze methode aan, zodat de recursie ontstaat
foreach (Principal p in GetGroupUsers(domainName, principal.Name, recursive))
{
//geen dubbele Users in de lijst
if (!result.Contains(p))
result.Add(p);
}
}
}
}
return result;
}
}




Bronnen:
Microsoft MSDN
Boeken:
The .NET Developer's Guide to Directory Services Programming