Server.MapPath
June 26, 2012 Leave a comment
Last week, I created a WinForms signature capture panel and then rendered the data out to a webpage. You can read about it here. The problem is that I used Response.Write to write the image to the browser. Even in a web control, the only thing shown in a browser is the image:
gives this:
I then decided that I should use a Web.UI.Image Control to render the image.
The problem? ImageUrl is the method you use to assign the image, and that only has 1 signature – 1 String that is the Url of the image that is, typically, located on the file system.
Without thinking too hard, I decided to put the image on the file system and then point to the image in the code behind.
I wrote the following code:
private void LoadSignature() { SignatureFactory signatureFactory = new SignatureFactory(); String fileName = String.Format("~/images/Signature.bmp"); using (Bitmap bitmap = new Bitmap(200, 100)) { using (Graphics graphics = Graphics.FromImage(bitmap)) { Signature signature = signatureFactory.LoadSignatureFromFileSystem(@"C:\Signatures\signature.xml"); Pen pen = new Pen(Color.Black); SolidBrush solidBrush = new SolidBrush(Color.White); graphics.FillRectangle(solidBrush, 0, 0, 400, 50); foreach (Glyph glyph in signature.Glyphs) { foreach (Line line in glyph.Lines) { graphics.DrawLine(pen, line.StartPoint.X, line.StartPoint.Y, line.EndPoint.X, line.EndPoint.Y); } } bitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Bmp); } } this.signatureImage.ImageUrl = fileName; }
When I ran it, I got the following exception:
Carp! And no inner exception to boot! When you Bing/Google/AskJeeves this exception, you get TONS of potential reasons (Security, Location, OOM, etc…) – basically, the managed wrapper for the CGI+ call didn’t implement any exceptions. Without knowing anything about the implementation, I have to believe that HRESULT did return something, MSFT was just to lazy busy to send out meaningful exception message.
After screwing around for a bit, I would get the message to write to the file system by hard-coding the path like so:
//String fileName = String.Format("~/images/Signature.bmp"); String fileName = String.Format(@"C:\Users\Jamie\Desktop\Tff.SignatureCapture\Tff.SignatureCapture.WebForm\images\Signature.bmp");
The problem is that the Signature.ImageUrl now breaks:
It was coding after 8PM, so I immediately started throwing more gasoline on the fire by compounding my mistakes. I thought, heck, I need need 2 strings for the file – 1 that the GDI+ uses to write and 1 that the ASP:Image control can read from like this:
It worked, so I went to
String readFileName = String.Format("~/images/Signature.bmp"); String writeFleName = String.Format(@"C:\Users\Jamie\Desktop\Tff.SignatureCapture\Tff.SignatureCapture.WebForm\images\Signature.bmp");
bed, safe in the knowledge that I created a great solution:
Around 2 in the morning I woke up. “You idiot” I thought. The ASP.NET framework already has a provision to resolve relative and absolute paths. It is the Server.MapPath function:
bitmap.Save(Server.MapPath(fileName), System.Drawing.Imaging.ImageFormat.Bmp);
Sure enough, that did the trick. Since I was up a 2:15AM with my computer on, I decided to look at the ASP Image.Control to see if I could extend it to have an ImageStream function.
Sure enough, it is not sealed. that might be a fun project for next week. I went back to sleep, in a better place….