The URL ‚….. for Web project ‚….‘ is configured to use IIS Express as the web server but the URL is currently configured on the local IIS web server.

Die komplette Fehlermeldung die ich erhalten habe lautet wie folgt:

20110622 - IIS Express

Auch wenn dieser Fehler bei arbeiten an einem DotNetNuke Modul aufgetreten ist, kann dieser Fehler in jedem anderen Web Projekt unabhängig von DotNetNuke auftreten.

Was war geschehen.

Ich habe ein laufendes Projekt, von einem Windows 7 Rechner mit Visual Studio 2010 auf dem auch der IIS7 installiert ist, in ein Mercurial Repository gespeichert, und dann später auf einem zweiten Rechner geklont um auf diesem anderen Rechner einige Änderungen vornehmen zu können.

Nach dem Klonen des Projekts musste ich, da der Rechner auf dem ich den Klone erstellt habe, keinen IIS sondern nur den IIS Express installiert hat die Projekteigenchaften dahingehend ändern, dass das Projekt mit dem IIS Express funktioniert.
Was übrigens auch kein Problem war und einwandfrei funktioniert hat.

Bereits zu diesem Zeitpunkt hatte ich mir tatsächlich schon überlegt, ob es zu Problemen führen könnte, wenn ich das Projekt später wieder eingecheckt und dann auf dem ursprünglichen Rechner aktualisiere. Bin aber, da ich neben dem echten IIS auch den IIS Express auf dem ursprünglichen Rechner installiert habe zu der Überzeugung gekommen, dass es keine Probleme geben dürfte, was sich, wie man hier lesen kann nicht bewahrheitete.

Einige Wochen später, natürlich hatte ich mittlerweile vergessen, dass ich eine Umstellung von IIS auf IIS Express vorgenommen hatte, habe ich das Projekt aus dem Mercurial Repository auf dem ursprünglichen Rechner wieder ausgecheckt, bzw. eigentlich nur aktualisiert.

Und nachdem ich mit Visual Studio das Projekt geöffnet habe, kam es zu dem oben beschriebenen Fehler.

Mit der Fehlermeldung konnte ich erst überhaupt nichts anfangen. Dann fiel mir aber ein das ich ja diese IIS Express Änderungen an dem Projekt machen musste um es auf dem auf dem anderen Rechner zum laufen zu bekommen.

Das eigentliche Problem bei diesem Fehler ist, dass sich das Visual Studio Projekt nicht mehr öffnen lässt und daher auch keine Einstellungen geändert werden können. So dass man nicht einfach die Verwendung des IIS Express wieder ausschalten kann. (Ich hätte natürlich händig auch den IIS Express konfigurieren können, das hätte vermutlich auch geholfen)

Ich habe dann folgende Lösung entdeckt, und möchte diese für mich und gegebenenfalls auch für andere die ein solches Problem haben hier veröffentlichen, damit man,  wenn ein solches Problem wieder auftritt diese Lösung wieder finden kann und nicht wieder nach einer Lösung suchen muss.

So nun aber zur eigentlichen Lösung des Problems:

In der Konfigurationsdatei [Projektname].vbproj.user befindet sich unter der Region PropertyGroup folgende Einstellung:

<PropertyGroup>
       <UseIISExpress>true</UseIISExpress>
</PropertyGroup>

Diese Einstellung ändert man auf false, speichert die Datei, macht ein Reload der Projektdatei.

Und fertig.

Fehler BC30456: „Framework“ ist kein Member von „DotNetNuke.UI.Skins.Controls.DotNetNuke“

Nachdem ich mit der weiter unten beschriebenen Systemumgebung versucht habe die Source Version von DotNetNuke Version 5.6.2 zu installieren und zu übersetzen habe ich den nachfolgenden Fehler erhalten:

Fehler BC30456: „Framework“ ist kein Member von „DotNetNuke.UI.Skins.Controls.DotNetNuke“

Nachdem ich kurz versucht habe über Google eine Lösung zu finden und dort als Lösung einen Tipp vorgefunden habe der vorschlägt einfach nicht die Source Version zu verwenden, habe ich nur den Kopf geschüttelt und selbst nach einer Lösung gesucht.

Hier aber nun zur Lösung des Problems und zur verwendeten Systemumgebung:

  • Windows 7 Rechner
  • Visual Studio 2010 SP1
  • IIS Express (7.5)
  • DotNetNuke Version 5.6.2 Source Version (diese Version)

