- C# Objects
- XML Mappings (something extra to learn)
- Database relations
17 November 2009
Not that into NHibernate
10 November 2009
ObjectDataSource TypeName and Nested Classes
The type specified in the TypeName property of ObjectDataSource 'myODS' could not be found.
Long story short, the object I was using was actually a nested class. Even though you write you code like this:
MyNamespace.MyClass.NestedClass.Action();
The actual fully qualified type name for an ObjectDataSource TypeName will be "MyNamespace.MyClass+NestedClass" with a SelectMethod of "Action". If you visit this MSDN page and look down to where it talks about delimiters, you will see that nested classes use a plus as a delimiter for some reason instead of the usual dot.
05 October 2009
Crystal Reports 2008 V1 and MySQL
I finally ended up finding this page, and using the JDBC drivers. They aren't perfect, and they are a pain to install (editing config files), but they seem to work better than ODBC. I suppose Crystal just hates MySQL... which is ironic since that's the database they embed in their server product!
Getting Crystal Server 2008 setup... now that's a whole different (and painful) ball of wax. If I had this to do over again, I think I would have evaluated Crystal alongside a solution from Logi first. From the hassle I've had just to get a Crystal Reports Server 2008 solution working (and still not successful so far), I can only imagine it being better with Logi.
17 April 2009
Using Reflection to fill a Business Layer object
Getting tired of endlessly assigning properties for business objects, I decided to try to make life easier on myself. So I developed a handy class, which takes a DataRow and fills a Business Layer object with that data. So now every one of my business object constructors is as simple as this:
public MyItem(DataRow Row)
{
Converter.Fill(this, Row);
}
The class that does all the conversion is as follows:
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
namespace MyNamespace.Data
{
class Converter
{
public static void Fill(object LogicObject, DataRow Row)
{
Dictionary<string, PropertyInfo> props = new Dictionary<string,PropertyInfo>();
foreach (PropertyInfo p in LogicObject.GetType().GetProperties())
props.Add(p.Name, p);
foreach (DataColumn col in Row.Table.Columns)
{
string name = col.ColumnName;
if (Row[name] != DBNull.Value && props.ContainsKey(name))
{
object item = Row[name];
PropertyInfo p = props[name];
if (p.PropertyType != col.DataType)
item = Convert.ChangeType(item, p.PropertyType);
p.SetValue(LogicObject, item, null);
}
}
}
}
}
The full class for MyItem could look something like this:
using System;
using System.Data;
namespace MyNamespace.Data
{
public class MyItem
{
public int item_id { get; set; }
public string item_name { get; set; }
public DateTime item_expiry { get; set; }
public MyItem(DataRow Row)
{
Converter.Fill(this, Row);
}
public static MyItem Select(int item_id)
{
DataRow row;
// code to perform query and get row
...
return new MyItem(row);
}
}
}
In this implementation of Converter, your business object properties have to have the same names as the column names in the database. However, the Converter could be modified to also accept a Dictionary (or array of KeyValuePair) that provides a mapping from database column names to object property names.
26 March 2009
Why no one should ever again use Internet Explorer
Web pages, which by my reckoning are the core use of the Internet, unfortunately don't magically spring up. A person has to create those pages. A person then has to maintain those pages. If a page feature is difficult to get working or is not supported in all browsers, then that feature gets abandoned. Thus, if a browser lags behind, and a lot of people are using that browser, then developers have to forsake features, or worse hack them in, to target the maximum audience.
This brings us to IE, which is by far the furthest behind the curve, both in terms of standards-compliance and features. Take a simple feature like rounded corners, which have been available in other browsers since IE was at version 6. For a developer to add rounded borders in FireFox, Chrome, and Safari is a couple of simple lines of styling. IE 7 and 8 releases passed by without this simple feature, and Microsoft's recommendations (put out in 2005, and sadly still relevant to IE8) on how to emulate this feature all complicate and bloat site design and maintenance.
Some developers will still choose to implement features like this. And as a result, they will spend a chunk of their time implementing and maintaining the hacked-in-for-IE feature rather than developing other features. The end result is that the users of the site lose out. All the time the developer wasted on adding in an IE-specific hack could have been put to a much more constructive use.
So far I've only mentioned absence of features. IE has a number of rendering problems that cause a developer to spend a lot of time trying to get a site to work in IE. All browsers have rendering issues, but IE is the very worst in my experience.
With the recent release of IE8, some of IE's hackiness will supposedly be eliminated, but it is still very far behind in terms of features.
So, from a developer standpoint, IE is severely limiting. Not only does it not have time-saving features that other popular browsers are supporting, but years will pass before they update the browser, and then they don't add much, or even get anywhere close to catching up to the state-of-the-art, from a developer perspective.
The best way for the web to move forward is for IE to be abandoned wholesale by users. Then developers can turn the time they would ordinarily waste hacking things into their code for IE into more time creating, innovating, and improving the web. If users dropped IE en mass, I believe that web developer productivity would increase by no small amount. Which in turn means that the end user has a better experience.
If you use a PC (IE is currently only available on PC), do yourself and the rest of the Internet a favor and use IE only once: to download some other browser. Firefox is probably the most popular. Safari is great if you like simple interfaces. Chrome is currently my favorite and is produced by Google.
27 January 2009
jGrowl
I started developing a web application that needs a sophisticated notification system. It turns out the actual notification message is the easy part since jGrowl does all the work for me.
Here's all you have to do to get jGrowl to work:
Download jGrowl.
Copy the 3 files into your web site directory:
jquery-1.2.6.js (or your newer or minimized version of jQuery)
jquery.jgrowl.js (or the minimized version)
jquery.jgrowl.css
(I put the 2 .js files in /scripts and the .css file in /styles.)
Link to the 3 files like so:
<link href="styles/jquery.jgrowl.css" rel="Stylesheet" type="text/css" />
<script src="scripts/jquery-1.2.6.js" type="text/javascript"></script>
<script src="scripts/jquery.jgrowl.js" type="text/javascript"></script>
Then within any Javascript file, you should be able to call jGrowl:
$.jGrowl("This is a jGrowl notification.");
Also, the notification text was blue for me, which didn't look to good on a black background. I fixed it by adding the following CSS to my main CSS file:
div.jGrowl div.message
{
color: #fff;
}
24 September 2008
More Navigation
Cross-browser support (IE, Chrome, Firefox)
Scriptable (add/change links by only changing HTML, can create an ASP .NET or other server control with it)
The design I came up with looks like this:
The images are replaceable to match whatever theme. Sizes and so forth can be adjusted in the CSS.
Here's the HTML layout:
<div class="line"></div>
<table class="links" cellpadding="0" cellspacing="0">
<tr><td>
<a href="#">
<span class="left"></span>
<span class="mid-wrapper">
<span class="mid"></span>
<span class="text">Text</span>
</span>
<span class="right-mid"></span>
</a>
</td><td>
<span class="divider"><span>
</td><td>
<a href="#">
<span class="left-mid"></span>
<span class="mid-wrapper">
<span class="mid"></span>
<span class="text">Text</span>
</span>
<span class="right-mid"></span>
</a>
</td><td>
<span class="divider"><span>
</td><td>
<a class="selected" href="#">
<span class="left-mid"></span>
<span class="mid-wrapper">
<span class="mid"></span>
<span class="text">And More Text</span>
</span>
<span class="right"></span>
</a>
</td></tr>
</table>
</div>
It is a lot of HTML, compared to some other ways to do it, but it doesn't have any weird, oversized target areas, and it is very scriptable.
Here's the CSS (for transitional doctype):
{
position: relative ;
width: 100% ;
height: 32px ;
text-align: center ; /* centers in IE */
}
.subNav .line
{
position: absolute ;
left: 0 ;
top: 15px ;
height: 1px ;
border-top: 2px solid #aaa ;
width: 100% ;
}
.subNav .links
{
position: relative ;
top: 0 ;
margin: 0 auto ; /* centers in firefox and chrome */
text-align: center ;
vertical-align: bottom ;
}
.subNav .links a
{
position: relative ;
display: block ;
text-decoration: none ;
color: #000 ;
height: 32px ;
padding: 0 4px;
}
.subNav .links a:hover
{
cursor: pointer ;
}
.subNav .links a .left
{
position: absolute ;
display: block ;
left: -4px ;
width: 8px ;
height: 32px ;
background: url(subNav-grey-left.png) no-repeat ;
}
.subNav .links .selected .left
{
background: url(subNav-blue-left.png) no-repeat ;
}
.subNav .links a:active .left
{
background: url(subNav-blue-left.png) no-repeat ;
}
.subNav .links a .right
{
position: absolute ;
display: block ;
top: 0 ;
right: -4px ;
width: 8px ;
height: 32px ;
background: url(subNav-grey-right.png) no-repeat ;
}
.subNav .links .selected .right
{
background: url(subNav-blue-right.png) no-repeat ;
}
.subNav .links a:active .right
{
background: url(subNav-blue-right.png) no-repeat ;
}
.subNav .links a .left-mid
{
position: absolute ;
left: 0 ;
top: 0 ;
display: block ;
width: 4px ;
height: 32px ;
background: url(subNav-grey-mid.png) repeat-x;
}
.subNav .links .selected .left-mid
{
background: url(subNav-blue-mid.png) repeat-x;
}
.subNav .links a:active .left-mid
{
background: url(subNav-blue-mid.png) repeat-x;
}
.subNav .links a .right-mid
{
position: absolute ;
right: 0 ;
top: 0 ;
display: block ;
width: 4px ;
height: 32px ;
background: url(subNav-grey-mid.png) repeat-x;
}
.subNav .links .selected .right-mid
{
background: url(subNav-blue-mid.png) repeat-x;
}
.subNav .links a:active .right-mid
{
background: url(subNav-blue-mid.png) repeat-x;
}
.subNav .links a .mid-wrapper
{
position: relative ;
display: block ;
}
.subNav .links a .mid
{
position: absolute ;
display: block ;
height: 32px ;
width: 100% ;
background: url(subNav-grey-mid.png) ;
}
.subNav .links .selected .mid
{
background: url(subNav-blue-mid.png) ;
}
.subNav .links a:active .mid
{
background: url(subNav-blue-mid.png) ;
}
.subNav .links a .text
{
position: relative ;
top: 8px ;
font-size: 14px ;
font-family: sans-serif ;
line-height: 16px ;
vertical-align: top ; /* makes it v-centered in IE */
padding: 0 8px ;
}
.subNav .links .divider
{
display: block ;
height: 32px ;
width: 1px ;
background: url(subNav-divider.png) no-repeat ;
}
As you can see, everything to do with the layout is defined in the CSS, from sizes to images.