Here’s one of those things I’m always forgetting, and since most of my work is on-site at clients, I don’t have a large source code repository to go back to reference.
To correctly reference a style sheet from within a master page in ASP.NET, use the following:
<link rel="stylesheet" href="<%= ResolveUrl("~/css/screen.css") %>" type="text/css" media="screen, projection" />
It’s the ResolveUrl that does the trick.
At the risk of appearing to be an idiot, I’m going to blog this so I don’t forget. Especially since it bit me twice *in the same project*. Oops.
In .NET 2.0, the old method of getting information from the app.config has been depreciated. The new method is:
ConfigurationManager.ConnectionStrings.Item(YourDB).ConnectionString
For this to work, though, you need to remember to add a reference to System.Configuration. This needs to be done for each project in the solution that uses it. Thankfully I figured out that last bit pretty quickly.
I like to keep a good separation between forms and function in Windows applications I write. So to call a login form, I might call a public function on the login form like: Login.GetLogin(loginName, password).
I was trying to add yes / no values to three dropdowns on my ASP.NET page. We’re using custom drop down controls, so I needed to add the dropdown items in code behind. Always liking to be efficient in my code and make it pretty, I used this:
One piece of functionality that is often requested is the ability to submit a web form using the <enter> key. In some cases, you may need multiple textbox controls to submit differently by defaulting to different buttons. In the past there have been various javascript hacks to ensure this works successfully, but in ASP.NET 2.0 there is a simpler function.
By setting the defaultbutton property on a form or – even better – an <ASP:Panel> control, the page automatically handles it for you. Each set of controls which should submit with a certain button can be contained in the panel and everything is hooked up automagically.
One caveat: If you set a default button on a panel but not in the form, other controls seem to use the panel’s default button even when they are not in the panel.
Yes, it is true, I’ve switched to the dark side. The last bastions of VB.NET have fallen.
After a conversation with a pair of developers I work with, I have finally been convinced that C# is a better syntax than VB.NET. That’s saying something, considering I used to believe I liked my languages verbose. You know, like COBOL. There were three things in the C-based syntax of the language that bothered me:
- Case sensitivity
- Curly braces
- Semicolons
On my client’s project one of my tasks was to write a search engine and corresponding UI screen. The results of the search are displayed using an asp:Repeater control in a pattern similar to Google. One more requirement is a section that pops open to reveal additional, less-frequently-used actions. Sort of a “dropdown” of more options.
I thought I would use a hyperlink with a call to javascript that toggles the display of a <div>. It seemed like the best solution within the context of the existing page.
With that in mind, I added some javascript to my ASP.NET page (using RegisterClientScriptBlock) without a problem. But when it came to adding the “more” link and the show/hide div, I ran into a serious issue.
What I really wanted to do in the repeater’s ItemTemplate was:
<ItemTemplate>
<a href="javascript:toggleDisplay('<%=pnlMoreLinks.ClientID%>');">show / hide</a>
<asp:Panel runat="server" ID="pnlMoreLinks" CssClass="morelinks">
Show and hide me!
</asp:Panel>
<ItemTemplate>
My thought was that it would render code to the browser along the lines of:
<a href="javascript:toggleDisplay( 'ctl00_ContentPage_Repeater_ctl01_pnlMoreLinks');">show / hide</a>
<div id="ctl00_ContentPage_Repeater_ctl01_pnlMoreLinks" class="moreLinks">
Show and hide me!
</div>
The problem is that causes a compile error:
The name 'pnlMoreLinks' does not exist in the current context
Not good. Outside of the repeater, the <%=pnlMoreLinks.ClientID%> works beautifully. Inside the repeater: compile error. It seems the reference to the asp:panel is not available to other controls in the designer. In case you were wondering, proximity had no effect either.
A quick check with the other smart people led to no real epiphanies though the designer. In the end, I manually set the reference in the link to the ClientID of the panel through the ItemDataBound event on the repeater. In the code behind, this method lets you control the formatting of each row as its being rendered. The ClientID of the panel is available at this point of the page’s life cycle.
protected void rptSearchResults_ItemDataBound(object sender, RepeaterItemEventArgs e) {
HyperLink link = (HyperLink)e.Item.FindControl("lnkMoreLinks");
Panel panel = (Panel)e.Item.FindControl("pnlMoreLinks");
if (panel != null && link != null)
link.NavigateUrl = "javascript:toggleDisplay('" + panel.ClientID + "');";
}
The repeater’s ItemDataBound method has been invaluable to me in a few other tasks… having more control of the repeater than is provided by the designer and data binding is essential to usable, well-built web apps.
And now I have a hide-able div in a repeater control. Sweet.
DCOM, it turns out, is #2 on the all time Spawn of Satan list. I haven’t run into a project with more problems than the one using OLE for Process Control (OLE) over DCOM.
This week’s adventure happened because the client upgraded their machine to Service Pack 2 of Windows XP. Most in the tech industry know it was rolled out to curb zombie PCs. So the firewall and nearly everything else was closed down. Without being told about the upgrade, I was at the client site trying to figure out what was wrong.
Fixing the problem was relatively simple once I Googled DCOM changes in SP2. In fact, I even found an article on the OPC Foundation’s website on Using OPC via DCOM with Windows XP Service Pack 2 (direct link to the .pdf).
(Hat tip to Professor Z.)
For some reason I can’t seem to remember this when I need it.
If you have a dropdownlist in ASP.NET:
<asp:dropdownlist id="states" runat="server">
If this dropdownlist is databound:
DataSet ds = new DataSet();
ds.ReadXml(Server.MapPath("states.xml"));
states.DataSource = ds;
states.DataBind();
...and you want to add a blank value to ensure the user has selected a value, do the following:
states.Items.Insert(0,"");
You can substitute any value for the blank string, such as "--select--".
I finally got over the Not-Invented-Here (NIH) Syndrome about the blog here at Uhri.com. Wow, what a relief.
In 2000, when I first set up this website, I decided I would write my own app to add posts to the front page. These became known as Spectacularities. I’m not sure that at the time the word “blog” even existed. It certainly hadn’t caught on by that point if it did. Essentially, I was building software for blogging.
I wrote a quick little utility to add Spectacularities to the home page. It consisted of a user control for displaying the page, a single form for post entry, and one database table. It was enough to get things working that day and I was happily on my way. I never intended for my little blogging app to stay as small as it was. I never intended for it to end up as decrepit as it did.
For reasons I can’t remember at the moment, the admin page eventually fell into disuse. Something broke and I just never fixed it. It may have been right around the time .NET arrived and I never upgraded the page. I switched instead to using the stored procedure directly in Query Analyzer to add and update my posts. It was a lot of single quote manipulation and generally a pain in the rear.
Then the archive page, built using the said user control, began to get out of hand. When three years of posts began to appear on it the load time was unbearable. I took the archive offline.
With just the current post displayed and a propped up SP, things really began to go downhill. I posted less and less frequently. Finally, at the end of 2004, I put Uhri.com out of its misery. The whole site got replaced by a single flatline graphic. It was a sabbatical which lasted almost an entire year.
In September of 2005 I approached the problem with new vigor. I came up with a new strategy for my own blogging software, tenatively dubbed “uBlog” (I thought it was a clever name, anyway). I started the “very public” redesign of the site with requirements gathering and everything. I put up use cases and details about how the site would be designed. It was all part of my grand plan to write an XHTML and CSS-based blogging software in ASP.NET.
I started checking out the other blogging tools out there. WordPress had caught my attention on several occasions because of its standards compliance. I reviewed dasBlog, .Text and its fork SubText, and a newcomer to the .NET blogging tools, VineType. VineType seemed to be the most promising — a .NET-based blogging tool with XHTML standards. I may still consider VineType in the future as their codebase grows. The developers there seem to have a good thing started and while it may not grow to the size of WordPress, they do provide the basis of a good blogging system in ASP.NET.
As I reviewed these competitors, I came to a sinking realization.
I had NIH Syndrome. I wanted to create my own tool with features the way I wanted them. I saw the thriving WordPress community and was jealous. There were plug-ins for anything feature I could possible want. With the exception of VineType, the .NET blogging tools looked like garbage. If I were to roll my own, I could make it as easy and beatiful as WordPress. But if I built my own software, I could never reach the critical mass of WordPress. There wouldn’t be a community of developers building add-ins that would make a great .NET blogging application. There just aren’t enough bloggers in the .NET world that would care.
I wust wasn’t sure I was ready for the kind of commitment involved in something that would most likely be unsuccessful.
Joel probably said it best:
If it’s a core business function — do it yourself, no matter what.
As a corrollary, if it’s not a core business function, outsource it.
It turns out blogging software isn’t a core business function. Its not what I want to spend my free time doing. I’m much more interested in the creation of content. That’s what the blogging software is for, after all. I’d be crazy to reinvent the wheel just to call it uWheel (hey, another catchy name).
So I installed WordPress and haven’t looked back.
|
