2005 2006 2007 2008 2009 2010 2011 2015 2016 2017 2018 aspnet azure csharp debugging docker elasticsearch exceptions firefox javascriptajax linux llblgen mongodb powershell projects python security services silverlight training videos wcf wpf xag xhtmlcss

Base64 PNG Server

In my mind, one of the coolest things tht modern web browsers can do is deal with base64 PNG images. PNG images are the "new standard" in web images. They can be very small in size or they can be larger as true color images depending on your needs. They don't replace everything, but they do replace a lot.

A base64 PNG image is a PNG image encoded as base64. Base64 encoding is a way to encode non-printable characters (stuff you can't see, but the computer can read) into printable characters (things like letters and numbers).

Base64 PNG images (which are text) can actually be read by modern web browsers as real images. In fact, it's one of my qualification requirements for being a modern web browser (actually there are MANY requirements in my mind). You can actually use base64 PNG images directly in CSS. Here's an example...

background: url(data:image/png;base64,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);


Well, it's not SUPPOSED to be small! It's supposed to be embeddable. And it is. But think for a moment. You can take an image (not just PNG mind you, GIF can do this as well) and turn it into Base64. Now, can't you dynamically load images on the client? Well, yes you can... All you have to do is do a remote call to somewhere which will send the Base64 stream back.

One you get the stream back all you have to do is prefix the base64 stream with "data:image/png;base64," and assign the entire value to the src property (attribute) of an img object.

Here's an example I put together a few months ago of how you can do all this... Firefox users only please! IE6 won't get NEAR base64 images.

PNG Client/Service Example

Actually, this is also a great example of how to work with web remoting (I just CAN'T call it Ajax, that's too weird) and how to dynamically work with XML files.

Firefox 1.5 released!

The last 32 days rocked! The release of .NET 2.0 and now Firefox 1.5. Both are absolutely revolutionary in their technology.

So, go get it! Woohoo!!! The link is in the list below.

Also, I remind everybody about my "What's new in Firefox 1.5" video, which is also in the list of links below.

...and yes, Chris Pederick's Web Developer Toolbar works great with Firefox 1.5. His page link is also below...

Learn WCF via MSDN Nuggets

Want to learn WCF (a.k.a. Indigo)? If so, you should head on over to MSDN UK to see Mike Taulty's latest MSDN Nuggets.

http://www.microsoft.com/uk/msdn/events/nuggets.aspx

Currently there are three videos:

  • Hello World
  • Type Serialization
  • Bindings

You will find that WCF looks much like old-school COM, but has the power of MSMQ, COM+, remoting, Web Services and the simplicity of .NET. Awesome!

For more information on WCF check out this great MSDN article: http://msdn.microsoft.com/library/en-us/dnlong/html/introtowcf.asp.

User Control Error: The base class includes the field 'xxx', but its type (yyy) is not compatible with the type of control (zzz).



I'm not a huge user of user controls, but today I was porting an ASP app over to the real world and I figured the particular scenario I was working with didn't really warrant the power of a server control. So after I went an took the 12 seconds out of the day to create a user control all was well. It was working beautifully and all that jazz…until I published the website to the test server!

The base class includes the field 'cltFemaleItems', but its type (Items)
is not compatible with the type of control (ASP.items_ascx).

WHAT!!!! I'm marking this one as an ASP.NET 2.0 bug. After a bit of searching online I realized that there aren't really ANY workarounds to this online.

I went back and read the message again and noticed this small hint: "( ASP.items_ascx)". Below is what my user control class declaration looked like and what the declarative directive looks like. Everything looks fine...

<%@ Control Language="C#" AutoEventWireup="true" CodeFile=" Items.ascx.cs" Inherits="Items" %>


public partial class Items : System.Web.UI.UserControl

Based on the error message hint, however, changed the name of the contro. Here is what I changed the above code to...

<%@ Control Language="C#" AutoEventWireup="true" CodeFile"Items.ascx.cs " Inherits="items_ascx" %>


public partial class items_ascx : System.Web.UI.UserControl 

Then I republished and viola! All it well... That's one really weird ASP.NET 2.0 bug. Anyhow, this workaround seems to work well.

"Common Language Runtime detected an invalid program"

If you've ever gotten this error you've probably been one of the most confused people in the world. In your debugging you may have seen that this message came from an InvalidProgramException.

Well, while this problem should be rare, here's an example harness of where you may see it.

// ThrowerHarness.cs
namespace ThrowerExample
{
  class ThrowerHarness
  {
    static void Main(string[] args)
    {
        try
        {
            Thrower.Start( );
        }
        catch (System.Exception ex)
        {
            System.Console.Write("Error: " + ex.Message);
        }
      }
    }
}

Alright, so where's it coming from?

In this case, it's actually coming from the IL.

// Thrower.il
.assembly ThrowerLib { }


.class public Thrower {
  .method static public void Start( ) {
    stloc.0
    throw
    ret
  }
}

This actually comes from invalid IL. In this case I'm putting 0 on the stack and then throwing...well, nothing really. This is not something a good compiler would create. If you see this it's probably a bug in the compiler or manually written IL.

Anyhow, to test the above do this...

ilasm /dll ThrowerLib.il
csc /r:ThrowerLib ThrowerHarness.cs

Atlas October 2005

If you are anything like me, you consider a technology is new as long as it's marked as experimental. Atlas still qualifies for being new...or even, pre-new. In any case, the October 2005 version of Atlas has been released and can be downloaded at the link below.

http://atlas.asp.net/

You can find a list of changes here: http://weblogs.asp.net/atlas/

Note that unlike WCF and WPF, which in my mind are stable for production, Atlas is still experimental and is only in the technical preview stages. Not that it will explode into pieces, but there is little to no documentation on almost all of Atlas and given the early nature of the product, things are almost guaranteed to change.

Cool SMS/VS2005 Integration Feature

Today I discovered a very wierd feature regarding SQL Management Studio 2005 ("SMS") and Visual Studio 2005 (of course I'm using the FREE standards editions from the MSDN/Technet seminars)

OK so here it is...

  • Open SMS
  • Navigate to a table and modify it.
  • Copy the text of one of the columns
  • Go to an ASPX page in Visual Studio 2005 and paste.

If you did it right you will see the weirdest thing in the world: it pastes a GridView linked to a SqlDataSource, which it also pastes.

<asp:GridView ID="GridView1" runat="server"
     DataSourceID="SqlDataSource2"
     EmptyDataText="There are no data records to display."
     AutoGenerateColumns="False">
    <Columns>
        <asp:BoundField DataField="ContactID"
            SortExpression="ContactID"
            HeaderText="ContactID">
        </asp:BoundField>
    </Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
    SelectCommand="SELECT [ContactID] FROM [Employee]"
    ConnectionString="<%$ ConnectionStrings:AdventureWorksConnectionString1 %>"
    ProviderName="<%$ConnectionStrings:AdventureWorksConnectionString1.ProviderName %>">
</asp:SqlDataSource>

You will also find that it pastes the appropriate connection string directly into your web.config.

<add
 name="AdventureWorksConnectionString1"
 connectionString="[string omitted;  it was LONG"
/>

Cool, huh?

p.s. If you want to paste that particular name, as I wanted to do, you can always do the old school paste-into-notepad-copy-out-of-notepad trick that is a tried and true way to strip off Web Browser formatting.

.NET Wikipedia Entry Edit

OK so I got SICK of the horrible midunderstandings written about .NET on Wikipedia...so much so that I rewrote much of it.

As of right now, 95% .NET 2.0 material written at http://en.wikipedia.org/wiki/Microsoft_.NET was written by me. The only parts I didn't write were the top two 'changes in 2.0' bullets. I added all other .NET 2.0 content.

Here are some snippets I added regarding .NET 2.0

".NET 2.0 is a severe redesign of not only the technology, but also the model of Microsoft's .NET agenda. While .NET v1.x was considered more of a Rapid Application Development (RAD) model and was often compared with Sun's Java. C# 2.0, part of the .NET 2.0 model, is now compared more closely with C++, so much so infact, that large portions of Microsoft's Windows Vista are written in C# and the .NET framework."

I also added information about how .NET was NOT the competition for Java, but was infact originally intended to be COM+ 2.5 by one team and "Next-Generation Web Services" by another. In addition, I removed anything about .NET 2.0 betas and updated the information about the express editions to be more proper.

'+' sign in e-mails



Announcement: Plus signs in e-mail addresses ARE VALID! I can't tell you how many time I went to a blog, a forum, or a (poorly design web…)store and my e-mails didn't pass validation. On some blogs I even get ASP.NET exceptions.

Plus signs in e-mails are commonly used for sub-addressing. When you have an e-mail like help@gmail.com and you don't want to give that to a webstore you can simply hand out help+nospam@gmail.com or help+Amazon@gmail.com or whatever and you're still good.

So PLEASE... if you wrote a buggy application or script that disallows '+' in e-mail addresses, fix your bugs.

Excerpts from my XHTML 1.1 Chapter



One of the great things about XHTML 1.1 is that you are never allowed to serve it's content as text. You can send every type of XHTML 1.0 as text all day long, but never XHTML 1.1. You say you never send as text anyhow? Sure you do… that's what the text/html content-type is all about. The default for every web server (that I know of) is to send "browser" content (i.e. HTML, XHTML) as the text/html content-type. To use a different content-type you have to specifically say so.

The typical way to send XHTML 1.1 content is actually with the application/xhtml+xml content-type. To server a page using this type in .NET, you simply state the following in the early parts of your .NET page rendering (at the Init or Page events).

C#

Response.ContentType = "application/xhtml+xml";

VB2005

Response.ContentType = "application/xhtml+xml"

When you do this, you kick modern web browsers, like Firefox, into what I like to call "parsing mode", "ultra strict mode", or "application mode" depending on my mood, but what it really is is XML parsing mode. In my lectures I often say "HTML is fundamentally unparsable". What I really mean is "HTML is fundamentally unparsed". That is, browsers tokenize HTML (via scanning), rather than parse it via XML parsing. Not to say that web browsers parse XML per se, but they could fundamentally do so it they wanted to. XHTML is XML and therefore "XHTML is parseable". Kicking modern web browsers into this ultra strict mode actually forces the browser to parse the page in an XML centric manner. What's this mean? It means that if your XML (XHTML) is not well-formed, it will throw an error. It's important to note that when you are in this ultra strict mode, the browser is not a validator (that would be REALLY cool), but is more of a well-formedness checker and is the closest things we have to a runtime compiler (which, I know, seems like an oxymoron.)

So, why do this work to get this ultra strict mode? For one simple reason: QA! Quality assurance requires that you take your work seriously. You can't just throw together a bunch of pages and throw them out on the web. If you were writing C#, C++, or Java you would be forced to run your code through a compiler to check for errors. By using ultra strict XHTML mode, you again get this forced compliance.

One word of caution...and it's a common word of caution. Gosh, no matter what I say or what I do on the web it always seems to be the same word of caution: this doesn't work in IE! This is because IE, by default, has absolutely no idea what application/xhtml+xml is. If you try to send this type of content to IE, it will probably try to download the file locally. Now there are times when it will load fine, but what usually is happening in these cases is that the content type is specified in the Windows registry to tell IE how to render it. Since we are talking about the web here, and not the Intranet world we have to follow the universal rules of the W3C, ECMA, and...well least common modern denominators (I throw the word modern in there just in case anyone wants to say that Netscape Communicator 4 is the LCD...and for the record, I don't care about any 4th generation browsers.)

So we need to make sure that IE doesn't get this ultra strict content type. Consequently, we won't have ultra strict mode in IE. Now, if you're paying attention at all you will notice that we have a page with at least two content-types required to support two different planets of browsers (IE, the rest of Earth). You can't send two at the same time. Not a problem. All we need to do is whip out a quick condition based upon what the browser can and cannot do.

When it comes to server-side browser detection some people like like to rely on the UserAgent string of the browser. This is actually a very bad idea due to how easy it is to modify a browser's UserAgent string (especially in IE with all the IE toolbars out there!). I actually read somewhere where someone said that "using the UserAgent is the fastest way to hell" I'd have to go along with that hyperbole.

Here's what you really do: test if the browser can accept the application/xhtml+xml content-type. If they can use it, use it. If not, don't. That's all there is to it, but before I get into the code there's one more thing. We're not talking just about the content-type here, were also talking about the document type (the DTD). If the condition comes back negative, that is, it does not accept xhtml+xml, then you can't use XHTML 1.1 either. So you also have to control the content-type nad the document type in the same shot. This is also not a problem.

Here's a standard method I use in the pages I want to be in ultra strict mode.

In the ASP.NET page, I replace the doctype with the following.

<asp:literal id="litDoctype" runat="server"></asp:literal>

Now in the code-behind I do the following...

C#

Boolean debugMode = false;
private void SetDoctype( ) {
    Boolean mimeTypeOverride = false;
    if (Request.QueryString["xhtml"] != null && Request.QueryString["xhtml"] == "1") {
        mimeTypeOverride = true;
    }
<span style="color: rgb(43,145,175)">Boolean</span> realBrowser = <span style="color: rgb(0,0,255)">false</span>;
<span style="color: rgb(0,0,255)">if</span> (Request.ServerVariables[<span style="color: rgb(163,21,21)">"HTTP_ACCEPT"</span>] != <span style="color: rgb(0,0,255)">null</span> || mimeTypeOverride) {
    <span style="color: rgb(43,145,175)">String</span> httpAccept = Request.ServerVariables[<span style="color: rgb(163,21,21)">"HTTP_ACCEPT"</span>];
    <span style="color: rgb(0,0,255)">if</span> (httpAccept != <span style="color: rgb(0,0,255)">null</span> &amp;&amp; httpAccept.IndexOf(<span style="color: rgb(163,21,21)">"application/xhtml+xml"</span>) &gt; -1 || mimeTypeOverride) {
        realBrowser = <span style="color: rgb(0,0,255)">true</span>;
    }
}


<span style="color: rgb(0,0,255)">if</span> (realBrowser &amp;&amp; !debugMode) {
    Response.ContentType = <span style="color: rgb(163,21,21)">"application/xhtml+xml"</span>;
    litDoctype.Text = <span style="color: rgb(163,21,21)">""</span>;
    litDoctype.Text = <span style="color: rgb(163,21,21)">"\n"</span>;
    litDoctype.Text += <span style="color: rgb(163,21,21)">"\n"</span>;
}
<span style="color: rgb(0,0,255)">else</span> {
    Response.ContentType = <span style="color: rgb(163,21,21)">"application/xml"</span>;
    litDoctype.Text = <span style="color: rgb(163,21,21)">"\n"</span>;
}
}

VB2005

Dim debugMode As Boolean = False
Sub SetDoctype()
    Dim mimeTypeOverride As Boolean = False

    If Request.QueryString("xhtml") <> Nothing And Request.QueryString("xhtml") = "1" Then
        mimeTypeOverride = True
    End If


    Dim realBrowser As Boolean = False
    If Not (Request.ServerVariables("HTTP_ACCEPT") Is Nothing) Or mimeTypeOverride Then
        Dim httpAccept As String = Request.ServerVariables("HTTP_ACCEPT")
        If Not (httpAccept Is Nothing) And httpAccept.IndexOf("application/xhtml+xml") > -1 Or mimeTypeOverride Then
            realBrowser = True
        End If
    End If


    If realBrowser And Not debugMode Then
        Response.ContentType = "application/xhtml+xml"
        litDoctype.Text = ""
        litDoctype.Text = "" & vbNewLine
        litDoctype.Text += ""
    Else
        Response.ContentType = "application/xml"
        litDoctype.Text = ""
    End If
End Sub

This code is actually longer than you might expect, but this version is a bit more robust than a simple condition. The first to notice about this code is obvious: it checks to see if the browser can accept the application/xhtml+xml content type by checking the HTTP_ACCEPT server variable. Depending on the result, the browser either gets application/xhtml+xml content type and the XHTML 1.1 doctype or text/html content type and XHTML 1.0 Transitional.

Secondly, as you can also see, I've included a debug mode which, if set to true, will tell the page to serve the "less-strict" doctype. This comes in handy when you want to make sure you get the "less-strict" doctype. I'm using a private class boolean field named debugMode as a means to put the entire page into debugMode. You could also use a query parameter to put just this one part into debug mode.

Finally, you can see something rather odd towards the beginning of the code. Even though we are doing all of this to guarantee well formed XML, this does not in any way give us any information about validation. That's where this other part comes in. If you were go point the W3C validator at this page it would actually get the XHTML 1.0 Transitional doctype with the text/html content-type. That's all well and good for validating against that doctype, but you technically have two different versions of the same page here. You need to validate against the XHTML 1.1 version as well. So, with the inclusion of a quick query parameter check I'm allowing for the ability to give the W3C validator a Url such as default.aspx?xhtml=1 which will force the page to be in XHTML 1.1 mode. This is a little easier than always having to tell the W3C validator the XHTML 1.1 override (I never much liked the warning it gives you anyways when you do it their way anyhow). As I mentioned previously, you could use a similar technique for for it into the "less-strict" mode. One idea would be to set default.aspx?xhtml=0 to kick in "less-strict" mode.