Two Useful, Totally Unrelated ASP.NET Topics

Here are two coding tips that I have found useful in recent days:

Explanatory text in a textbox can force the user to read directions. The textbox could say something like, “Enter search terms here separated by commas.” But when the user places the cursor inside the textbox, the instructions should clear. The standard ASP.NET textbox control does not have an OnFocus event, but the same effect may be achieved with JavaScript. Add an attribute to the textbox control during the Page_Load event:

//Note that value is set to an empty string (two single quotes)
if(!Postback)
{
   txtBox.Attributes.Add("onFocus","this.value='';");
}

Some ASP.NET controls use JScript Eval statements for databinding. In some cases, you may want to include single and double quotes in the Eval format string. Use HTML escape sequences in place of quotes:

Single quote: '
Double quote: "

Consider the following example, which uses an Eval format string:

   < %# Eval("Url","this.window.href=&apos;{0}&apos;") %>

Learning CSS for ASP.NET

Several weeks ago, I started implementing an ASP.NET 2.0 interface for a postal systems project. Although I had previous experience with n-tier web architectural design, the ASP.NET programming model was new to me, as were the constellation of languages and constructs used in modern web design. My first objective was to prototype all screens in the new interface. Initially, I thought of using Visio to layout the content, but I soon realized that it’s better to put a working “skeleton” in front of the user. The skeleton may lack tier 2 connections, but it should represent the interaction model, which includes:

This article addresses the last point. CSS syntax is straightforward, but several key insights took me days to internalize. Cross-browser issues further complicate the matter, but for now I will describe high-frequency concepts that CSS designers must thoroughly understand. Unless otherwise noted, the reference “CSS” refers to the CSS Level 2 (CSS2) standard.

The Document Object Model (DOM)
W3C’s “What is the DOM?”  article summarizes technical information that I will not reproduce here. From the CSS perspective, the designer should simply remember that the DOM is a hierarchy with nodes and that a style may be associated with each node (See below).

Further, styles cascade to child nodes, but may be overridden by selectors associated with those child nodes. For example,

#header
{  
   font-size: 14px;
   margin-left: 5px;
}  

#header div
{
   font-size: 10px;
}

The first selector sets the font size for all text in the header section to 14 pixels. Inside the header section’s <div> block (or blocks), the font changes to 10 pixels. But what is the left margin for header <div> blocks? The margin-left style cascades down from the #header declaration to the child block. Therfore, the <div> block’s margin-left property is also 5 pixels.

Here it is useful to note that the DOM gave rise to the concept of Dynamic HTML (DHTML). DHTML is not a language, but rather a collection of three technologies that allow client-side modification and update of the browser display:

Taken together, these three tools allow the designer to implement a variety of dynamic features that do not require a page refresh (for example, “On Hover” text boxes, expanding text areas, and real-time clocks).

id v. class
The code above uses selectors to identify nodes in the DOM. The id and class selectors concern us now. Here is how to declare and use them:

/* This is an id */
#id-declaration
{
   font-size: 10px;
   border: solid 1px #000000;
}  

/* This is a class */
.class-declaration
{
   font-size: 8px;
   padding-left: 1em;
} 

Next, associate the selectors with specific nodes in the static HTML:

This is a class

 This is another one!

Incidentally, this example reveals the guidelines for using id and class :

Note that classes may also be defined within ids and that ids may be associated with standard HTML tags:

/* The title class only applies to children of header */#header .title
{
   font-size: 10px;
}  

/* The name id only applies to <p> elements */
p#name { font-size: 10px; }

div v. span
The “id-declaration” example applies a style to a <div> tag. A <div> is a containing block that may be used to layout elements on a page. Positioning styles applied to the <div> then move all of the elements within the <div>. By default, divs follow a flow-layout, meaning that they align vertically on the page in the order of declaration. Conversely, a <span> should be used for inline elements, such as bits of text.

CSS provides selector attributes to modify these layout schemes. float is probably the most confusing. Consider the following:

#content-container{
   float: left;
}

Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

This is a floated element. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

The floated element will align itself with the left-side of the innermost enclosing container, in this case, the body. The text (and other elements) will then flow around the <div>. Follow these rules of thumb when using floated elements:

Positioning 
In addition to float, brute-force positioning techniques exist. By default, all elements align as if position:static were declared. In other words, elements flow sequentially according to the HTML markup. Declaring position:absolute removes the element from that sequential flow:

#top-left{
   position:absolute;
   top:0;
   left:0;
}

This element will align to the top-left of the browser window, overlapping any elements if necessary. This may not be the desired effect, in which case the position:relative method exists to simply move the element relative to its position in the normal flow. The following code results in a 10-pixel indentation from the normal layout flow.

#nudged-left{
   position:relative;
   top: 0;
   left: 10px;
}

Bumped left 10 pixels!

When positioning elements, use either top or bottom AND left or right.
External v. Internal Stylesheets
In ASP.NET, I prefer to capture all master styles in a file called TopLevel.css. The master page links to this external sheet. Next, I add a content area to the head of the master page as follows:


std::string in the Visual Studio .NET Debugger

The VS.NET 2003 debugger evidently displays only the first 256 characters of a std::string. It terminates the string with “/H”. I could find no documentation about this behavior. Output the string to the console to ensure its validity:

std::string temp; //A long string
Console::WriteLine(new String(temp.c_str()));

