Reportviewer: The report definition is not valid. Details: Data at the root level is invalid. Line 1, position 1.

20. Januar 2010

Nach dem Deployen (Web Deployment Project) von lokalen rdlc Reports aus Visual Studio 2008 heraus, gab es auf dem IIS folgenden Fehler:

[ReportProcessingException: The report definition is not valid.  
Details: Data at the root level is invalid. Line 1, position 1.]

[DefinitionInvalidException: The definition of the report
'Main Report' is invalid.]

 

Das Problem ist, dass die Reports vorkompliliert werden, was leider kontraproduktiv ist. Durch ergänzen der csproj Datei für das Deploy kann der Fehler umgangen werden:

<Target Name="AfterBuild">
  <Delete Files="$(OutputPath)\Reports\Report.rdlc" />
  <Copy SourceFiles="$(SolutionDir)WebSites\MyWebApp\Reports\Report.rdlc" 
        DestinationFolder="$(OutputPath)\Reports" />
< /Target>

 

.NET, ASP.NET

ASP.NET Performance von Visual Studio steigern

16. April 2009

Visual Studio verlangt nach schnellen Festplatten. Je schneller, desto besser. Nichts ist allerdings so schnell wie eine RamDisk. Wer glaubt, dass die RamDisk eine Sache aus der alten DOS-Zeit ist, der irrt. Speicher ist billig und 64 Bit Betriebssysteme sind auch schon fast Mainstream (na ja, noch nicht so ganz).

Was liegt also näher, die brach liegenden Megabytes des RAMs als RamDisk zu nutzen. Unter Vista x64 nutze ich die RAMdrive von QSoft, welche sich recht komfortabel über den Gerätemanager einstellen lässt. Zur Zeit nutze ich 1GB als Laufwerksgröße.

Damit nun ASP.NET Projekte diese RamDisk nutzen können, muß in der machine.config das tempDirectory angepasst werden:

<compilation tempDirectory="R:\Temp\aspnet"/>


Details zu diesem Eintrag findet sich bei MSDN.

Weiterhin lassen sich auch das Cache-Verzeichnis vom FireFox oder IE auf die RamDisk legen, um die Performance zu steigern.

.NET, ASP.NET

Page Events feuern nicht

24. September 2007

Wieder mal ein Fehler der Kategorie: Aua!

Auf einer ASP.NET Seite sitzt ein Button und nach der Umstellung der Anwendung von .NET 1.1 auf .NET 2.0 feuern die Events der Seite nicht mehr... nach ziemlich langem herumprobieren stellte sich die folgende Zeile im Header als Übeltäter heraus:


<script language="javascript" src="JavaScript/General.js"
type="text/javascript"/>
Nach Umstellen auf


<script language="javascript" src="JavaScript/General.js"
type="text/javascript"></script>

feuerten auch wieder die Events!

Ich bin eigentlich ein Freund der kurzen Schreibweise der Tags, doch hier scheint mehr mal wieder mehr zu sein...

 

ASP.NET

Kommunikation mit UserControls über eine MasterPage in ASP.NET

4. April 2007
Die in ASP.NET 2.0 eingeführte MasterPage erfreut sich zunehmender Beliebtheit. Denn mittels dieser lassen sich Elemente, die auf allen Seiten einer Anwendung gleich sein sollen, einmalig erstellen und verwenden. Damit ist die MasterPage ein Pflichtelement für jede ASP.NET Webanwendung.
Nun stellt sich aber die Frage, wie Controls, die in der MasterPage liegen mit anderen Controls bzw. UserControls auf der jeweiligen Seite (bzw. im ContentPlaceHolder) kommunizieren sollen? Die MasterPage weiss ja noch gar nicht, welche Controls in der Seite enthalten sind. Eine mögliche Lösung möchte ich hier skizzieren:
Bei diesem Beispiel enthält die MasterPage einen Button und eine TextBox. Sobald auf den Button geklickt wird, soll der Text an die UserControls geschickt werden, die sich für diesen Text interessieren. Das Interesse an einem Text lässt sich recht gut über ein Interface definieren:

public interface ITextConsumer
{
    void HandleTextEvent(object sender, TextEventArgs e);
}


Die Nutzinformation, also der Text wird mittels eines Event Arguments übermittelt:

public class TextEventArgs : EventArgs
{
    private string text;

    public string Text
    {
        get { return text; }
        set { text = value; }
    }
}


Die UserControls, die sich nun für den Text interessieren müssen einfach das Interface ITextCosumer implementieren:

public partial class WebControls_DataControl : System.Web.UI.UserControl, ITextConsumer
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }

    #region ITextConsumer Member
    public void HandleTextEvent(object sender, TextEventArgs e)
    {
        ' Process the Text. E.g. search in the database etc.
    }
    #endregion
}


