BlogEngine.NET – VS2010 – Master Page error beim öffnen der default.aspx

Beim Versuch die Datei default.aspx im Design Mode aus Visual Studio 2010 heraus zu öffnen wurde die folgendende Fehlermeldung ausgegeben:

Dieses ist nicht unbedingt ein BlogEngine spezifisches Problem und kann auch mit anderen Projekten auftreten.

Das Problem tritt auf, da in der verwendeten Basisklasse „BlogBasePage“ die Methode  OnPreInit vom PreInit Event aufgerufen wird. In dieser Methode wird eine Masterpage benötigt, da diese dort an die Basisklasse.MasterPageFile zugewiesen wird.

Siehe nachfolgenden Code Auszug:

this.MasterPageFile = string.Format("{0}themes/{1}/site.master", Utils.RelativeWebRoot, this.theme);

Nun gibt es die Möglichkeit direkt in der web.config eine default masterpage anzugeben, und genau dies ist auch die Lösung unseres Problems:

Der Eintrag muss wird in der Region „pages“ der web.config vorgenommen.
Dieser Bereich der web.config sieht vor der Änderung wie folgt aus:

<pages
	enableSessionState="false"
	enableViewStateMac="true"
	enableEventValidation="true"
>

Nun gibt es die Möglichkeit über den Parameter masterPageFile in der web.config eine default Master Page anzugeben, und genau dies machen wir, indem wir den Eintrag in der web.config, wie folgt ändern:

<pages
	enableSessionState="false"
	enableViewStateMac="true"
	enableEventValidation="true"
	masterPageFile="~/themes/Standard/site.master"
>

Man beachte den neuen Parameter

masterPageFile=“~/themes/Standard/site.master“

Dieser setzt die Master Page aus dem Standard Theme als Default Master Page, welche dann in der Basisklasse BlogBasePage verwendet werden kann, so dass der hier beschriebene Fehler nicht mehr auftritt.

Man kann natürlich auch jede andere Master Page aus jedem beliebigen Theme verwenden. Am besten verwendet man die Master Page aus dem verwendeten Theme.

Und nachdem diese Einstellung in der web.config vorgenommen wurde, kann man die default.aspx ohne den hier beschriebenen Fehler öffnen.

DotNetNuke – Dateimanager Ordner Baumansicht wird nicht geöffnet

Auf einem DNN Portal das unter DotNetNuke Version 5.6.2 betrieben wird, kommt es plötzlich zu dem Problem, dass beim Klicken auf das Pluszeichen des Dateimanagers, die Unterordner nicht mehr angezeigt werden.

Die nachfolgende Abbildung zeigt dieses Phänomen:

Es sieht so aus, als ob endlos versucht wird die Verzeichnisstruktur zu lesen und darzustellen. Doch dies wird, wenn es erst einmal zu diesem Verhalten gekommen ist, nicht mehr geschehen, auch wenn man noch so geduldig ist.

Ich habe diese Verhalten auf verschiedenen Systemen gesehen und in einigen Fällen kommt es noch zur Ausgabe einer Fehlermeldung ähnlich der nachfolgenden:

„Laufzeitfehler in Microsoft JScript: Sys.ArgumentException: Cannot deserialize empty string. Parameter name: data“

In anderen Fällen, je nach Umgebung, eingesetztem Browser und Browsereinstellungen kann es aber auch vorkommen, dass keine Fehlermeldung ausgegeben wird.

Also nicht darauf verlassen, dass eine Fehlermeldung ausgeben wird.

Und unbedingt beachten: Dieser Fehler verursacht auf keinem mir bekannten Fall einen Eintrag im DNN Ereignisprotokoll.  Da es sich bei diesem Problem um ein Clientseitiges JavaScript Problem handelt, kann DNN von diesem Fehler nichts mitbekommen und dementsprechend auch keine Eintrag in das Ereignisprotokoll vornehmen.

Wenn dieses Problem auftritt, sollte man unter den Systemeinstellungen in den Erweiterten Einstellungen die Einstellungen der Leistungsoptimierung im Bereich kontrollieren,

Wenn dort als Kompressionseinstellungen „GZip-Kompression“ eingestellt ist, dann sollte diese Einstellung dahingehend geändert werden, dass „unkomprimiert“ ausgewählt ist.

Nun noch die Einstellung speichern und ich bin mir ziemlich sicher, dass der Dateimanager nun wieder funktioniert.

