Refactor rename on LINQ to SQL Classes 2

This is a quick, dirty work around to renaming the properties of the LINQ to SQL classes. Say you have a simple DBML class you want to rename.

image

Simple enough right? Just click in there and edit the WidgetName to Name right? Wrong! You have code like this.

public Widget CreateNewWidget(string name, string description)
{
    return new Widget {
        WidgetDescription = description,
        WidgetName = name
    };
}

You’re going to abandon all those calls to WidgetName and do a search and replace refactor. That sucks. So rename it to WidgetName2 for now and let all the references break.

image

That breaks our code.

image

Fine for now. Create a partial class for the Widget.cs and add our WidgetName back in

public partial class Widget
{
    public string WidgetName { get; set; }
}

Use ReSharper to rename that property to name.

image

Then delete the partial class, or property and rename the property in the DBML to Name.

Done.

Visual Studio 2010 Cassini / IIS Deltas 0

We’ve recently upgraded to the shiny new Visual Studio 2010 Beta 2. With the go live license we hope we can transition to the RTM once it drops. It has some nice features everyone already knows about.

First step to the future, the conversion. The conversion went pretty smooth. It doesn’t like the MVC 1.0 project, but that’s OK since it was just a shell placeholder. We plan on converting that to the MVC 2.0 before we get any real work in there.

After fixing a few minor things the conversion wizard missed, we fire up the app in Cassini….and it looks awful.image

OK, well maybe it doesn’t look awful, but it doesn’t look how our talented designers want it to look. It is mostly there. That bottom block should appear to the right of the login. Fire up the same VS 2010 project in IIS and it looks fine. image

Weird huh? Looking at the HTML there are a few differences between the two, but none that we would really expect to cause the two to render differently. Some URL’s were changed to absolute URL’s and include the hostname and port of each site. There are some view state differences, but nothing else.  Hmm…Why don’t we just stop using Cassini and debug through IIS.

There were just a few steps needed to set that up. First, tell Visual Studio to use a different server besides the development server.

image

Here we’ve already setup a host header IIS site and added dev.mysite.localhost do the hosts file. We have a hybrid of ASP.Net and classic ASP, so we already used ISS for a lot of testing.

Second step, run Visual Studio as administrator. You can default the shortcut to always run as administrator by editing the advanced properties of the shortcut.

image

That’s it. It looks like Visual Studio automatically attaches to the IIS process. The best part; It is a worlds faster than Cassini. I don’t know why you would debug through Cassini, unless you had to because you were missing either administrator privileges or missing IIS with your Home version of Windows.

Animating Partial Postbacks and UpdatePanels with jQuery 4

Update panels make it really easy to do pseudo ajaxish stuff with little or no extra effort. Wrap your controls in a an UpdatePanel, pay for the entire page to post back and go through its life-cycle and you’re pretty much there. I’ve already written a bit on the extra steps you’ll need if you’re doing some jQuery magic inside that UpdatePanel. It’s not difficult and easy enough to either delegate up the chain to something outside the UpdatePanel (e.g. event delegation) or rinse and repeat the jQuery after the partial post back is complete (e.g. add_endRequest).

What would be really slick-o-matic is if we could do some animation to transition the partial postback so it wouldn’t just explode with new content in our face. Now granted, that may be an overstatement. The content changes usually aren’t drastic or very distracting to but let’s add a bit of polish.

Keep in mind this is a first draft, done in about 30 minutes after an idea landed in my head at 3am. It still needs some polishing, but the major hurdles are taken care of.

For our example, we’ll have a simple Div that will be worked upon in a partial postback. Our goal will be to gently transition the display of that work to the user. Something like this.

Original Video – More videos at TinyPic

We’ll start off with some basic styles to help illustrate the change. We’ll change the content of the Div and also the class.

	#mydiv{ width:200px; border:solid 1px black; font-size:xx-large; }
	.myclass0 { height:200px; background-color:Blue; }
	.myclass1 { height:100px; background-color:Red; }
	.myclass2 { height:150px; background-color:Lime; }
	.myclass3 { height:50px; background-color:Purple; color:White; }

Nothing too exciting, but our partial postback will give us some new dimensions and style. It’ll get the point across.

Next we need some HTML.