In der MasterPage muss nun im Click Ereignis des Buttons die Controls Collections des ContentPlaceHolders durchlaufen werden. Dabei wird jedes Controls auf das Interface ITextCosnumer gecastet. Klappt der Cast, wird der Text über die im Interface definierten Methode übermittelt.

protected void Button1_Click(object sender, EventArgs e)
{
    TextEventArgs text = new TextEventArgs();
    text.Text = this.TextBox1.Text;
       
    foreach (Control cntl in this.ContentPlaceHolder1.Controls)
    {
        ITextConsumer eventConsumer = cntl as ITextConsumer;
        if (eventConsumer != null)
        {
            eventConsumer.HandleTextEvent(this.Page, text);
        }
    }
}


Das war's! Diese Lösung funktionert recht gut mit direkt in den Seiten implementierten UserControls. Enthalten die UserControls selbst noch weitere Controls, die sich für den Text interessieren, muss diese Information evtl. weitergereicht werden (hier auch wieder die Controls Collection durchlaufen).


Development, .NET, ASP.NET

Howto debug Javascript in Visual Studio

13. März 2007

In Zeiten, in denen immer mehr Javascript in ASP.NET Webanwendungen Einzug hält, ist das Debuggen von Javascript unumgänglich. Mit folgenden Handgriffen wird das Debuggen in Visual Studio ermöglicht:

1. JavaScript Debugging im Internet Explorer einschalten (durch deaktivieren der Skriptdebuggingeinträge):


2. Im Javascript Code die Zeile

debugger;

hinzufügen. Das Debugging wird dann genau an dieser Stelle bei in Visual Studio gestarteten Anwendungen aktiviert.

 

ASP.NET, Development

Lokalisierung in ASP.NET 2.0

15. Februar 2007
Die Lokalisierungsmöglichkeiten von ASP.NET 2.0 sind schon recht cool, aber immer wieder muss ich nach der genauen Schreibweise zur Verwendung von Resourcedateien in aspx oder ascx Seiten bei Goolge forschen. Daher

<%$ Resources:Resource,TextInResourceDatei %>

Hierbei wird die Resource TextInResourceDatei aus dem Resourcefile Resource.resx verwendet.

Development, ASP.NET

Howto: Verwenden von log4net in ASP.NET Webanwendungen

7. Februar 2007

Hier ein Kurzleitfaden, um log4net in ASP.NET Webanwendungen zu verwenden:

1. Einträge in der Web.config vornehmen:



<configSections>
  <section name="log4net"
      type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>

<log4net>
  <root>
    <level value="DEBUG"/>
    <appender-ref ref="FileAppender"/>
  </root>
  <appender name="FileAppender" type="log4net.Appender.FileAppender">
    <file value="log/log-file.txt"/>
    <appendToFile value="true"/>
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%d{dd.MM.yy HH:mm:ss} %-5p %c %m%n"/>
    </layout>
  </appender>
</log4net>

2. In der Global.cs (Global.asax) im Application_Start Event log4net initialisieren:



log4net.config.xmlconfigurator.configure()

3. Verwenden des Loggers durch eine statische Variable in jeder Klasse:



private static readonly ILog log = LogManager.GetLogger(typeof(Classname));

4. Anschliessend kann der Logger in der Klasse verwendet werden:



log.Debug(string.Format("LogMeldung {0}", varname))

.NET, ASP.NET

Kommunikation zwischen eigenen User Controls in ASP.NET

8. November 2006
Als ein ganz wichtiges Mittel zur Kapselung von immer wiederkehrenden Bestandteilen bei ASP.NET Webanwendugen existieren User Controls. Im Gegensatz zu Custom Controls lassen sich User Controls recht schnell und einfach innerhalb einer Anwendung erstellen, können aber nicht wie Custom Controls in anderen Anwendungen weiterverwendet werden.
Prinzipiell sollte man User Controls immer als eigenständige Einheit ohne Abhängkeiten zu anderen Controls oder Seiten entwickeln. Was aber, wenn man einem anderen User Control ein Ereignis senden will bzw. eine Methode aufrufen will? Beispiel: ein User Control für eine Statuszeile. Andere User Controls sollen dem Statuszeilencontrol den aktuellen Zustand mitteilen. Beispielsweise, daß Daten erfolgreich geladen oder aktualisert worden sind. Diese Infos gehören eigentlich zum guten Stil, denn in Zeiten von Ajax kann der User nicht mehr anhand des fehlenden Flackerns beim Postback erkennen, ob eine Aktion nun ausgeführt worden ist oder nicht.