Übrigens scheint dieses kein neues Problem in der Version 5.6.2 zu sein, sondern schon in älteren Versionen vorzukommen.

Also wenn ein solches Problem mit einer älteren Version auftritt, auf jeden Fall die Einstellungen prüfen und gegebenenfalls ändern.

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

WordPress – geplante Artikel werden nicht veröffentlicht

Dieses Thema scheint eines der ewigen Themen in WordPress zu sein.

Egal ob mit Bing gegoogelt oder mit Google gebingt, es werden für fast alle WP Versionen Artikel gefunden die über das Problem berichten, dass geplante Artikel nicht veröffentlicht werden und man auch nicht einfach diese geplanten Artikel nachträglich manuell veröffentlichen kann.

Ich hatte dieses Problem aktuell mit der WordPress Version 3.1.2.

Schnelle Abhilfe hat mir hier aber ein Plugin mit dem Namen WP Missed Schedule gebracht.

Einfach das Plugin über WP installieren und fertig.

Das Plugin kümmert sich dann darum, das nicht korrekt veröffentlichte Artikel doch veröffentlicht werden.

Besten Dank für das tolle Plugin

DotNetNuke – PortalSecurity.HasEditPermissions – Obsolete

In der Serie Clean Code meiner DotNetNuke Module geht es Heute um die Methode PortalSecurity.HasEditPermissions().

Ebenfalls seit der DotNetNuke Version 5.0 ist die Methode HasEditPermissions() aus dem Namespace DotNetNuke.Security.PortalSecurity nicht mehr zu verwenden.

Die beschriebene Methode wird dazu verwendet, zu ermitteln ob der angemeldete Benutzer die Rechte zur Bearbeitung für ein bestimmtes Modul besitzt.

Ein Aufruf, der bis zur Version 5.0 wie folgt ausgesehen hat:


if (PortalSecurity.HasEditPermissions(ModuleId, TabId))

sollte nun durch den nachfolgenden Aufruf ersetzt werden.


if(ModulePermissionController.HasModuleAccess(
SecurityAccessLevel.Edit,
"EDIT",
this.ModuleConfiguration))

Mehr folgt in Kürze

DotNetNuke.Entities.Portals.PortalSettings.GetHostSettings() – Obsolete

Auf der Suche nach dem Clean Code meiner DotNetNuke Module werde ich in den nächsten Tagen über einige kleine Migrationsschritte berichten.

Beginnen werde ich in diesem Sinne mit der Ersetzung der bereits seit DotNetNuke Version 5.0 obsoleten Methode GetHostSettings aus dem Namespace DotNetNuke,Entities,Portals.PortalSettings.

Hier ein Code Auszug aus einem DNN Modul, welcher bis zur DotNetNuke Version 5.0 Verwendung so oder ähnlich eingesetzt wurde.

Der Code dient dazu, die in einem Portal erlaubten Dateiendungen zu ermitteln. Oder mit anderen Parametern einfach eine Einstellung auf Host Ebene auszulesen

string fileExtensions = DotNetNuke.Entities.Portals.PortalSettings.GetHostSettings()["FileExtensions"].ToString().ToLower();

Für die obsolete Methode kann man nun folgende beiden Varianten verwenden:


string fileExtensions = HostController.Instance.GetSettingsDictionary()["FileExtensions"].ToString().ToLower();

oder diese variante


string fileExtensions = HostController.Instance.GetString("FileExtensions").ToLower();

Ich persönlich finde die Variante mit GetString() in diesem Fall die angebrachtere.

SQL View – Manchmal darf’s nicht null sein !

In einer SQL View soll eine Spalte als (int, NULL) ausgegeben werden, die in der zugrundeliegenden Tabelle als Spaltentyp (int, Not NULL) definiert ist.

Hintergrund dieser Forderung ist, das die View als Datasource für ein recht aufwendig zu formatierendes DataGridView dient und bei der Formatierung dieser Spalte nicht als (not null) definiert sein darf.

Mit einem einfachen Cast direkt in der View ist diese Anforderung sehr einfach umzusetzen. (siehe nachfolgenden Code Abschnitt)

SELECT CAST(dbo.MyTable.ID AS int) AS MyID, .....

FROM MyTable

Enum als Datasource für DataGridViewComboBoxColumn im DataGridView verwenden

