Png images and ASP.NET… Getting a “A generic error occurred in GDI+”?

Another one I would have spent hours on was solved in two minutes by the wonder that is the internet. More specifically Chris Garrett over at ASPAlliance explains the solution to the png generic error in GDI+ exception .

The short story is you can’t use the Bitmap Save() method with a non-seekable stream. So, instead of just doing this:

img.Save(context.Response.OutputStream, ImageFormat.Png);

You have to do something like this:

MemoryStream memoryStream = new MemoryStream();
img.Save(memoryStream, ImageFormat.Png);
memoryStream.WriteTo(context.Response.OutputStream);

Cheers Chris, you saved me hours of work!

Simple ASP.NET SEO Enhancement

As many people have mentioned one of the most important (and easy) SEO related enhancements you can make to your site is to use a unique title and meta description on each page.

In ASP.NET 2.0 the page title is easily set either via either the title attribute of the page directive in the markup, or by setting it directly in code e.g

this.Title = “my unique title”;

Creating a unique meta description is slightly more involved but still pretty straight forward.

HtmlMeta metaDescription = new HtmlMeta();
metaDescription.Name = “description”;
metaDescription.Content = “my unique description”;
this.Header.Controls.Add(metaDescription);

These are two of the simplest and quickest SEO related enhancements you can make to your ASP.NET site – you’ve really got no excuse not to!

Ndbunit is great – once you get past the pain

Over the last few days I’ve been setting up my latest project to use Ndbunit to initialise the database to known state prior to running each of my unit tests. It has been a bit of painful process as the documentation is fairly minmal and non-existant for some features, but I think I’ve got there now.

A couple of things I wanted to put down here in case I ever forget them and start banging my head on the desk again!

Firstly if you want to use the InsertIdentity method you need to make sure your xsd sets the AutoIncrement attribute to true for your identity column. eg.

<xs:element autoincrement=”true” type=”xs:int” name=”PERSON_ID”>

Secondly if you want to insert more than one row into a table you need to make sure your xsd sets the IsDataSet attribute to true e.g

<xs:element name=”PERSON” isdataset=”true”>

HttpHandlers and session state

While hacking on my website the other night I found a need to build an HttpHandler (actually a page would have worked fine, but a httphandler was more elegant). I got part way through debugging when I found that session state wasn’t available in an HttpHandler! This caused me some consternation as I have an HttpModule which I use to retrieve my nhibernate session during the execution of a request and it stores the nhibernate session in the HttpContext session (hopefully that’s not too many sessions and you’re still with me).

Anyway I almost re-engineered the handler to work another way when a search of google groups revealed this simple solution, your handler simply has to “implement” the empty IRequiresSessionState interface (you’ll need to be using the System.Web.WebSessionState namespace.) e.g.

public class VerificationHttpHandler : IHttpHandler, IRequiresSessionState

That’s it, you now have http session available in your handler.

nhibernate – a complex beast

I am beginning to discover that nHibernate is a far more complex beast than I realised. Over the last couple of days I’ve spent some more time reading the documentation (out of necessity rather than pure interest) and it is capable of some amazing things, however this flexiblity comes at the cost of complexity (as is often the case).

Here’s an example of a trap for young players that caught me the other night. I have two entities A & B that map two two underlying tables tableA and tableB. The primary key of tableA is a foreign key in tableB. tableA contains a property Rating1Count which is the count of a column in tableB. I had code similar to the following:

ISession session = NHibernateHttpModule.CurrentSession;
ITransaction transaction = session.BeginTransaction();
try
{
    log.Debug(“Saving new B”);
    session.SaveOrUpdate(b);

    log.Debug(“saved new B”);
    ICriteria crit = session.CreateCriteria(typeof(A));
    crit.Add( Expression.Eq(“AId”, a.AId) );
    log.Debug(“Executing query”);
    IList As = crit.List();
    if (As.Count == 1)
    {
        a = As[0] as A;
        log.Debug(string.Format(“Count of 1s in tableB {0}”, a.Rating1Count));
    }
    transaction.Commit
}

After testing this I found that even though my changes were being persisted to tableB (verified by querying mysql directly) they weren’t reflected in my tableA object.

Then it dawned on me, at what point does nhibernate write the changes to the database? I moved the transaction.Commit line up to be directly below the call to SaveOrUpdate and lowe and behold it works!

In hindsight it’s obvious, but it had me scratching my head for a while (and it was late – at least that’s my story and I’m sticking to it!).

Nasty little ASP.NET 401 problem

I discovered this nasty little problem the other day while building a couple of simple little pages and I thought I should post it so I don’t forget and waste ages on it again!

Essentially the issue is that if you have custom error pages for different types of http status codes such as 401, 403 or 404 then you will have be prepared to do a little bit coding for your 401 page to be displayed unlike your other error pages which you can automatically redirect to by turning on customErrors in the web.config file like so:

<customErrors mode=”Off” defaultRedirect=”Error.htm” >
<error statusCode=”403″ redirect=”AccessDenied.htm”/>
</customErrors>

The problem with 401 is that if you are using the web.config authorisation section as well, and you have explicitly denied the user permission then their request will be authenticated but not authorised and appears to be terminated before the ASP.NET custom error handler can run. For example:

<location path=”MySecurePage.aspx”>
<system.web>
<authorization>
<allow users=”james” />
<deny users=”*” />
</authorization>
</system.web>
</location>

Here the only way to redirect your user to your custom error page will be to check for this condition in the application_end event in the global.asax like so:

protected void Application_EndRequest(Object sender, EventArgs e)
{
if (Response.StatusCode == 401 && Request.IsAuthenticated == true)
{
Response.ClearContent();
Response.Redirect(“AccessDenied.htm”);
}
}

Note: trying to set your custom 401 page in IIS won’t work either as user is authenticated by IIS, but their authorisation fails at the ASP.NET level

Nasty!

Thanks to Ashraf Moollan

A useful .NET library to know about

I recently discovered Mapack for .NET by Lutz Roeder of Reflector fame. If you haven’t heard of Reflector I don’t know what rock you’ve been hiding under…

Anyway Mapack is a great library of math functions you’re likely to need at some stage but aren’t built into the .Net framework. I was looking for a Matrix class for doing matrix math, and also an example of a least squares implementation in C#. Mapack has both of these and a bunch more.

Check it out at http://www.aisto.com/roeder/dotnet/

Event preemption?

So I’ve been having this wierd problem with event execution order where half way through handling one event another event handler is fired. If you know why please enlighten me!

Here’s a copy of my newsgroup post which you can find here.

I am seeing some unexpected behaviour in a single threaded winforms app

and was hoping someone could explain what is going on.

I have two events attached to a chart control on my form, and during

execution one event seems to preempt the execution of the other.

My code looks similar to the following:

private void MyChart_Click(object sender, System.EventArgs e)

{

…do some logic tests

GetSomeData();

}

// This event is attached to the context menu for the chart control.

private void DrillDownMenuItem_Click(object sender, System.EventArgs e)

{

…do stuff

}

private DataSet GetSomeData()

{

…setup tasks

…Call web service

…finish stuff

}

What happens is that when I right click and select drill down from the

chart controls context menu the MyChart_Click event fires and does the

logic tests. Execution then steps into the GetSomeData method, but when

the web service is called execution jumps to the

DrillDownMenuItem_Click event. This runs to completion then execution

returns to the GetSomeData method which finishes and finally returns to

the MyChart_Click event handler.

Can someone explain why this is so?

[EDIT] so I figured it out by myself. I turns out it is a bug in the dundas chart control >:-(