I have started a new blog for
Clydesdale Software and all my entries are being moved there. Please change
your rss feeds to point at the
new feed.
I have started a new blog for
Clydesdale Software and all my entries are being moved there. Please change
your rss feeds to point at the
new feed.
I’m a big believer in solid state drives, at least a believer in the concept. The concept I’m referring to is having a stateful storage device with no moving parts, instantaneous seek times, much faster read and write speeds than spindle hard drives while being much more reliable and durable. It is obvious from the above why this would be desirable but are we there yet?
Solid Sate Drive’s are breaking new ground every day. I do not believe the flash
technology that SSD’s are built on now will be the answer for very long. With
the introduction of phase change memory, which is stateful, the flash technology may
go away in SSD’s and this new technology may take over.
If you happen to be doing multilingual work and are looking for good font that contains many languages take a look at Arial Unicode MS.
I found some good
tips on OCZ's site for improving performance with SSD's with Windows Vista which
would also most likely work on Server 2008.
I will be trying these out when I get my new m4400 and throw in my SSD.
DevExpress has a nice little feature in their ASP .NET controls to be able to redirect in an ajax callback. This works just as advertised in IIS 6 but in IIS 7 the ASPxHttpHandlerModule http module needs to be added as a module in the IIS manager.
To add as a module go to IIS 7 Manager ->Your Website->Modules->Add Managed
Module.
mfLY! for Visual Studio allows developers
to build using many patterns, one of which is Model-View-Controller (MVC). In
this post I will focus on how the controllers load views in mfLY!.
One aspect of MVC in mfLY! I want to
point out here is how navigation is handled. In an MVC application it is the
controller that decides what view to load, and mfLY! is
no exception but it does it just a bit different.
In mfLY! there are Workflow Directors
and View Workflows. If it helps think of these as a workflow controller and
view navigation controllers. Workflow Directors are responsible for controlling
navigation between View Workflows. View Workflow’s on the other hand control
navigation between views. So when an application starts it lets the Workflow
Director choose what View Workflow to start and the View Workflow in turn decides
what view to show. Each action (i.e. button click) in the application that is
registered with the View Workflow can trigger the View Workflow to load the next view.
View Workflows allow the developer to encapsulate different feature areas into a workflow.
An example of this may be having one application with an Inventory View Workflow and
an Orders View Workflow. Since views are decoupled from navigation they can
be used across multiple workflows.
The Workflow Director creates each View Workflow on demand, but does have the ability
to create all of the View Workflows at one time.
The View Workflows have a similar creation mechanism. A View workflow can create
views on demand, all at one, or one level ahead. One level ahead means when
a view is loaded the View Workflow analyzes the possible paths and creates all the
views that could be the next view, this way the lag between views is less. In
many cases the best option is to create all the views for the workflow at once since
a user will most likely be working in a feature area for a specific task. Of
course this all depends on how many views are in the View Workflow.
In a future post I will show how to leverage the mfLY! workflow
engine to do business logic and much more.
Recently Clydesdale Software deployed a new site which heavily leverages the sending of emails.
My first approach was to run our own smtp server which in the end turned out to be
a headache with spam and blacklists.
Next, was using the clients existing smtp which they pay a service company for. This
service company only allows so many emails to be sent each hour. So another no go.
The solution, redundant smtp servers and a pay for smtp server. The first attempt
to send an email is done by AuthSmtp. AuthSmtp is
an affordable service which makes it very easy to upgrade and downgrade your service
level that is based on how many emails you send. The second smtp server is the one
the client has that only allows so many emails per hour. And the secret sauce, Advanced
Smtp Server which lets you define multiple smtp gateways and will try each one
in order. It also uses a queue and the messages will be retried to send if a failure
occurs.
Just came across a very annoying bug when migrating from Access to SQL Server.
Access's base date is December 31, 1899 which is represented by the serial number
1. If the existing queries are using the DateValue function this is very important.
SQL Server's base date is January 1, 1900 which is represented by the serial number
0.
So, when migrating from Access to SQL Server and the existing Access queries use DateValue
you may have to do a hack around like I did, create user functions for DateValue and
CDate that add 2 to the serial number.
You may ask, who cares if the float value of the datetime is off. Well, in this case
there are people connecting via excel which also uses the DateValue function and expects
the same base date as Access.
To recap, Access and SQL Server have different base dates and SQL Server is zero based
while Access is one based.
Fun, Fun
After purchasing two consumer grade gigabit switches, the NetGear GS108 and the Linksys
SD2008, and having them both fail I really started to think if gigabit was ready for
the consumer. I would have to say from my experience with consumer grade gigabit switches
that it is definitely not ready for prime time.
The good news is as a consumer you can still have gigabit, you just may pay a little
bit more for it. I would recommend purchasing business class switches. The switches
I'm using are the Dell
PowerConnect 2708 which I'm very impressed with thus far; though it does not take
much to impress me at this point, staying turned on is enough:)
In a previous
post I talked about how I was dd-wrt to route
multiple WAN IPs. Well, ever since that post I have been screwing with it because
it has not been working quite right. I finally figured it out with the help of some
forums out there. Use the below script in the Firewall section under Administration->Commands
to route multiple WAN IP's to internal IPs:
ip addr add [extra wan_ip]/29 dev vlan1
iptables -I FORWARD -d [internal ip] -j ACCEPT
iptables -t nat -I PREROUTING 1 -p all -d [extra wan ip] -j DNAT --to [internal ip]
iptables -t nat -I POSTROUTING 1 -p all -s [internal ip] -j SNAT --to [extra wan ip]
The main piece I was missing was the first line which puts the extra wan ip on the
same vlan as the wan ip the router is using.
Hopefully this will save someone from having to scroll through forum posts looking
for an answer.
So I decided to make the switch, yes I have gone over to the Mac side. Since I do
all my work anyway in virtual machines my host OS just needs to be a thin layer that
allows me to check email, write blog posts, surf the web, etc. Well, OS X fits the
bill and it uses considerably less memory than Vista. My virtual machines running
VMWare Fusion seems to run faster as well.
One of the things I love about OS X is stuff just works! Example, needed to add my
network printer; OS X already found the printer and I just had to make it my default.
If I want to get into the guts of things I just open a bash terminal and I'm on my
way.
Many software vendors are now offering versions of their products for Macs that it
has not been an issues thus far finding the software I need. I'm also starting to
look at the Xcode environment and exploring how to build software for Mac's. A new
year a new challenge. Now don't get me wrong, I spend a lot of time on the .NET side
of things and that is not going to change but every once in a while I need something
different.
Live in a Mac, work in Windows!
So I'm in the process of switching my main computer over to being a MacBook Pro. I
work on VMs all the time and my other windows laptops/desktops are running VMWare
Workstation so the natural choice for my new Mac was VMWare
Fusion.
VMWare Fusion seemed to work
flawlessly at first but then I ran into an issue using GoDiagram. GoDiagram would
not paint correctly, it would create a window effect where I would see what was behind
it (like looking through a window). My first thought was it must be a buffering problem
so I googled around and found nothing. It turns out the solution is simple, going
to Virtual Machine->Settings->Display and check Accelerate
3D graphics solved the issue.
The Big
Event is coming to Denver on Thursday January 31st. What is it,
well here is a summary.
Hope to see you there!
I’m making the switch to Jetbrains
Team City. For years I have used Cruise Control .NET and I consider myself
pretty knowledgeable in the workings of it. I can say hands down that I
can get a new build machine up running quicker using Team City (which I do not know
too much about) than using CC.NET.
Team City walks you through the configuration which then points at your build
file. It also has a nice little feature for displaying build outputs
on the web site which is useful for nightly build outputs. There is Visual Studio
integration so if you want to run a personal build all you have to do is click a button
in Visual Studio. If the personal build passes then the code is checked in,
otherwise the errors need to be fixed.
Did I mention there is a free version which is what I’m using!
We are excited to announce the newest member of our
family, Chloe Luif. She made her appearance at 8:09am on January 17 and weighed
in at 7 lbs and is 20 inches long. Mom and Dad are doing well and baby is enjoying
long naps.
The other day I was automating some IIS routines such as creating and editing application
pools. I found that the user and password for the application pool can be retrieved
in plain text very easily using the code below.
string serverName = Environment.MachineName;
DirectoryEntry appPools =
new DirectoryEntry(string.Format("IIS://{0}/W3SVC/AppPools",
serverName));
appPools.RefreshCache();
foreach (DirectoryEntry entry in appPools.Children)
{
Console.WriteLine(
"User:
" + entry.Properties["WAMUserName"].Value
+
"
Password: " + entry.Properties["WAMUserPass"].Value);
The above sample is going against IIS6. The moral of the story is watch what
user you use for IIS app pools.
So I decided to buy another m1330, but this time upgrade a bit. I went for the
64GB solid state drive and the LED display.
The solid state drive is awesome, it boots up a full 15 seconds faster than my other
m1330. Finally I have a laptop that can run VM’s at a decent speed off
of the internal hard drive. I also installed 64 bit Vista so now I have
4 gigs of ram which is nice. Installing 64 bit Vista was an interesting task,
but in the end I have everything working except the fingerprint reader application.
At first I really did not notice a difference with the LED screen but after using
it for a while and then looking at the regular screen on my other m1330 I really noticed
a difference. It seems much easier on my eyes.
There was a great comment on my last post about the HDMI output. If you right
click on the volume control in the system tray and choose playback devices you can
choose HDMI for audio output.
I can’t believe it took this long to get a better way to manage users and groups
through code!
There is a new namespace in .NET 3.5 System.DirectoryServices.AccountManagement which
allows easy management of users and groups via code.
Below shows how easy it is to get the local IIS_WPG group:
PrincipalContext context = new PrincipalContext(ContextType.Machine);
GroupPrincipal iisWpgGroup = GroupPrincipal.FindByIdentity(context, IdentityType.Name,
"IIS_WPG")
It used to difficult to even find if a user was a member of a group.
Now there is a “Contains” on the group and there is also LINQ
which is what I used.
var addedUser = iisWpgGroup.Members.SingleOrDefault(principal => principal.SamAccountName
== "User1");
The above will return the member if they are there or null if the member is not in
the group. It is also stupid simple to add and remove members from a group.
Add Local:
iisWpgGroup.Members.Add(context, IdentityType.Name, “User1”);
iisWpgGroup.Save();
Add Domain:
PrincipalContext domainContext = new PrincipalContext(ContextType.Domain,
domain);
iisWpgGroup.Members.Add(domainContext, IdentityType.SamAccountName, “User1”);
iisWpgGroup.Save();
Remove:
var user = iisWpgGroup.Members.SingleOrDefault(p => p.SamAccountName
== “User1”);
if (user != null)
{
iisWpgGroup.Members.Remove(user);
iisWpgGroup.Save();
}