Vor längerer Zeit habe ich in diesem Artikel berichtet wie man enum Werte über die DataSource Eigenschaft an eine Combobox binden kann.

Hier eine Darstellung einer solchen Bindung in einer normalen Windows Form:

Will man nun aber enum Werte in einem DataGridview an eine, als Combobox definierte, Spalte (DataGridViewComboBoxColumn) binden, geht das nicht ganz so einfach, und eben nicht so wie es in meinem oben erwähnten Artikel beschrieben ist.

Das Ergebnis soll so aussehen:

Wer schon einmal eine solche Tabelle programmiert hat, weiß, dass man nachdem man die DataSource Eigenschaft der DataGridViewComboBoxColumn zugewiesen hat, noch den ValueMember und den DisplayMember angeben muss (Siehe nachfolgende Abbildung).

Da wir die DataSource Eigenschaft bei der enum Variante über den Source Code zuweisen (es geht auch anders, dazu evtl. zu einem späteren Zeitpunkt mal mehr), müssen wir natürlich auch die beiden Eigenschaften  DisplayMember und ValueMember aus dem Quellcode heraus zuweisen.

Nur wie heißen die denn ?

Und genau hier liegt das Problem, bzw. die hier beschriebene Lösung.

Diese Eigenschaften gibt es bei der ursprünglich von mir beschriebenen Lösung nicht.

Und daher müssen wir uns solche Eigenschaften bilden. Hierzu verwenden ich eine Helper Klasse die das notwendige implementiert. (Siehe nachfolgenden Source Code)

Hier nun der Code der Klassen

[Serializable]
public class EnumHelper
{
	public int Key { get; set; }
	public string Value { get; set; }

	public static IEnumerable<ValueListItem> CreateDataSourceFromEnum(Type t)
	{
		var list = new List<ValueListItem>();

		Array aEnum = Enum.GetValues(t);
		foreach (var array in aEnum)
		{
			var vi = new ValueListItem
						 {
							 Key = (int) array,
							 Value = array.ToString()
						 };

			list.Add(vi);
		}
		return list;
	}

	public static IEnumerable<EnumHelper> DataSourceFromEnum(Type t)
	{
		var list = new List<EnumHelper>();

		Array aEnum = Enum.GetValues(t);
		foreach (var array in aEnum)
		{
			var vi = new EnumHelper
						 {
							 Key = (int) array,
							 Value = array.ToString()
						 };

			list.Add(vi);
		}
		return list;
	}

}

[Serializable]
public class ValueListItem
{
	public int Key { get; set; }
	public string Value { get; set; }
}

Und so kann man die Helper Klasse verwenden um die DataSource Eigenschaft sowie die ValueMember und DisplayMember Eigenschaften zuzuweisen.

private void InitDgv()
{
	bereichDataGridViewTextBoxColumn.DataSource = EnumHelper.DataSourceFromEnum(typeof(EntladungsTyp));
	bereichDataGridViewTextBoxColumn.DisplayMember = "Value";
	bereichDataGridViewTextBoxColumn.ValueMember = "Key";
}

Wichtiger Hinweis

Ich verwende diese Klasse bereits seit mehreren Jahren und weiß nicht mehr genau ob ich von irgend jemand etwas übernommen und überarbeitet habe, oder ob ich das im stillen Kämmerchen ausgebrütet habe.
Eine kurze Recherche im Internet hat keine direkten Ergebnisse / Quellen hervorgebracht. Es gibt zwar einige Beiträge die sich auch mit enum Helper Klassen beschäftigen, aber die, welche ich gerade gesehen habe, beschäftigen sich nicht genau mit dem von mir hier beschriebenen Thema, so dass ich zur Zeit keine Angaben über eventuelle Quellen, die mich inspiriert haben könnten, machen kann.

Aber wenn jemand erkennt dass ich Code von wem auch immer verwendet habe, hinterlasst dass bitte in einem Kommentar, so dass sich eventuell fehlende Quellnachweise schließen.

C# -Die Auflistung wurde geändert – Der Enumerationsvorgang kann möglicherweise nicht ausgeführt werden

Eine Meldung ähnlich wie die Überschrift kann man ganz leicht erhalten, wenn man mit Auflistungen in einer Anwendung arbeitet, welche mehrere Threads verwendet und ein Thread lesend und ein anderer schreiben auf die Auflistung zugreift.