Notifying Managed Code of a Native Callback

Here’s a way for unmanaged code to notify managed code of a callback. The two code types use different calling conventions and the user cannot change the latter’s convention. Instead, use an inner class like this:

__gc classManagedClass
{
private:
__nogc class UnmanagedClass
{
static void __cdecl MyCallback()
{
ManagedClass *mc = ManagedClass::GetClass();
mc->MyFunc();
}
};

ManagedClass *thisClass;

public:
ManagedClass() { thisClass = this; }
static ManagedClass* GetClass() { return thisClass; }

void MyFunc() {}
};

The GetClass() method is a bit unsightly, but elegent nonetheless. The managed code can pass MyCallback to unmanaged code via a function pointer. The unmanaged code calls MyCallback and then MyCallback calls the managed method MyFunc(). This approach is especially useful for IJW DLLs in VC7.

References:

Managed Assemblies, IJW, and .h Files

I solved an intersting problem yesterday, although I still cannot fully explain the solution. My project uses a mixed mode DLL to load some native binaries. I constructed the DLL as a managed assembly so that in my managed code, I can use the following:

#using "mydll.dll"

This statement–It Just Works, or IJW–imports all types. Now I had defined my exception hierarchy in a separate header common to the whole project (not just the mixed dll). The exe and dll thus had the same #include statement. I could both compile and link with this setup. When the DLL threw an exception, though, I encountered a problem. Consider this snippet:


//Exception.h
__gc public MyException : public Exception
{
MyException(String *s) : Exception(s) {}
};

//mydll.dll, built with /LD /clr
#include "Exception.h"
myFunc() {
throw new MyException(S"BLAH");
}

//main.cpp, built with /clr
#include "Exception.h"
try
{
myFunc();
}
catch(MyException *e)
{
//This handler does not catch MyException!
}
catch(Exception *e)
{
Type *t = e->GetType();
Console::WriteLine(t->ToString());
}

The second exception handler illuminated the most elusive aspect of this issue. Although the first handler could not catch the exception, the second catch block showed a MyException type. I have not found a sufficient explanation for this behavior, but it must stem from the interaction of native code and MSIL in the mixed DLL.

Mixed Mode DLL and “/Zl”

I spent 8 hours today debugging a stupid switch set by the VS.NET 2003 AppWizard. I’m trying to wrap some DLLs into a mixed mode DLL for use in some managed code. After laboring with an unmanaged wrapper compiled with /clr, I gave up and tried a “.NET Class Library” AppWizard. Then I added my DLLs, classes, etc. The project compiles correctly and then the linker fails, issuing this error:

LNK2020: unresolved token (0A00002C) ??_7type_info@@6B@

Right. I finally determined that the /Zl switch caused the issue. You will find this setting in Properties->C/C++->Command Line->Additional Options.

Mixed mode DLLs have significant issues in both .NET 1.0 and 1.1.

MFC / COM Interop with .NET (Managed C++)

Approach:

For my current project, I needed to write a plugin for an MFC-based application. I wanted both the rich GUI components and XML support provided in .NET, though, so I needed to wrap the MFC / OLE automation functionality and then connect to it via managed code. The MFC application provided a type library (.tlb). Here are the steps I took and some references.

1) The tlb only contains interface definitions. Therefore, you must generate instances of those interfaces. Unfortunately, the .NET AppWizards do not provide that capability for .NET classes. Start a new MFC project and click “Add new class” from the project menu. You can then “Add an MFC class from a type library.” Load the tlb file in the next dialog. The available interfaces appear in the left box. Select the desired interfaces and continue. A new header file will appear in the project for each interface. You can now instantiate the classes.

2) I elected to place all of the MFC code into an extension DLL and then implicitly link the DLL into my .NET code (the “It Just Works” or IJW method for mixed/unmanaged Dlls). This approach hides all of the MFC headers, types, etc. in the DLL. The managed code may operate with no notion of the underlying MFC functionality. Create a new “MFC extension DLL” project and add the classes generated in (1).

3) You must then export all functions and classes from the DLL. Instead of using the AFX_EXT_CLASS macro, I used the following code:


#ifdef _WINDLL
/* #include MFC headers here */
#define DLLExport __declspec( dllexport )
#else
#define DLLExport __declspec( dllimport )
#endif

class DLLExport MyClass
{
...
};

Add the DLLExport macro to non-member functions like this:

void DllExport MyFunc(void);

This approach mirrors the AFX_EXT_CLASS macro, but allows the .NET code to use the header without the MFC libraries.

4) I used the stock DllMain function generated by the AppWizard. Add *safe* startup code to DllMain. See the “DllMain Restrictions” section in this article.

5) Build the project. Ensure that you dynamically link the C Runtime Library (CRT) by setting the /MD or /MDd switch in Project Properties->C/C++->Code Generation. The .NET application in the next step *MUST* use the same switch. Otherwise, the exe/dll application will have two versions of the CRT and you will experience some nasty problems.

6) Implicitly link (IJW) the DLL to the .NET exe. #include the header from (3) in the EXE. Add the DLL’s .lib file to the Linker->Input->Additional dependencies box. The .lib file contains compile-time information for linking the DLL. Finally, copy the .dll file to the project output directory.

Issues:

References:

Powered by WordPress
Entries and comments feeds. Valid XHTML and CSS.