<form id="form1" runat="server">
	<asp:ScriptManager ID="ScriptManager1" runat="server">
	</asp:ScriptManager>
	<div>
		Original time: <%= DateTime.Now.ToLongTimeString() %> 
		<asp:UpdatePanel ID="UpdatePanel1" runat="server">
			<ContentTemplate>
				<asp:Button runat="server" Text="Button" ID="MyButton"
						OnClick="MyButtonClick"
					OnClientClick="return ClientClick(this,'#mydiv'); " />
				<div id="mydiv" runat="server">
					<asp:Label runat="server" Text="Label"
                                           ID="MyLabel"></asp:Label>
				</div>
			</ContentTemplate>
		</asp:UpdatePanel>
	</div>
</form>

The magic is going to live in the ClientClick event handler, but forget about that for now. The server side OnClick event will do some trivial work.

 protected void MyButtonClick(object sender, EventArgs e)
 {
	 MyLabel.Text = DateTime.Now.ToLongTimeString();
	 var c = "myclass" + DateTime.Now.Millisecond % 4;
	 mydiv.Attributes.Add("class",c);
 }

This could just as easily toggled a view from edit mode to read-only, expanded a detailed area, etc. Here, we are just picking one of four css classese to use on the div and also giving a label the current time. Like I said this isn’t the cool part.

The final steps are to do the following:

  • Get the jQuery animation to happen on the click of the button.
  • Get the partial postback to wait until the animation is done.
  • Get the DOM to appear in the pre-animation state when it comes back from the partial postback.
  • Get the animation to happen once we have the new page ready to go.

The function needs to know what needs to be animated upon. I’ve been using slide transitions, but the animation is something I think can very easily be abstracted out. We make some quick tests to see if we are in the process of animating or if the animation has been completed. I struggled with how to delay the button click’s post back from happening until the animation is complete and finally decided to just let it happen a second time, but to flag the second click to allow it to continue posting back. I’m using the jQuery data feature to keep some state about the button.

If we are currently sliding, then there is nothing left to do, and if we are done sliding then we can skip the other steps and continue the postback.

if (d.data("isSliding")) return false;
if (d.data("doneSliding")) return true;

If we don’t meet those conditions, we need to slide. We set our flag, wire up the end request handler and the callback to the slide method and kick off the slide.

The slide method is the simplest.

d.slideUp(500,
	function() {
		d.data("isSliding", false);
		d.data("doneSliding", true);
		$(sender).click();
	});

Slide our control up, and when we’re done, set some flags and kick off the click a second time. With the flags set, we’ll fire off the postback. Nothing really fancy here either. Notice we can still reference d here. We don’t need to find it again.

The endRequest handler looks a bit more involved.

var prm = Sys.WebForms.PageRequestManager.getInstance();

var f = function(s, e) {
	d = $(whatToSlideDown);
	d.css("display", "none");
	d.slideUp(0);
	d.slideDown(500);
	prm.remove_endRequest(f);
}

prm.add_endRequest(f);

Here, inside the function we do need to ask jQuery to find what we want again. The DOM has been changed and the old d we created from $(whatToSlideUp) probably isn’t there anymore. In addition, we need to set the element in the state we left the old element. In this case, we want the display to be set to “none”. This allows the slideDown to work just like we would expect following a slideUp.

This is part of the setup that I don’t like. I’ve tried quickly running a slideUp(0) on the the new elements, but I was seeing a flash of the default state before getting the slide up. This is something that I would like to factor out. The animation, including this default state should be a parameter to the function.

Here is a look at the function as a whole. It’s a stupid function name I know, but that is easily changed.

function ClientClick(sender,whatToSlideUp,whatToSlideDown) {

	if (!whatToSlideDown)
		whatToSlideDown = whatToSlideUp;

	var d = $(whatToSlideUp);

	if (d.data("isSliding")) return false;
	if (d.data("doneSliding")) return true;

	d.data("isSliding", true);

	var prm = Sys.WebForms.PageRequestManager.getInstance();

	var f = function(s, e) {
		d = $(whatToSlideDown);
		d.css("display", "none");
		d.slideUp(0);
		d.slideDown(500);
		prm.remove_endRequest(f);
	}

	prm.add_endRequest(f);

	d.slideUp(500,
		function() {
			d.data("isSliding", false);
			d.data("doneSliding", true);
			$(sender).click();
		});
	return false;
}