Nachdem ich also DNN 5.6.2 auf dem Rechner installiert habe und die Solution in Visual Studio unter IIS Express eingerichtet habe, wollte ich das Gesamte Projekt übersetzen.

Das ist aber mit dem oben beschriebenen Fehler gescheitert.

Um den Fehler zu beheben muss man folgende Änderung in der Datei: jQuery.ascx.vb welche im Unterordner amin/Skins des Website Root Verzeichnises zu finden ist, vornehmen.

Der Aufruf Im Page.Init Event muss wie folgt geändert werden.

Hier der Source des Originalevent

Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
	DotNetNuke.Framework.jQuery.RequestRegistration()
End Sub

Hier der geänderte Source, man beachte das Global vor dem Verweis auf DotNetNuke

Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Init
	Global.DotNetNuke.Framework.jQuery.RequestRegistration()
End Sub

Nach dieser Änderung kann man die Solution Fehlerfrei übersetzen.

Übrigens habe ich später doch noch einen Hinweis im Web gefunden, welcher die gleiche Lösung parat hält wie die hier von mir beschriebene.

Ich möchte daher an dieser Stelle auch auf diesen englischsprachigen Beitrag hinweisen.

Compilation error in dnn 5.6.2

Finalize – C#

Vorab möchte ich festhalten, dass ich in diesem Beitrag lediglich die Information darüber geben möchte wie man unter C# das äquivalent zur Finalize Methode in VB implementiert. Dies soll keine Diskussion über die Verwendung von Garbage Collection oder von Managed und Unmanaged Code werden.

Eventuell werde ich dazu mal in einem separaten Beitrag meinen Senf dazu abgeben, nun aber zum eigentlichen Thema dieses Beitrags:

Die Finalize Methode die es unter VB gibt ist unter C# der Destruktor.

Um einen Destruktor für eine Klasse unter C# zu implementieren muss man eine Methode mit der Tilde und dem Klassennamen erstellen.

Also zu Beispiel muss der Destruktor für eine Klasse MyClass wie folgt deklariert werden:

~MyClass()
{
//Hier alles rein was im Destruktor aufgerufen werden muss um alle Ressourcen des Objektes freizugeben
// Eigentlich sollte man aber wenn man einen Destruktor deklariert mindestens die IDisposable Schnittstelle
// in seiner Klasse implementiert haben und dann auch die Dispose Methode im Destruktor aufrufen, siehe hier
Dispose(false);
}

DotNetNuke 4.5.3 Core Hack – Und die Suche wird Deutsch

Nachdem ich mein eigenes Portal (das wo Ihr gerade drauf seid) auf die aktuelle Version 4.5.3 von DotNetNuke aktualisiert habe und mich auch ein wenig über den wesentlich besseren Editor FCK gefreut habe, wurde meine Freude aber doch schnell wieder getrübt.


Meine „alten“ Beiträge wurden in der Suche und im Modul WhatsNew einwandfrei mit den Umlauten angezeigt und auch die Suchfunktion hat bei den Umlauten wunderbar funktioniert. Meine neuen Beiträge aber wurden alle verstümmelt dargestellt (In der Suche und in der Anzeige des Moduls WhatsNew).


Was war geschehen?


Ich habe ein wenig in den Datenbanken recherchiert und stellte fest, dass der FTB Editor der in der 3er Version von DotNetNuke als Standard eingesetzt war, die Umlaute anders kodiert hat wie dies der FCK Editor macht. Das sollte generell eigentlich auch kein Problem sein, aber das Problem war nachdem ich soweit gekommen war relativ schnell gefunden.


Beim indizieren der Inhalte werden alle zu indizierenden Texte durch eine Funktion  mit dem Namen StripEntities geschickt um HTML Fragment die   und ähnliche Zeichen zu entfernen. Leider wird hierbei ein Regex Filter eingesetzt der auch Zeichen wie ö oder Ü aus dem Text entfernt. Und genau hier liegt das Problem, durch die Funktion StripEntities werden die in HTML kodierten Umlaute aus den Texten entfernt. Aber dies ist kein wirklich großes Problem, nachfolgend zeige ich wie die Funktion im Original aussieht und welche Änderung man machen muss, damit die Umlaute nicht herausgefiltert werden.


Hier der Original Code:

Public Shared Function StripEntities(ByVal HTML As String, ByVal RetainSpace As Boolean) As String
‚Set up Replacement String
   Dim RepString As String
   If RetainSpace Then
      RepString = “ „
   Else
      RepString = „“
   End If
   ‚Replace Entities by replacement String and return mofified string
   Return System.Text.RegularExpressions.Regex.Replace(HTML, „&[^;]*;“, RepString)
End Function

Und hier der Code nach der Änderung:

Public Shared Function StripEntities(ByVal HTML As String, ByVal RetainSpace As Boolean) As String
‚Set up Replacement String
   Dim RepString As String
   If RetainSpace Then
      RepString = “ „
   Else
      RepString = „“
   End If
   ‚Replace Entities by replacement String and return mofified string
   Return System.Text.RegularExpressions.Regex.Replace(HTML, „&[^uml;]*;“, RepString)
End Function

Und wer keine Lust hat diese Änderung selbst zu machen, kann auch einfach dem nachfogeldenden Link folgen und die DotNetNuke.DLL einfach herunterladen. Es handelt sich dabei um die Version 4.5.3. Einfach runterladen in das BIN Verzeichnis der DotNetNuke Installation kopieren und fertig.


Hier gibt es die kompilierte Version der DotNetNuke 4.5.3 DLL


Fast fertig, denn die „falschen“ Einträge sind bereits in der Datenbank vorhanden und müssen erst noch einmal erstellt werden..


Dies geht folgendermaßen:


Also als Host einloggen.


Im Menü Host den Menüpunkt SQL aufrufen und das folgende Script in das SQL Fenster kopieren.

———- START Script———–

delete SearchItem

go

delete SearchWord

go

delete SearchItemWord

go

delete SearchItemWordPosition

go

———END Script————-


run as script anklicken


und den Link ausführen betätigen.


Entweder kann man jetzt warten, bis der nächste Schedule Aufruf der Suchindex erstellung läuft, oder wenn man es eilig hat (wer hat das nicht) Im Host Menü den Menüpinkt Search Amdin aufrufen und Re-Index Content anklicken.


 


 

ASP.NET Redirect – Aber bitte Suchmaschinenfreundlich

Wenn Sie die URL zu Ihrer Webseite ändern müssen, sollten Sie bereits vorher die richtigen Maßnahmen ergreifen, dass ein Internet Surfer der auf diese Seite zugreifen möchte nicht den häßlichen Fehler 404 (Datei nicht gefunden) angezeigt bekommt.

Eine durchaus übliche Lösung hierfür ist es ein meta refresh hierfür zu verwenden.

Auf der URL eines Seite anzulegen welche als einzigen Inhalt den nachfolgenden meta refresh enthält.

meta http-equiv="refresh" content="0; URL=http://www.Domain.de/" />

Der oben dargestellte meta refresh leitet ohne Zeitverzögerung den Internet Surfer auf die im Parameter URL stehende neue Webseite um.

So weit so Gut, aber !!

Es gibt 3 Gründe warum man dies nicht machen sollte:
  1. Sie werden diese Umleitung ewig bestehen lassen müssen, da der Internet Surfer nie wirklich etwas von Ihrer neuen Internetseite erfährt.
  2. Suchmaschinen bewerten solche Umleitungen häufig als SPAM und streichen wenn Sie Pech haben, all Ihre Seiten aus Ihrer Datenbank.
  3. Das Thema Ranking spielt hier eine Rolle. Ich Denke jeder kennt das PageRank von Google. Also nehmen wir einmal an Sie hatten auf der alten URL einen PR von 5, im besten Fall akzeptiert die Suchmaschine Ihre Umleitung und behält Ihren Eintrag in Ihrer Datenbank. Das Ranking der Seite liegt aber weiterhin auf der alten URL und wird nicht zu einem eventuelle Ranking der neuen Seite hinzugezogen.

Was geschieht bei einem Redirect egal ob über meta-equiv oder über Source Code „Context.Response.Redirect“.

Die Seite wird umgeleitet und im Response Header wird ein Status Code 302 zurückgeben.

Dieser Status kommt sagt aus das die URL gefunden wurde. Gefunden bedeutet aber, Sie musste gesucht werden, nicht Gut !!

Wenn ein URL Zugriff einwandfrei verläuft dann sollte ein Status Code 200 zurückgegeben werden.