Zum Senden einer Nachricht an so ein Statuszeilecontrol bedarf es erst einmal einer Klasse zur Aufnahme der Argumente:

public class StatusMessageEventArgs : EventArgs{
  private string _message;
  private int _type;

  public enum Types {
    Info,
    Error
  }

  public String Message {
    get {
            return _message;
         }
    set {
            _message = value;
         }
  }

  public Types Type {
    get {
            return (Types)_type;
         }
    set {
            _type = (int)value;
         }
    }
}


Hier wird einerseits eine Message als String übergeben, als auch der Typ der Message: Info oder Error.
Als nächstes benötigen wir eine öffentliche Methode in dem Statuszeilencontrol, dass die Nachricht empfangen und verarbeiten soll:

public void HandleStatusMessageEvent(object sender, StatusMessageEventArgs e) {
  if (e.Type == StatusMessageEventArgs.Types.Info) {
    this.TextInfo = e.Message;
  }
  else {
    this.TextError = e.Message;
  }
}


This.TextInfo und this.TextError sind nur weitere private Properties, die die Statuszeile entsprechend aktualiseren.
Im User Control, daß eine Nachricht an das Statuszeilencontrol senden will, muß ein Eventhandler definiert werden:

public event EventHandler OnSendStatusMessage;

Dieser Eventhandler kann dann entsprechend im User Control aufgerufen werden:

if (OnSendStatusMessage != null) {
  StatusMessageEventArgs message = new StatusMessageEventArgs();
  message.Type = StatusMessageEventArgs.Types.Info;
  message.Message = "Daten sind aktualisert worden";
  OnSendStatusMessage(this, message);
}

Letztendlich muss dann auf der Seite, die die beiden User Controls enthält eine Verknüpfung zwischen Eventhandler und der Methode hergestellt werden:

this.MyUserControl.OnSendStatusMessage += new
EventHandler (this.StatusControl.HandleStatusMessageEvent);

Das war's! Durch diese recht lose Kopplung können User Controls miteinander kommunizieren. Die Aufgabe der Verknüpfung der Controls übernimmt dann immer die Seite, in die die User Controls aufgenommen werden.

Development, ASP.NET

Visual Studio 2005 Performance Probleme bei ASP.NET Projekten

17. Oktober 2006
Wenn's mal wieder länger dauert beim Build: Prüfen, ob Verweise bzw. eingebundene Assemblies mit einer Refresh Datei (wie Assembly.dll.refresh) versehen sind. Diese Datei sorgt bei jedem Build dafür, dass geprüft wird, ob einen neue Version der Assembly vorliegt und das kann den Buildprozess extrem ausbremsen. In einem Projekt von mir benötigte ein Build mit einer Vielzahl von Refresh Dateien so ca. 2 Minuten, nach dem Löschen der Refresh Dateien waren es nur noch 10 Sekunden.
Das Löschen ist recht gefahrlos. Man muss dann nur selbst dafür sorgen, dass die Assemblies immer aktuell sind.

Development, .NET, ASP.NET

Global.asax ohne Code-Behind

25. Juli 2006
Zur Realisierung von ernsthaften Webanwendungen sollte man eigentlich immer das Code-Behind Modell vorziehen, anstatt den Code direkt in eine aspx Seite zu kodieren. Allerdings habe ich nicht schlecht gestaunt, als ich für eine neue Anwendung in Visual Studio eine Global.asax anlegen wollte: Es wird heifür immer Inline-Code verwendet. Auch gibt es keine Option beim Anlegen der Global.asax, um eine Code-Behind zu erzeugen. Abhilfe: manuelles Hinzufügen der entsprechenden Code-Behind Datei:

1.
<%@ Application Language="C#" Inherits="Global" %>
zur Global.asax hinzufügen. Alles andere rauskopieren.

2. Im App_Code Ordner eine Klasse Global.cs anlegen

3. In Global.cs die Klassendefinition ändern:
public partial class Global : System.Web.HttpApplication

4. Die folgenden Methoden zur Global.cs hinzufügen:
    void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup
    }
    void Application_End(object sender, EventArgs e)
    {
        //  Code that runs on application shutdown
    }
    void Application_Error(object sender, EventArgs e)
    {
        // Code that runs when an unhandled error occurs
    }
    void Session_Start(object sender, EventArgs e)
    {
        // Code that runs when a new session is started
    }
    void Session_End(object sender, EventArgs e)
    {
        // Code that runs when a session ends.
        // Note: The Session_End event is raised only when the sessionstate mode
        // is set to InProc in the Web.config file. If session mode is set to StateServer
        // or SQLServer, the event is not raised.
    }

Siehe auch Ross W Nelson's Blog: Fixing the Global.asax in ASP.NET 2.0

ASP.NET