That’s it. There is definitely room to polish this up and make it more flexible. I’ll post back when I get it up and running in a real application so it looks more useful.

Asp.Net and forcing password change after PasswordRecovery 0

Like many websites, we implemented a feature that will let our users self recover lost or forgottton passwords.  Asp.Net provides this right out of the box with the PasswordRecovery control.  It took us 90% of the way to where we want to be. It verifies the account exists, generates a random password and mails it to user.  The last step we wanted was to force the user to change their password after they’ve requested a new on from the PasswordRecovery control. Turns out, it wasn’t that bad.

We created a new profile property for our user to track if we were requiring a password change on the next login.

 <profile>
   <properties>
     <add name="RequirePasswordChange" type="System.Boolean" allowAnonymous="false"/>
   </properties>
 </profile>

We already had our ForgotPassword.aspx page with our PasswordRecovery control on it. We just needed to write up one more event.

<asp:PasswordRecovery ID="PasswordRecovery1" runat="server"
     OnSendingMail="SendingMail" >
 </asp:PasswordRecovery>

In the new event we’ll set that flag so we know the next time they successfully log in, we’ll make them change their password. I didn’t really see any other event that was more appropriate than SendingMail, but since we only send the e-mail when we pass all the challenges we’ve setup, it works well enough.

Also, since we’re not logged in, we have to ask for the profile by name, and then make the change.

protected void SendingMail(object sender, MailMessageEventArgs e)
{
    var p = Profile.GetProfile(PasswordRecovery1.UserName);
    p.RequirePasswordChange = true;
    p.Save();
}

The login page has some code added after we login.

<asp:Login ID="Login1" runat="server" OnLoggedIn="LoggedIn">
</asp:Login>

If we require the password change, then redirect to the new page.

protected void LoggedIn(object sender, EventArgs e)
{
    if (Profile.GetProfile(Login1.UserName).RequirePasswordChange)
        Response.Redirect("ChangePassword.aspx");
}

Lastly, ChangePassword.aspx resets the flag on successful login.

<asp:ChangePassword ID="ChangePassword1" runat="server"
    OnChangedPassword="ChangedPassword">
</asp:ChangePassword>
protected void ChangedPassword(object sender, EventArgs e)
{
    Profile.RequirePasswordChange = false;
    Profile.Save();
}

That’s it.

Git Extensions and Visual Studio 6

With the Git extensions you get some nice Visual Studio integration. You get a nice menu and toolbar to work some of your Git magic right from the IDE.
ss-20090215112020

One Click Lorem Ipsum 0

I’m working on layout of new HTML pages and have been adding the Lorem Ipsum filler time and time again. At first I just get a browser window with it open, copy and pasted it whenever I needed, but in keeping the desktop clean of clutter, the browser window was often closed, causing me to search for it, select it, copy, etc. So here’s how to save you time:

  1. Create a toolbox tab for common text.
  2. Select Lorem Ipsum from a file in Visual Studio.
  3. Drag the text to the toolbar.
  4. Done.

Now when you want to inject the lorem ipsum into the text, just click it on the toolbox item.

Even better, for the ReSharper users, make “lorem” a live template for the entire text. Then you just type “lorem” + tab and you get the entire passage.

Replacing TFS Diff Tool 5

The TFS diff tool is horrible. It a pretty bare minimum difference between the two versions. The UI is basic.

image

Nice huh? This line changed, but you’re on your own to know what characters actually changed. While tooling around in the Visual Studio Options dialog I can across the settings that would let me change the diff and merge tools.Check out Tools | Options | Source Control | Visual Studio Team Foundation | Configure User Tools…

image

I needed a another diff tool, so I downloaded a trial of Beyond Compare and plugged it in there and it worked great! Except, in 15 days it wouldn’t be working so great unless I could convince someone to shell out the $X to get us past the trial. After pinging some of my buddies about what diff tools they use, I decided to try the diff tool in TortoiseSVN. I installed it and added TortoiseMerge to the dialog.

image

Ran my compare again and Bang! A new diff dialog appears that is much better than before.

image

That is still a lot of redundant clutter for me, so switching views helps a little with that.

image

We no longer get the detail about what changed on a line, but it is so much easier to manually identify when the rows overlap, I’m not missing it.