So jetzt haben wir was von Status 200 und 302 gehört, aber wie können wir es erreichen dass wir durch unseren Redirect die Suchmaschinen nicht böße machen und dass die neue URL als Quelle der Information im Internet bekannt wird.

Die Lösung heißt: Permanente Weiterleitung.

Eine Permanente Weiterleitung ist im ersten Moment auch nur ein Redirect, aber der zurückgegeben Status Code ist 301 (URL wurde verschoben). Diese Information nutzen die meisten Suchmaschinen um Ihre Einträge auf die neue URL in Ihren Datenbanken zu aktualisieren. Das hat den Vorteil. dass nach einige Zeit die Informationen über die neue URL direkt in den Suchmaschinen zur Verfügung stehen, und ganz wichtig, das auf der alten liegende PageRank wird auf die neue URL übernommen.

Wie kann ich jetzt eine Permanente Umleitung erstellen:

Mit einem meta-equiv leider nicht (nicht in ASP.NET)

Aber für was haben wir denn ein intelligentes Framework auf dem unser Web läuft.

Zu diesem Zweck erstellen wir einfach eine ASPX Seite die dem alten URL Namen entspricht.

In diese ASPX Datei schreiben wir folgenden Inline Code:

    <%@ Page Language="vb" AutoEventWireup="false"%>
    <SCRIPT runat="server">
    Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Context.Response.Status = "301 Moved Permanently"
    Context.Response.AddHeader("Location", "<http://www.schelian.de/Default.aspx/tabid/189>")
    End Sub
    </SCRIPT>

Wenn Sie nun die Datei auf dem Server gespeichert haben wird eine permanente Suchmaschinenfreundliche Umleitung vorgenommen.

Hier ein Beispiel http://www.schelian.de/MindManager.aspx

Dieser Link wird auf den URL http://www.schelian.de/default.aspx/tabid/155 umgeleitet.

Und nun viel Spaß beim suchmaschinenfreundlichen Umleiten von Seiten!

DNN User Controls Programmierung VB versus C#

Bei der Programmierung von DotNetNuke Modulen gibt es ja wie allseits bekannt die freie Wahl der .NET Programmiersprachen.

Die beiden beliebtesten Sprachen zur Programmierung von DotNetNuke Modulen sind wohl VB.NET und C#.

Bei der Programmierung von User Controls sind jedoch obwohl beides .NET Programmiersprachen sind die Sprachspezifischen Eigenschaften wie zum Beispiel der Unterschied zwischen Groß und Kleinschreibung bei C# im Gegensatz zu VB.NET zu berücksichtigen. Das dies aber nicht die einzigen Unterschiede sind wird spätestens dann ganz deutlich wenn man versucht ein in VB.NET erstelltes User Control als Vorlage für ein C# User Control zu verwenden.

Schauen wir uns das doch einmal am Beispiel des Moduls Event, das ja Bestandteil des Core Produktes DotNetNuke ist, einmal etwas näher an.

Hier der Auszug aus der Events.ascx (mit VB.NET Codebehind)

<TR>

<TD id=colIcon vAlign=top align=center width='<%# DataBinder.Eval(Container.DataItem,"MaxWidth") %>' rowSpan=3 runat="server">

<asp:Image id=imgIcon runat="server" Visible='<%# FormatImage(DataBinder.Eval(Container.DataItem,"IconFile")) <> "" %>'

ImageUrl='<%# FormatImage(DataBinder.Eval(Container.DataItem,"IconFile")) %>' AlternateText='<%# DataBinder.Eval(Container.DataItem,"AltText") %>'>

</asp:Image></TD>

<TD>

<asp:HyperLink id=editLink runat="server" Visible="<%# IsEditable %>" NavigateUrl='<%# EditURL("ItemID",DataBinder.Eval(Container.DataItem,"ItemID")) %>'>

<asp:Image id="editLinkImage" ImageUrl="~/images/edit.gif" Visible="<%# IsEditable %>" AlternateText="Edit" runat="server" resourcekey="Edit"/>

</asp:HyperLink>

<asp:Label id=lblTitle text='<%# DataBinder.Eval(Container.DataItem,"Title") %>' Cssclass="SubHead" Runat="server">

</asp:Label></TD>

</TR>

Unsere besondere Aufmerksamkeit müssen wir dabei vor allem auf die Funktionen DataBinder.Eval() und EditURL() lenken.

Schauen wir uns Diese Syntax am folgenden Beispiel etwas näher an:

