Subtext: Alternative to Community Server and dotText
posted on 03/04/06 at 11:28:56 am by Joel Ross
About the time that Community Server was announced, Phil Haack decided he didn't want to move in that direction, so he took the current dotText code base (which hadn't been updated in a while) and started making the changes he wanted to see. He called it Subtext, and this past week, it hit 1.0.
I haven't checked it out yet, but the feedback that I've seen thus far has all been positive, so if you're looking for an alternative to Community Server and dotText is a little outdated for your liking, you should check out Subtext.
Of course, there's always dasBlog too. Anything project that has Scott Hanselman's hands in it has to be good!
Someday, maybe I won't be so cheap and spring for some hosting that actually supports ASP.NET and be able to use one of these projects.
Categories: Software
Code Generation or O/R Mapping?
posted on 03/04/06 at 01:05:22 am by Joel Ross
I'm going to be doing a major revamp of the business and data layers of an application I have. Right now, it's mainly data readers and dataviews being used, with a few custom business objects. While it works, and is efficient for the task, I programming will be easier and less error prone if I can switch to a domain model with all business objects.
Which brings me to my question. Which is better? Code generation or O/R mapping? I'm a huge fan of CodeSmith, and recently got a license for version 3. I've generated thousands and thousands of lines of code with CodeSmtih, so I'm familiar with it. I've never done anything beyond a sample application with any O/R mapper, so I'm fairly new at it.
Here's where I see the advantages and disadvantages for each one. Let's start with code generation. You have complete flexibility. You can create your objects just the way you want them. You can inherit from your own base class, or not have one if you don't want one. The downside is that if you change your data model, you have to touch the objects to reflect those changes. Plus, while a tool like CodeSmtih is awesome, it can be cumbersome to create the initial template (hint: create a class the way you want it, and back into a template).
For O/R mappers, a lot require you use a base class that all objects have to inherit from. This limits your flexibility. Others have requirements on how you have to do things, which again limit your flexibility. The advantage is that there's basically no data layer?- it's generated (usually on the fly) by the O/R mapping software, and "just works."
Right now, I'm leaning toward generating everything, but I can stil be persuaded. What's the best O/R mapper you've used (and remember, I'm cheap!)? Would you rather generate or map?
Categories: Development
ASP.NET 2.0 Development Heating Up...
posted on 03/03/06 at 11:14:51 pm by Joel Ross
...according to book sales over at O'Reilly. Of course, book sales don't necessarily indicate actual numbers, but it seems like a pretty good indication. ASP.NET book sales are up, while PHP and JSP book sales are down. Now,?I could easily see this being explained away by saying that there's no need to buy a book on PHP or JSP since there's a huge amount of online resources for each of those two, but not so much for ASP.NET 2.0, and I'm sure that's part of it.
But still, being an ASP.NET 2.0 developer, that makes me feel pretty good about what I'm doing!
Categories: ASP.NET
ClickOnce Deployment on dnrTV
posted on 03/03/06 at 03:44:41 pm by Joel Ross
Man, I wish this was available three or four months ago when I was building my first ClickOnce application! On the latest editon of dnrTV, Brian Noyes does a few simple demos that show you exactly how to build a ClickOnce app. It's a great watch, even if you've already built one in the past.
Categories: Development
NCAA Tournament Pools Are Legal In Vermont
posted on 03/03/06 at 01:40:19 am by Joel Ross
One of the things we struggled with when we first started the Tourney Pool Manager was the gambling aspect. We include a money mode, but with a disclaimer saying that if you use that for gambling, you accept all risk.
Why do we even include that? Well, it's not illegal everywhere. If you're in Vermont, it actually is legal. They've made an exception to gambling for March Madness office pools! I guess they figured it'd be too hard to enforce anyway...
Categories: Develomatic
Sahil Malik Coming to Grand Rapids
posted on 03/03/06 at 01:30:59 am by Joel Ross
Sahil Malik will be speaking at the April 11th GR .NET User Group meeting. I'm planning to attend at this point, and looking forward to meeting Sahil.
He's not listed on the GR .NET website, but he's got it listed on his site, so I'm going to go with that.
Categories: General
How I Use Virtual PC (or VMWare) For Development
posted on 03/03/06 at 12:58:18 am by Joel Ross
A reader recently (well, recently when I first starting writing this!) asked me to expound upon how I use Virtual PC for development, and I'm more than happy to do so.
I made the switch to Virtual PC for development early last year, so I've worked through quite a few of the issues I ran into, and I'll talk about those, as well as highlight some of the issues that I'm still struggling with, and how I've been able to work around them so far.
The first thing I did was build a base image that had everything on it that I thought I would need. I installed things such as Office, Visual Studio, and MSDN documentation. I used Windows 2003 for a variety of reasons, but the fact that it supports multiple websites and is the environment that I deploy most of the projects I work on were the main factors in my decision.
I didn't start out using Virtual PC. I started doing all development on my laptop, mixing and mashing client environments and hoping there were no conflicts. Well, there were, and that's what led me to Virtual PC in the first place. I say this because that's how I got a list of the software I wanted on my virtual drives. I made a list of all software I had on my machine, went through and eliminated the software I didn't need (another downfall of doing it all on one machine!), and divided it up. I had three lists: Base machine, virtual disk, or both.
So I made one virtual disk with all of the software on it I wanted and configured everything like I wanted - things such as font colors in Visual Studio (I like my strings to be in red, my XML opposite of what is default, etc.), my shortcuts, including setting up TaskSwitchXP and SlickRun with the settings I want. Then I install the latest patches.
After everything was configured like I wanted, I shut it down, and made a copy of it. That copy is what I used for my first client development environment. I renamed it so that I didnt' have naming conflicts, and then I installed the software I needed for their environment (Source OffSite and a VPN client, for the first one I did) and then start using it. Anything I changed that was also on the base, I kept track of as a task to perform on my base image. Any software I started using that I couldn't live without went on a list to be installed on the base.
So what happens when I have a new client that I need a new VPC for? Well, I open up the base, apply any patches, and then work my way through the list I made while using the first VPC. Then I shut it down, and copy it. Then I go through the same process as above.
Why do I copy instead of using differencing disks? First, the patching is key to me. I want to be able to apply patches to my base and not have to do it to every image I base off of that. I know I could have multiple layers of differencing disks, but that just seems?problematic for me to maintain. I'd rather patch and copy, and be ready to go. I don't really use differencing disks at all - I've heard they can grow to be as big as regular disks over time, so I don't see the need. Also, I'm not doing this to test environments, I'm doing it to have isolated environments. Therefore, there's no need for me to use them.
If I was using VMWare on a regular basis, I would go through the same process, except at the end, I'd convert it to a VMWare disk and use it that way. Why start in VPC? Because I can easily convert to VMWare if I need to, but I can't go back the other way.
If you're using VPC or VMWare, what do you do differently, and why?
Categories: Consulting
Tourneytopia.com Updates
posted on 03/03/06 at 12:34:49 am by Joel Ross
Since we announced the launch of Tourneytopia.com, we've still been very busy tidying things up. We've done builds just about every night since then, and sometimes first thing in the morning if we found a critical issue.
Well, I'm hoping that will slow down now. When we launched, we still had a few minor issues and features we wanted to get done, and tonight, I feel like we've got them all done. Don't get me wrong, there's still things we want to do. But most of that relates to either brand new features or changes to the current features to make it support more than just March Madness. So, given how busy we've been, we've decided to shelve any new features until next year, and put off making it more generic until April.
So, what does that mean? It means we're now feature complete for 2006! I listed out the major new features a while ago, but here's what we've added recently:
- Improved What-If Scenarios: First, what we need to answer exactly what "What-If Scenarios" are. Once the tourney gets to the final four, the scenarios become active. Last year, all we did was show them for that week between the final four being set and when the first final four game was finished. After that, it was disabled again. This year, we still show them, and incorporate the actual results into the scenarios - so you track as the final four and championship games complete which scenarios are still valid, but also see what could have been. By the way, I always fall into the "what could have been" category - there's usually a scenario where I can finish in second or third, but it never comes to pass.
- Licensing can be purchased directly from Tourneytopia.com. You can initialize a purchase directly from the Tourneytopia.com. We aren't completely automated - we still have to add your license once we are notified, but by this weekend, we are hoping to have it completely automated. The good news (if you want to look at it that way!) is that most people don't make their purchase until the week before the tourney starts or the week of the tourney so it shouldn't affect too many people (although, orders are starting to come in!).
- We made a change in how we handle unlicensed entries. Before, if an entry came in and it took you over the number of entries you had licenses for, then that entry was saved, but not visible on the site. That can get confusing for users who don't (and shouldn't have to) know anything about how it's licensed. They wonder what happened to their entry. Well, now they'll be able to find their entry. It just won't be scored or ranked. But users can still see it, and edit it before the tourney starts.
- We also have made quite a few minor UI improvements, including some basic formatting of grids, removal of an unneeded page, and a few others. Nothing major here, but the changes give it a better feel.
So what's coming from Tourneytopia.com? Not much new over the next few weeks. Our focus now is sales and support, and we'll fix bugs as we find them. Then, it'll be time for March Madness - my favorite time of the year!
Categories: Develomatic
Congrats to pwarner!
posted on 03/02/06 at 10:44:44 pm by Joel Ross
Congratulations to pwarner for winning the Second Annual Tourney Logic Match Play Pool Contest. He (yes, I know for sure that pwarner is a male) gained the most points throughout the tournament. We'll be sending out his $25 Best Buy gift certificate soon!
While pwarner won it all, everyone who entered helped us out tremendously, and I want to thank everyone for that! We were able to find quite a few bugs and squash all of them. Fortunately, none of those issues involved any type of data loss - the one that confused?a lot of people was the bracket change that happened at the last minute - the 12th overall person dropped out of the tourney due to a back injury, and numbers 64 through 13 all moved up one slot, throwing the whole bracket out of whack. Luckily, we have a way to edit the bracket, so anyone who was able to get back into their bracket could fix it up. Not that i tprobably made much of a difference - the seeding of this tourney is much less of a factor than it tends to be in March Madness. Anyone can beat just about anyone!
Categories: Develomatic
URL Rewriting And ASP.NET 2.0's Site Navigation
posted on 03/02/06 at 10:37:56 pm by Joel Ross
I'm going to be blogging about Tourney Logic and Tourneytopia a lot in the near future, so be forwarned. It's not because I'm pushing it on you. It's because that's what I'm doing right now. It's actually why I haven't been blogging a lot lately, but I recently ran across a few things that were complex enough that I want to write them down before I forget what I did to fix them.
So, today's post is brought to you by URL Rewriting. Specifically, we installed the Tourney Pool Manager in a subfolder: /Pools. Then we set up a sitemap file, which is based on our files (obviously). Here's a sample of our files: /Pools/Default.aspx, /Pools/SubmitPicks/Picks.aspx, /Pools/Pool/Standings.aspx, etc. You get the idea. But the installation needs to be able to support multiple pools from the same installation. In my mind, there were two logical ways to do this: First, we use querystrings: /Pools/Default.aspx?PoolId=NCAA. Not bad, but which looks better? That, or this; /Pools/NCAA/Default.aspx. That brings us to the second option - URL rewriting.
I found a nice library that provided Regex support. It would basically pull the Pool Id out of the URL and direct you to the correct page. Then, we handle the Application_BeginRequest event, and if the RawUrl and the actual URL are different, we know it was rewritten. We then pull the Pool Id out, and shove it in the Context.Items collection for later use. This is where the fun begins. Some background: We set up our site map based on the actual files, not with the Pool ids. We don't know the pool ids ahead of time, so we had entries in our site map like this: ~/Default.aspx, ~/SubmitPicks/Picks.aspx, ~/Pool/Standings.aspx.
Now to the issues. First, the simple one. If you use the Menu control, by default, the links will be exactly what's in your site map file. So we lose the pool id. We did that for a while, and stored the pool id in a cookie. That's fine, until people are in multiple pools. Or want to send a link to someone else. So we had to include the pool id in the links that were generated. Easy enough. There's an event when each item in the menu is databound. Handle that event, and change the URL to include the pool id, which, since the menu is only in our header and footer, it's all contained in our master page.
The Login control was next. It's roughly the same - except there's no event, so I just handled it's pre-render event, and changed the URLs we added to the template there. There's two for us - the login link itself, and then the account page, which is seen when you're logged in. The logout link is a post back, and we redirect to the RawUrl (which already includes the "pretty" url) once you're logged out.
Now for the tricky one. The breadcrumb. We think it's a nice thing to have on the page, so you can keep track of where you are. Here's the problem we had. Every page has a property on it - Page.SiteMap. It hands controls two things: the RootNode and the CurrentNode. The RootNode works fine because it's not based on where you are. But the CurrentNode is determined by the SiteMapProvider. We're using the XmlSiteMapProvider, and what it does is look at the Request.RawUrl and compare that to the site map file. If it finds a match, then that's the current node. If not, the current node is null.
Well, that presents a problem now, doesn't it? Our RawUrl isn't in the site map - we've got that extra pool id in it. So, for a while, it just wasn't showing up. Once we realized that, it's simply a matter of creating our own SiteMapProvider to handle it for us. Obviously we don't need to create it from scratch, so we inherited from the XmlSiteMapProvider, and just overrode FindSiteMapNode(string rawUrl). We take that raw URL, and remove the pool id from it. That allows the XmlSiteMapProvider to operate as usual. And of course, we had to override the databound event for the breadcrumb to change the URLs written to the page.
Now, some may be asking why we didn't just go further and change the URLs of the SiteMapNodes in a custom provider. Good question. I tried. And tried. And I got it working, but there was a slight problem. ASP.NET only goes back and reads the nodes from web.sitemap when the file is changed or the application is restarted. So if I went in and changed all of the URLs to have a particular pool id in it, then it would screw up all of the other pools. I tried - I even thought I had it working, but then I had URLs with multiple different pool ids in it at the same time. That was a problem. That's why I came up with what I did.
I'm deploying the last changes that fixed a bunch of navigation issues tonight. Most likely, by the time you read this, it'll be out. But if you go there fast enough (or have been there in the past few days), you may have seen that if you are logged in as an admin of a pool, that some pages didn't work. Because of the way I was overriding FindSiteMapNode, something wasn't happening that should have been, and you only noticed it when you were logged in as the pool admin. That's when I changed my override to just pull the pool id out of the rawurl and then check that new URL. All problems solved!
Categories: ASP.NET