Avonelle's Tech Blog

I’m trying to take advantage of some new features in ASP.NET 4.5. One cool new feature allows you to easily bundle and minify CSS and javascript files to reduce page load times. I’ve been having trouble getting this to work, however.

It turns out the problem was that the path I generated for my CSS bundle wasn’t authorized. So if the user wasn’t logged in, they got a page without any CSS. Oops.

To be honest, I have almost no experience with applications running in a shared hosting environment. Most of my clients completely control their web servers, and it is much, much easier to support.

But I do have one customer whose app is on a shared server. Previously it was on a fairly crappy hosting company, but recently they made the switch to HostGator. I think HostGator is probably pretty good, but it is challenging for someone like me who has not had to deal with restrictions on some of the server settings.

When we upgraded their app to ASP.NET 4.0, we started seeing session time-outs at 5 minutes. This application involves entering financial data from tax forms, and the users are generally new to the app. Five minutes simply wasn’t enough time for many users to find and enter their information. As it turns out, the problem was the Idle Time setting for the application pool – it was set to 5 minutes, and it wasn’t an option to change it. Crap.

After some research, it appeared to me that if we switched from InProc sessions to a SQL server session server, we could avoid this problem. I made the change to my test server, and it seemed like the app pool Idle time was no longer affecting session state. (Of note: the SQL Session State Server scripts want to create a SQL Server job, which isn’t possible in shared hosting either. I found this post useful for getting around this.)

Then we implemented the same change on the production site. Users were still getting knocked out of the system when they were inactive for more than 5 minutes. What?! I was pretty annoyed.

Then I ran across this StackOverflow answer, and I was able to solve the problem. It also explained why it was working on my test server and not on the live server – the test server had a <machineKey> section in the web.config, but the live server did not. So the problem was actually not session itself, but an expiring forms authentication ticket.

I hope this helps the next guy. I had a lot of problems finding explicit answers via my Google-fu about how to solve shared hosting limitations with ASP.NET session state.

This post includes a list of the author’s task list tokens and how they are used. Adding my own tokens is something I’ve always considered doing but haven’t. Plus since the author is a solo developer, he calls out how some tokens are more useful for his approach as a solo-ist. As a fellow solo developer I found this illuminating.

This post does an excellent job of explaining how the author uses OneNote for development and debugging. Some of this is my process as well, although I don’t use it for tracking history on all bugs, just those that are particularly complicated to resolve.

Not a particularly hard problem to solve, but just making a note here because some of the DevExpress site appeared to be down today. Long story short: my customer was getting this error after installing a new version of our ASP.NET application. The error is because I upgraded the controls from the last build. The DevExpress controls include the version number in the name, so when they are updated you get new DLLs in your /bin folder. The install I sent to him only had the new controls, but since he installed it over a previous build it had both the old DLLs and the new ones, causing the error.

I don’t anticipate upgrading those controls all that frequently, but hopefully I’ll remember to tell him to delete the /bin folder before installing.

I’m really sick of reporting components. Actually, that’s not entirely true: I like programming reports. And when the reporting components work, they are groovy, too.

I just wish I didn’t have to know so many of them.

For years I worked with Crystal Reports, because that’s what everybody used. It wasn’t without problems, but it was the gold standard. We used to say “Crystal Reports: It sucks less than the competition.”

When .NET rolled around and my projects started needing reports, i looked at several options. I finally settled on ActiveReports, which seemed to do for a reasonable price. In this particular case, I needed to create deliver reports over the web with embedded HTML in some of the text. I ran into problems getting this to work with our HTML, but I was mostly able to sort them out.

A couple of years ago I worked on a project that also needed to deliver reports over the web. In this case, the customer was sold on SQL Server Reports. I spent a lot of time learning the technology, but I figured it would be worth it because I would probably just start using it for all my projects. After all, it comes with SQL Server and it works!

Fast forward to the end of last year when I started a new project converting an Access application to Windows .NET. An important requirement was that end users needed to be able to modify reports and create new ones. Unfortunately, this wasn’t something I could provide with the version of SQL Server they are using. Ugh. So I discovered ComponentOne’s Report for WinForms Designer Edition. I’ve spent quite a bit of time this year learning this component. Unfortunately it isn’t cheap; I had to spend something like $1,800.

Now I’m upgrading a web application using ActiveReports to .NET 2.0. I didn’t think it was a big deal, because while the app was version 1.1, I knew I had already purchased ActiveReports for .NET 2.0.

One snag. ActiveReports for .NET 2.0 doesn’t work with VS2008. Apparently the “2.0” is referring to the version of ActiveReports, not the version of the framework. It does work with ASP.NET 2.0, but the fact that VS2008 also supports 2.0 is meaningless. The designer, will only work in VS2005.