Nun ist es so, dass es zu diesem Thema eine ganze Reihe, von mehr oder weniger, guten Ansätzen im Internet zu finden ist (Natürlich überwiegend gute 🙂 ). Wobei eine der entscheidenden Aussagen ist, dass man diese Fehlermeldungen, dann erhält wenn man mit einer Enumeration (foreach Schleife) über die Auflistung geht und dabei neue Elemente der Auflistung hinzufügen oder Elemente löschen möchte.

Also zum Beispiel wie in der folgenden Klasse:

public class AppointmentList : List<Appointment>
{
	public void DeleteAppointmentsForDate(DateTime dt)
	{
		foreach (Appointment appointment in this)
		{
			if (appointment.StartDate.Date == dt.Date)
			{
				Remove(appointment);
			}
		}
	}
}

Eigentlich soll, die Methode der Klasse alle Appointments eines bestimmten Datums aus der Auflistung löschen.
Das mach sie auch, und zwar dann, wenn alles in einem Thread abläuft.

Aber nur dann.

Nun wird bei den meisten Lösungen im Internet vorgeschlagen anstelle der Iteration mit foreach einfach eine for Schleife zu verwenden.

Das würde dann so aussehen
(Ich möchte aber gleich hier sagen, dass diese Lösung für das Löschen auch nicht eingesetzt werden kann, da diese egal ob mit oder ohne mehreren Threads nicht richtig arbeitet).

public class AppointmentList : List<Appointment>
{
		for (int i = 0; i < this.Count; i++)
		{
			if (this[i].StartDate.Date == dt.Date)
			{
				this.RemoveAt(i);
			}
		}
	}
}

Und warum geht das nicht ?

Nehmen wir der Einfachheit halber mal an die Auflistung würde 4 Einträge enthalten und alle 4 würden das gleiche Startdatum haben, was bedeuten würde, dass alle 4 Listen Elemente gelöscht werden müssten.

Runde 1:
i == 0 und this.count== 3
Element an Index 0 wird gelöscht
Element mit Index 1 wird nun an Index Position 0 geführt
Element mit Index 2 wird nun an Index Position 1 geführt
Element mit Index 3 wird nun an Index Position 2 geführt
this.count ist nun nur noch 2

Runde 2:
i == 1 und this.count == 2
….

Eigentlich brauche ich gar nicht mehr weiter erläutern, jetzt ist klar, dass das löschen mit der for schleife mit erhöhendem Index (i++) nicht funktionieren kann, wenigstens nicht wenn es um das Löschen von List Elementen geht.

Aber natürlich gibt es auch dafür eine einfache Lösung, und diese sieht so aus:

public class AppointmentList : List<Appointment>
{
	public void DeleteAppointmentsForDate(DateTime dt)
	{
            for (int i = this.Count - 1; i >= 0; i--)
            {
                if (this[i].StartDate.Date == dt.Date)
                {
                    this.RemoveAt(i);
                }
            }
		}
	}
}

Genau, wir verwenden einfach eine for schleife mit einem herabzählendem Index (i–).
Dies funktioniert auch mit mehreren Threads.

C# – Dauer in Minuten aus Start und Ende Zeit ermitteln

Und wieder mal geht es um Zeitberechnung in C#.

Aufgabenstellung:
Wir haben 2 Datumswerte mit Zeitangabe. Nenne wir den ersten den Starttermin und den zweiten den Endetermin.
Aus diesen beiden Werten wollen wir nun die Dauer des Termins in Minuten ermitteln.

Und hier die Lösung:

DateTime _dtStart = DateTime.Now;
DateTime _dtEnde = _dtStart.AddHours(1); // Zum Test 1 Stunde addieren, das macht dann  60 Minuten Dauer

int dauer = (int) (_dtEnde - _dtStart).TotalMinutes;

Übrigens geht das natürlich auch wenn man anstelle einer DateTime Variable einen bzw. zwei DateTimePicker Werte verwenden möchte mann muss dann lediglich die Eigenschaft Value des DateTimePicker verwenden, also so:

            DateTimePicker dtpStart = new DateTimePicker();
            DateTimePicker dtpEnde = new DateTimePicker();
            dtpStart.Value = DateTime.Now;
            dtpEnde.Value = dtStart.Value.AddHours(1);

            int dauer = (int)(dtpEnde.Value-dtpStart.Value).TotalMinutes;