Visible='<%# FormatImage(DataBinder.Eval(Container.DataItem,"IconFile")) <> "" %>'

Mit dieser Zeile wird (in VB.NET ) erreicht dass nur wenn ein IconFile vorhanden ist das Control sichtbar ist, sonst wird der Wert Visible auf false gesetzt

Wenn wir eine solche Zeile in einem User Control einsetzen, welches mit C# zusammenarbeiten soll, dann ergeben sich gleich mehrere Problem (Fehlermeldungen während der Programmausführung, nicht beim übersetzen)

Als erstes wird in C# der Ausdruck nicht als If Ausdruck ausgewertet, da er nicht in () eingeschlossen ist.

Also muss das ganze auf jeden Fall schon mal so aussehen:

Visible='<%# (FormatImage(DataBinder.Eval(Container.DataItem,"IconFile")) <> "") %>'

Zu beachten hierbei sind die Klammern am Anfang und Ende der Auswertung

(FormatImage(DataBinder.Eval(Container.DataItem,"IconFile")) <> "")

Jetzt würden aber noch immer Laufzeitfehler entstehen, da C# bei der Typ Auswertung wesentlich kleinlicher (Gott sei Dank) ist, als dies VB.NET ist.

Das nächste Problem liegt in der Behandlung eines Stringvergleiches. in VB.NET ist der Vergleich string1 <> string2 ein gültiger Vergleich. In C# nicht, also müssen wir einen gültigen Vergleich für C# nehmen, der sieht dann so aus: string1 != string2.

Danach muss unser Ausdruck wie folgt aussehen:

Visible='<%# (FormatImage(DataBinder.Eval(Container.DataItem,"IconFile")) !="") %>'

Wenn Sie nun Denken, dass es nun funktioniert, muss ich Sie leider enttäuschen.

DataBinder.Eval() gibt als Datentyp ein abstraktes Objekt zurück, nun versuchen Sie mal einen Vergleich eines Objekt Datentyps mit „“ einem String, das wird C# nicht zulassen.

Also bleibt uns nichts weiter übrig, als das Objekt zu einem String umzuwandeln.

Die Umwandlung können wir wie folgt vornehmen:

DataBinder.Eval(Container.DataItem,"IconFile").ToString()

Somit sieht unser Ausdruck nun wie folgt aus:

Visible='<%# (FormatImage(DataBinder.Eval(Container.DataItem,"IconFile").ToString()) !="") %>'

Der nun hier dargestellte Ausdruck ist nun C# konform und wird keinen Laufzeitfehler mehr erzeugen.

Schauen wir uns nun noch ein zweites Problem unseres Beispiels an:

<asp:HyperLink id=editLink runat="server" Visible="<%# IsEditable %>" NavigateUrl='<%# EditURL("ItemID",DataBinder.Eval(Container.DataItem,"ItemID")) %>'>

Der hier dargestellte Ausdruck ist der typische Code für den Hyperlink, der aus dem Anzeige Control das Edit Control aufruft.

Der nicht C# konforme Teil dieses Ausdrucks ist nachfolgend dargestellt:

NavigateUrl='<%# EditURL("ItemID",DataBinder.Eval(Container.DataItem,"ItemID")) %>'

Wenn wir das bisherige aus diesem Artikel anwenden, dann wissen wir dass wir das aus dem DataBinder.Eval() zurückgegeben Objekt in einem String umwandeln müssen.

So das unser Ausdruck wie folgt aussieht:

NavigateUrl='<%# EditURL("ItemID",DataBinder.Eval(Container.DataItem,"ItemID").ToString()) %>'

Wie ich am Anfang schon bemerkt habe berücksichtigt C# im Gegenteil zu VB.NET die Groß und Kleinschreibung, und somit haben wir mit dem Aufruf der Funktion EditURL ein Problem, da diese in Wirklichkeit eigentlich EditUrl heißt.

Also ändern wir den Ausdruck wie folgt ab:

NavigateUrl='<%# EditUrl("ItemID",DataBinder.Eval(Container.DataItem,"ItemID").ToString()) %>'

Mit dem Wissen dieser notwendigen Änderungen wenn Sie ein User Control in C# verwenden möchten, was eigentlich für VB.NET konzipiert war, können Sie nun die notwendigen Änderungen in User Controls vornehmen so dass diese dann in einem C# DotNetNuke Module verwendet werden können.