Having spent almost $2,000 on reporting components already this year, you can understand why I didn’t want to drop another $500 for an upgrade for ActiveReports to 3.0. (Using the $2,000 reporting tool is not an option, as it is WinForms only.)

My solution has been to install Visual Studio 2005 side by side with VS2008, and create a class project that includes all the reports. Then I changed the reference in my VS2008 project to point to the DLL for that project.

It is stupid, but it will solve my particular issue.

I’d actually consider upgrading ActiveReports at some point. But I’d rather do it when I’m planning on it.

I’ve been experimenting with merging my MDIChild and MDIParent menus. My goal was to merge menu items within the File menu for each form into one universal File menu, but I was getting two file menus instead.

The secret sauce was that it apparently uses the Text property of the ToolStripMenuItem to match up the menus. And one of my menu items used “File” for the menu name, and the other used “&File” (for Alt-key access.) Once I made both Text properties the same value, it starting working as expected.

I was a bit disappointed this weekend when I realized that the ComponentOne Report for WinForms Designer Edition control is missing something I expected it would include: a way for end users to build queries. To be completely honest, I suppose it was a faulty assumption on my part; the two items aren’t necessarily the same thing. But it just never occurred to me that the designer wouldn’t include any user interface for the end-user to select the tables, columns, etc. that they will need for their reports.

I spent 5 minutes thinking that perhaps I could just create my own, but that notion was quickly thrown out the window – that would be a lot of work! I found two .NET components that seem to do the job: Active Query Builder and Easy Query .NET. I really liked Easy Query’s approach from an end-user perspective; it looks a lot easier for end-users to understand and work with.

Unfortunately, it is missing something that would make it a lot more work for me to use. Easy Query allows users to build their query via an easy user interface and then generates the requisite SQL, but it cannot take the SQL and transform it into their simple UI. So in addition to saving the SQL for selecting the records as part of the reporting code, I’d have to also save the queries in their custom format. No big deal, but I already have a bunch of queries embedded in many reports, and I’d have to take the time to re-create those again. Since Active Query Builder doesn’t have that limitation, I decided to go with it.

So far it has gone pretty well. The only outstanding problem I’m dealing with is that the reporting component handles parameterized queries with a somewhat different syntax than Active Query Builder. So I will need to do some parsing to address that. But I think it is doable in a fairly straightforward manner (hopefully).

I’m working on a project that involves converting an Access application to .NET. For the reporting piece of the application I’ve selected ComponentOne’s Report for WinForms Designer Edition, as I need to both convert several existing reports and provide an environment for users to create their own reports.

It is too early to say whether or not end-users will be satisfied with the results; I haven’t yet delivered that part of the project. I can say that I’ve been pleasantly surprised by the Access Report Import capability. While it isn’t perfect, it has been doing a reasonable job of importing the existing reports and converting them to the new format. I still have to do some clean-up work for things like specialized phone number formatting logic, but otherwise it hasn’t been too painful.

I have run into a few problems I haven’t quite figured out yet, but I’m relatively confident that I’ll be able to address most of them. The big question is: will my customer’s users find it as easy to work with the new application as they were with Microsoft Access? I hope so.

I actually enjoy creating more sophisticated reports. I wouldn’t want to do it full-time, but non-trivial reports can be interesting, and it is great to see people actually use all that data that they’ve entered.

Last week one of my customers contacted me with a problem. Their customer had purchased several HTC Touch Pro devices for use with the software I built for them. Unfortunately, the software was practically unusable on the device because it squashed everything into the upper left hand corner of the phone.

I feared that this was going to present a big problem. Fortunately, fixing this issue wasn’t bad at all. Mostly what I had to change was making sure that the AutoScaleDimensions and AutoScaleMode for the forms were set properly. Something of note: the linked article indicates that the designer automatically adds a statement setting these values, but several of my forms did not have the settings. My guess is that some of these forms were created with an earlier version that didn’t support it.

I had a few places where I had some custom scrolling code, but for the most part this was a quick fix. I was able to give the customer a quick turn-around and their customer is pleased with the results. Plus, while the app was created for square screen device, many places now utilize the complete screen if resolution is more rectangular.

I am so completely spoiled by Peter Blum's Data Entry Suite. His ASP.NET data entry and validation controls are so awesome and they just work. But this month I'm doing a lot of WinForm development, and so I can't use them. I've poked around a bit looking for something comparable to DES for WinForm development, but so far I haven't found anything as good. Plus I'm not enthusiastic about trying to wrap my head around something new, especially since the ones I've found so far are pretty pricey.

Yesterday I attended the MSDN Developer Conference in Minneapolis. This Microsoft conference is advertised as "the best of the PDC in your own backyard". Since I didn't attend the PDC, I don't know if it was the "best" but certainly there was content of interest.

The conference got off to a somewhat rocky start as the weather here had been poor the previous night and the traffic was not moving as quickly as desired. The result was that they started a half hour late to give more attendees an opportunity to arrive (they estimated that half the expected attendees were delayed by the weather.) Then the keynote went an additional 15 minutes over time, so from the beginning we were 45 minutes late! They tried to make up the time throughout the day, but as you can imagine it contributed to some confusion.

I was a bit disappointed by the keynote. The speaker touched on Windows Azure, Mesh Services, and Windows 7, but I found little in this talk that applied to me or my current customers. The Wikipedia Explorer demo was cool, but again probably not something of immediate use to me. Windows Azure is interesting, but it feels to me to be at least a couple of years out for adoption, and even then I'm not sure how many organizations have a need/desire to be "in the cloud".

The session on ASP.NET and jQuery was probably the most immediately useful of all the sessions. I wasn't very familiar with jQuery, but this session gave me some good ideas on how I might find it useful in my applications. It was interesting to me that Microsoft will not only be including it, they will also be providing full support for it. Something I need to investigate is if the use of jQuery will have an impact on DES or if they will play nice together.

I attended the Oslo session without knowing what Oslo was or if I cared. The intent of Oslo is to support a "model-driven approach" to software development. Oslo use seems even more far away than Windows Azure - I suspect that it will take a long, long time before this becomes a reality for real-world applications and not just theoretical and academic exercises. Still, the demos and discussion was interesting.

The session on Visual Studio Team System 2010 contained the most impressive demo (to me) of the entire day. The presenter showed how a bug stored in the issue tracking system could include both a video the tester reproducing the bug AND a debug trace file which the developer could attach to and use to debug the issue encountered (even though the issue occurred on a different machine for a different user at a different date/time.) I think he called this "historical debug trace" and while it was not completely wired up the concept was quite impressive. It was the first time I really thought that team system might have value for some of my customers. Unfortunately it is probably still too expensive for it to be cost effective for many of my customers.

The last session of the day for me was on ASP.NET 4.0. The big surprise for me in that session was that there were no big surprises. Almost everything he talked about was stuff I had already seen and heard about (MVC, jQuery, Dynamic Data, etc.) The two things I learned were: 1) VS2010 will support targeting ASP.NET 2.0 (as well as newer versions), and 2) we will have more control over client IDs. Both of these are useful things to know, but certainly not "big" things.

Overall it was a useful event and I'm glad I went. But I'm more glad that I didn't spend thousands of dollars trying to attend the full PDC.

Saturday I attended the fall 2008 edition of the Twin Cities Code Camp. As always, it was an enjoyable, well organized event. The only downside has been that the location is a bit too small for the activity, but they announced that the next one will be held at the U of M, so that issue should be resolved. Here is some of what I learned at this event.

How to be a Documentation Ninja

This session discussed the advantages of using the open source tool DocBook to create documentation. With DocBook, documentation is stored in XML and can be extracted in various ways and published to several different formats. This is something I will definitely be looking into further.

The Arc Programming Language

This session discussed Arc, a dialect of Lisp. The session was an interesting intellectual exercise, but Arc has little practical application for me or most business application developers right now.

Why Should Developers Care About Security?

I should have paid closer attention to the title of this session. I assume we would dig into more security specifics, but the session really was making the case for caring about security, not security implementation itself. Still, the session did a nice job of covering the many security areas developers need to consider, and it was delivered in an entertaining way.

Introducing Continuous Integration to Your Project

This session was well attended and covered a lot of ground. The one thing I wish I had asked during the session was if CI is as useful to those of us writing code alone, as most of my development work is as a solo coder. There still might be some benefit from the standpoint of making sure all the code is in the source code repository and pulling it together with automated testing, but integration is definitely less of an issue with only one programmer on a team.

Jumpstart Your Web Site with ASP.NET Dynamic Data

I've seen demos of dynamic data before, but the nice thing about this session was that it covered what the presenter thought could be better, and where he hoped the tool would go in the future. Good session.

I have to admit, I didn't take notes during this session. Unfortunately, this means I don't recall much of the specifics from this session, except that the speaker suggested that despite the turmoil in the markets this week, we can expect a lot of new and exciting things in technology.

One practical thing I took away from this session was that with web services, loose coupling is critical to changing your service without forcing all your partners to change their applications too. Also, the notion of "one true schema" is a myth, and can be a trap. Finally, I liked the suggestion to write unit tests in a completely different language (like with the Java toolkit). That way, you will more quickly find problems that will only surface with non-.NET consumers of the service.

This session focused on the business problem of showing store locations that are close to a provided address or zip code. Since I've solved this problem before, I was curious if there were better approaches to cracking this nut. As it turns out, my approach was dead-on for SQL 2000 (which happened to be the database I used), but there are other approaches for SQL 2005 and the new SQL 2008. The key with SQL 2008 is the addition of several data types that represent spatial data. The session covered how to use these new datatypes for various scenarios. I hope I get an opportunity to take advantage of this - I think this work is quite interesting.

Overall - it was a great conference! It sounds like they intend to come back next year, and I expect it will be just as good. It is a great alternative to high priced conferences like VSLive and TechEd, especially if you are in the Twin Cities.

I spent Monday and Tuesday at the Heartland Developers Conference in Minneapolis. I got a lot out of last year's event in Omaha, so it was a pleasure to attend it this year in Minnesota and skip the travel time. Here are some of the take-aways from the sessions I attended day 1:

Microsoft Software Development: Present and FutureThis session has some interesting tidbits. For example, I learned that many consultants at Magenic are running Windows Server 2008 as their desktop operating system. Also, .NET 3.0 is really an "add-on" to .NET 2.0 because Microsoft wanted to avoid the interdependency issues they experienced with the 1.1 to 2.0 upgrades. Rocky also defended the new Entity Framework. He noted that this version may not be appropriate for some scenarios, future versions will be better. Rocky indicated that parallel computing is an important trend that developers need to keep an eye on. (While his slides noted that virtualization was another important trend, he didn't really discuss this, which was too bad, because there are also some interesting things happening in this area.)

Overall, it was a great keynote. Lots of high level stuff to think about for the future.

This is one of those sessions that I attended not because I think I'll get to do much with SQL 2008 soon, but so that I have a better sense of what the technology brings to the table. Here are the factoids I got out of this session:

Yes, I have attended this session previously. But every time I go, I get something new out of it. This session is a vary practical session for ASP.NET developers. This time around, I learned:

97% of browsers can handle compression, and the server can handle sending not-compressed pages for those that don't, so there is really no downside to using compression in IIS, except if your server is already running into high CPU usage. Compression can cut bandwidth usage by 50%. Also, compression will work on web services for ASP.NET 2.0.

This session was quite interesting. I'm not sure how I can use it yet, but the notion of rating features based on levels of complexity instead of just trying to total up hours to complete was a different way of looking at the problem. One thing I took away from the session was that getting a business analyst or customer representative involved in the process could be quite valuable. Without looking at hours, by saying that feature X is at complexity level 2 and feature Y is at level 13, it helps customers to better understand where the most significant costs and effort reside. That can be useful for planning purposes and making decisions about priorization.

Today I solved a problem I was having with ASP.NET's membership provider and the "remember me" option for logging in. The problem was basically that if the user checked the "remember me" checkbox, during log-in, then closed their browser and re-opened the site, they were taken to the log-in page again. Thus, it appeared that the remember me option wasn't working.

It was.

The real problem was that the page "login.aspx" had been added as the default document in IIS. So, if the user didn't specify a page when they went to the site, login.aspx was loaded, and it looked like remember me wasn't working.

The solution was to remove login.aspx from the list of default documents in IIS. We also had to change the web.config so that the loginUrl attribute for the forms tag referenced login.aspx with a tilde (loginUrl="~/login.aspx").

This is a fairly obvious answer, but since I didn't find it when I was trying to resolve my problem, I'm adding it for the next guy.

I'm disappointed to say I won't be attending this year's Deeper in .NET. After going to Milwaukee in 2006 for this event with Val, I had such a good time that I've really been looking forward to them doing it again.

Unfortunately, the timing doesn't work very well. It is on the same date as the Twin Cities Code Camp, and TCCC is probably a better fit from a practical standpoint. (It has more sessions, and while both events are free, the distance to Milwaukee means additional costs like gas and a hotel.)

Hopefully, they'll be able to have this event again next year so that I can attend it again. Val and I met so many nice and interesting people in Milwaukee, and the sessions were really good. I hope they have a really good event on Saturday.

After much pain and suffering, I did finally get Visual Studio 2008 downloaded and installed into a new virtual machine template. Although there is no technical requirement for this, I like to keep separate virtual machines for each version of Visual Studio. The main reason is virtual machine size. If I have to keep multiple versions of Visual Studio in one VM, the disk size on the VM has to be a lot bigger. Although I also divide my VMs by customer, this isn't too much of a problem as for most of my customers we do not have to support multiple versions of Visual Studio. So, once I upgrade their apps I can archive the old VM and eventually delete it.

I haven't had a chance to do much with the RTM, but I do have some programming to do over the next few weeks so it should be fun to play with.

I started my Visual Studio 2008 RTM download last night. It was at 40% when I went to bed, and I expected it to be done this morning. When I logged in, it was at 99%, but with no connections. I tried to pause and restart it, and it restarted, at 0%. Blech.