Archive

Archive for the ‘Visual Studio 2005’ Category

A Flexible “Is In Range” Extension Method

I’m working out some business rules for an application that allows the end user to specify whether or not to direct records by the first letter of the last name of a student or by the grade of the student.

The quick extension method looks like this:

public static bool IsInRange<T>(this T value, T start, T end)

where T: IComparable<T>

{

return value.CompareTo(start) >= 0 && value.CompareTo(end) <= 0;

}

Our tests:

[Fact]

public void IsInRange_returns_correct_boolean_for_comparison()

{

9.IsInRange(1, 10).ShouldBeTrue();

“L”.IsInRange(“A”, “J”).ShouldBeFalse();

“A”.IsInRange(“A”, “A”).ShouldBeTrue();

“B”.IsInRange(“A”, “A”).ShouldBeFalse();

12302.IsInRange(1, 10).ShouldBeFalse();

 

“Bob”.IsInRange(“A”, “A”).ShouldBeFalse();

“Smith”.IsInRange(“A”, “Z”).ShouldBeTrue();

}

Everything works well… I haven’t tested all of the permutations and types yet… but it gets me out of the jam I’m in right now.

Is there a better way? ๐Ÿ˜€

Auto Incrementing Visual Studio Project Versions

March 9, 2009 Comments off

I’m not using NAnt or anything fancy for most of my projects—so I needed a simple, MSBuild way to automate my version numbers in a project..

<tangent>
HOLY CRAP! Why isn’t this built into Visual Studio Pro?
</tangent>

Here we go:

1. Download the latest build of AssemblyInfoTask (download here) (was 1.0.51130.0 for me).  This is a semi-Microsoft supported MSBuild task that gives you a lot of flexibility over your AssemblyInfo.cs files.

2. Install AssemblyInfoTask.  When prompted where—install into the GAC.  If you don’t have access to the GAC on your workstation, then why aren’t you developing on a VM? ๐Ÿ˜‰

3. Locate the Microsoft.VersionNumber.targets file.  If you installed to the GAC, it should be at %ProgramFiles(x86)%\MSBuild\Microsoft\AssemblyInfoTask Or %ProgramFiles%\MSBuild\Microsoft\AssemblyInfoTask (depending on your architecture).

4. Copy the Microsoft.VersionNumber.targets file into a location in your solution or project.  I recommend $(SolutionDir) so you can share it amongst all of your projects.  The guilde recommend pointing to the file directly; however, you can’t modify the base Major versions that way (without setting the same major version for ALL projects you ever work on).  You can also rename it as approprate.

“Int16s Are Too Small” Or “Why 2007 Broke Versioning” Fix

According to experts who are much smarter than me, the build version numbers are Int16s—meaning 65535 caps out the number.  Unfortunately, the year 2007 breaks this (070101 or 70101 for 07 jan 01) doesn’t fit within an Int16.  Stellar.

The MSBuild team recommended taking out the year and simply placing a 1 infront of it.  That works; however, I really like having the year in there somewhere.

For me, I’ve placed the year into the MinorVersion.  After reviewing most of our practices, the minor version for most of our projects changes with annual maintenance OR not at all (we bump the major version).  This, if nothing else, will help standardize when it changes. ๐Ÿ™‚  As always, YMMV.

No matter which solution you choose, you’ll need to remove the year from the BuildNumberFormats.

In your Targets file, you can change the two lines to report out the MMdd (0309, for example, today) to work around the bug.  I’ve bolded the two lines below.  As you can see, I also added the “9” to the MinorVersion to represent 2009. 

<PropertyGroup>

  <AssemblyMajorVersion>3</AssemblyMajorVersion>

  <AssemblyMinorVersion>9</AssemblyMinorVersion>

  <AssemblyBuildNumber></AssemblyBuildNumber>

  <AssemblyRevision></AssemblyRevision>

  <AssemblyBuildNumberType>DateString</AssemblyBuildNumberType>

  <AssemblyBuildNumberFormat>MMdd</AssemblyBuildNumberFormat>

  <AssemblyRevisionType>AutoIncrement</AssemblyRevisionType>

  <AssemblyRevisionFormat>00</AssemblyRevisionFormat>

</PropertyGroup>

 

<!– Properties for controlling the Assembly File Version –>

<PropertyGroup>

  <AssemblyFileMajorVersion>3</AssemblyFileMajorVersion>

  <AssemblyFileMinorVersion>9</AssemblyFileMinorVersion>

  <AssemblyFileBuildNumber></AssemblyFileBuildNumber>

  <AssemblyFileRevision></AssemblyFileRevision>

  <AssemblyFileBuildNumberType>DateString</AssemblyFileBuildNumberType>

  <AssemblyFileBuildNumberFormat>MMdd</AssemblyFileBuildNumberFormat>

  <AssemblyFileRevisionType>AutoIncrement</AssemblyFileRevisionType>

  <AssemblyFileRevisionFormat>00</AssemblyFileRevisionFormat>

</PropertyGroup>

 

This results in a version string that looks like 3.9.0309.{increment}.

5. Open up your project’s solution and unload the project you are wanting to auto-increment. Towards the end of the file, you’ll see the default MSBuild C# build path; add the location to your new .targets file in your solution directory.

<Import Project=$(SolutionDir)MyProject.VersionNumber.targets />

7. Save and Close and Reload the project.

8. Build/Rebuild your project and the AssemblyInfo.cs should set to the specified increment scheme.

You’re done!

“Too Many WebResources?” Fix 

My project references numerous resources for images and style sheets; however, having these inside of AssemblyInfo.cs seems to cause it to go haywire and throw array errors (assumingly because there is more than one [assembly:WebResource()] call).

To fix this, I moved my WebResources out of AssemblyInfo.cs and into a new file under Properties called WebResources (Add New Item > Assembly Information File).  Strip out everything except the WebResources you copy in and the project now compiles like a champ.

For additional setup details and options within the .targets files, the AssemblyInfoTask installer comes with a CHM help file that covers additional customizations available.

HTML Formatting and Spacing in ActiveReports

March 6, 2009 1 comment

ActiveReport’s RichTextBox is great for presenting HTML-styled content on PDF reports; however, there seems to be a snag with a few of the HTML tags and how the RichTextBox translates the commands to HTML.

To print out a bit of HTML (from a field), I have the following StringBuilder my details_Format:

builder

       .AppendFormat(

       @”{0}On {1}, <strong>{2}</strong> wrote: <br/>{3}<br/><br/>{4}”,

       […]);

However, the <strong> tags are not properly rendering spaces between them:

Issues with Spacing

There seems to be an existing notice on the DataDynamics forums (here) regarding the spacing, but it’s from 2007–-I’d assume it’s been fixed by now; however, I can’t find it in any of the AR3.0 release notes.

So what’s the fix?

Force the spaces in with non-breaking space commands.

       @”{0}On {1},&nbsp;<strong>{2}</strong>&nbsp;wrote: <br/>{3}<br/><br/>{4}”,

Bingo!

Fix With Spacing

Setting the ViewPort for iPhone/iTouch Ready Web Sites

January 13, 2009 Comments off

Scenario:

After rolling out two new web applications targeted for WindowsMobile and Blackberries, we had a request to test and support Apple iPhone/iTouch devices.  Not a big deal, or so I thought.

Unfortunately, Safari on these devices displayed properly, but every page required zooming and was almost impossible to read.  There had to be a way to get Safari to respect the set width of the page rather than scale it out.

Solution:

Michael: “are you setting the viewport?”

Thanks to Google and a bit of help from a friend (thanks Michael!), the mysterious solution was just a meta tag away.  The best place to start would be the “Safari Web Content Guide for iPhone OS”.  I had found bits of this document elsewhere, but the information about the Viewport tags are extremely helpful.

The default viewport width is 980px; however, you can hard code the width of your page.  I placed the following tag in the <head> section of my MasterPage for the mobile site.

<!– meta tag for iPhone/iTouch devices –>

<meta name=”viewport” content=”width=350px” />

That worked; however, the HTML elements (buttons, selects, etc) were still far too small.  It seems that “fit to device” is more explicitly expressed with the device-width value.

<!– meta tag for iPhone/iTouch devices –>

<meta name=”viewport” content=”width=device-width” />

device-width not only fit the text to the screen, but also properly scaled the elements as well.

Excellent. ๐Ÿ™‚

I need to fully read that Safari Web Content Guide to see if there are other wonky tags for iDevice goodness. ๐Ÿ˜‰

Review: ANTS Profiler 4.0 Beta

August 11, 2008 2 comments

A few months ago, I purchased ANTS Profiler 3.2 and have loved it.  It’s really helped me dig into some of my code, find performance hang-ups, and (I think) turn out better code and learn (it’s sometimes hard to find “do betters” in a single dev environment).

I played around with a few of the 4.0 builds and they were nice, but I honestly didn’t have time to dig into them.After a busy weekend, I sat down and spent some quality time with the 4.0 beta (b 4.0.0.740) of ANTS Profiler and am blown away.

Installation

Installation was a breeze.  The 4.0 installer saw my existing 3.2 install and “upgraded” it; however, I was a bit surprised to find that the 3.2 sat side-by-side with 4.0.  That’s PERFECT, actually, and I hope they plan to keep it that way.

ANTS 4.0 -- Installed!

First Run Through 4.0

I’d like to start off by saying the new profiler startup UI is fantastic.  The prior “multi-step” wizard was great and easy to work through; however, I really like seeing everything on the first page.  Simply set the options and click Start. 

Profiler Settings - click for full image
(click for full image)

In addition, the quick access to additional performance counters, such as page requests and memory usage is really helpful.  I’m curious if additional performance counters can be added or if the list (see below) is the only ones handled by ANTS. 

Once things are rolling, the results come pouring in.  Just like with 3.2, 4.0 has detailed line level data—percentages per called line, hits, etc.  Very useful information.

However, the new call trees are sweet!  Why look at spreadsheets and lines when a graphical representation is available?  I have to find ways to boggle coworkers with these. ๐Ÿ™‚

My understanding is (I haven’t RTFM’d yet) is that the call trees display both your code (those that are bolded) and the managed code from .NET and called libraries (those that are tinted).

From here, I can see that a good deal of my slow down querying AD is coming not from the top level code, but from the Ldap code in System.DirectoryServices.Protocols and that the wait caused by that is the biggest hold up in all of Session_Start.

Another cool feature is the live performance counter view while you’re profiling.  This perfmon look into your application’s performance allows you to pause and checkout spikes (or unexpected dips) in any of the locked counters.

Counters graph.

To see the line-by-line details, simply drag the mouse along a section of the graph to select it.  ANTS will zoom in on just that area.  You can see the “highlighted” area below in blue.

Line Graphs, Zoomed In

That spike can be diagnosed in the line view—one of our methods is that doesn’t call very often (42 times) is taking a HUGE amount of time due to another that is calling 1000+ times.  Time to drill into that code and find a way to unloop it.

Conclusion

ANTS 4.0 seems quite a bit faster than 3.2 profiling the couple of .NET 3.5 web projects that I had sitting around in development.  In the past, I tended to avoid running ANTS against local Cassini projects; however, this kept up pretty well (though I think it does explain the LdapConnection latency).

It also appears that 4.0 can profile remote IIS instances (at least it doesn’t refuse it like 3.2 does); however, I haven’t quite gotten that working with the port settings (more to learn).

I haven’t hit all of the features yet, but I’m very impressed with the new look and feel, added “while you profile” live features, and the call trees. I can’t wait for the next beta and/or gold release—it’s looking good!

Resharper 4.0.1 Beta Released

August 4, 2008 Comments off

Since the 4.0 release, the JetBrains team has been working diligently towards the 4.0.1 release.  According to Confluence, there are several hundred bug fixes between 4.0 diamond and the current build (#917) of 4.0.1.

What’s new with 4.0.1?  According to a newsgroup post from Ilya, the 4.0.1 updates revolve around bugfixes; I haven’t found any indication of additional features.  I haven’t scanned through all of the JIRA cases yet, but there’s a huge volume of “fixes”—which surprises me.  R# 4.0 has been running like a dream for me.

I’m installing 4.0.1 beta (marked “works here”) now; the joys of testing!

IQueryable Methods on ActiveReports ControlCollections

I’m currently working on a project with an extremely complex, multi-page report.  Unfortunately, a customer requirement was EXACT typography to the “Excel” report and there are hundreds (literally) of data points randomly on the page. 

There isn’t a good way to iterate through the results (it’s a very detailed grade card for elementary students) and still match the layout requirements.

So, I went about “drawing” it out—lots of Label controls, lines, boxes, and such.  To save myself a bit of time assigning DataFields, querying results, etc., I opted for a different kind of iteration—control iteration.

My schema was simple: q#i#, for the quarter and the primary data point of the report, the indicator Id.  Since my business object, a Report, was already assigned to the ActiveReport document, I could simply iterate away!

Unfortunately, if you try to determine if the detail.Controls (a ControlCollection) contains a control and it doesn’t exist—it doesn’t simply return null, it throws an exception.  In addition, the ControlCollection doesn’t have an Exists or a FindControl method.  So, you’re stuck catching exceptions.

foreach (var indicator in _indicators)

{

try

{

var indicatorHeader =

string.Format(“i{0}”, indicator.Id);

((Label)detail.Controls[indicatorHeader]).Text =

IsSpanish                                                                           

? indicator.SpanishText                                                                          : indicator.EnglishText;

}

catch (Exception)

{

continue;

}

}

Unfortunately, that destroys performance—especially with hundreds of iterations (of indicators).

There’s a way around this, at least in my opinion.  Instead of addressing the controls as part of the details.Controls ControlCollection, use a custom IQueryable collection.

Begin by adding a private variable to the report to hold the controls.  In my case, all of the controls I’ll be modifying are Label (of ARControl) controls.

private IQueryable<Label> _controls;

On my ReportStart (I’m sure I could use another method, but since these are static controls, that seemed a good place to start), dump all Label controls into a generic List object (because you cannot add into an IQueryable).

var controlList = new List<Label>();

foreach (var control in detail.Controls.OfType<Label>())

{

controlList.Add(control);

}

_controls = controlList.AsQueryable();

OR, if you want to get fancy and save a few objects:

_controls = detail.Controls.OfType<Label>().AsQueryable();

At this point, your _controls object has all of the standard LINQ goodness.  Our foreach now looks like:

foreach (var indicator in _indicators)

{

var indicatorHeader =

string.Format(“i{0}”, indicator.Id);

var indicatorControl =

_controls.SingleOrDefault(x => x.Name == indicatorHeader);

if (indicatorControl != null)

       {

              indicatorControl.Text = IsSpanish

? indicator.SpanishText

: indicator.EnglishText;

}

}

The entire block can be wrapped in a try/catch—rather than each “object check”.  The report also runs almost 100x faster.

IE6 Causes Z-Index Nightmares…

Rather than update the post from yesterday, this chaos deserves it’s own post.

Yesterday, I discussed layering Modal Popup Extenders with the Update Progress controls.  In IE7, FF3, and, well, most everything except IE6, it works like a champ as-is.

The “bug”?  After quite a bit of research, the problem revolves around the following issues:

  • lack of support for the { position: fixed } property,
  • lack of support for the { right; bottom} properties,
  • … unreliable suport for {height: 100%, width: 100% } properties,
  • general pain and suffering
  • <SELECT> tags (or ASP:DropDownList objects) exist above any other z-index,

I’m sure there were other issues.  Really.

After spending a good part of the day trying code, looking it up on QuirksMode, and trying again, I have somewhat of a solution; however, I still greatly dislike how it works in IE6.

On the MasterPage, I have a single UpdateProgress that isn’t associated to a specific UpdatePanel.  Therefore, it’ll catch all Async postbacks (and I only have ONE UpdateProgress control).

<asp:UpdateProgress

runat=”server” DisplayAfter=”100″ ID=”UpdateProgress”>

<ProgressTemplate>

<div class=”UpdateProgressModalBackground”></div>

<div class=”UpdateProgressPanel”>

<h3>Please wait…</h3>

<img src=”Images/ajaxbar.gif”
alt=”Please wait…”

style=”text-align: center; width: 100%; height: 10px; />

</div>

</ProgressTemplate>

</asp:UpdateProgress>

This, again, references our UpdateProgressModalBackground and UpdateProgressPanel styles.  These two styles are unchanged from the post yesterday.  Here they are again for reference:

/* UpdateProgressPanel is above EVERYTHING ELSE,

even other modal popups */

.UpdateProgressPanel

{

       z-index: 99999999;

       background-color:#fff;

       color:#fff;

       width: 200px;

       text-align: center;

       vertical-align: middle;

       position: fixed;

       bottom: 50%;

       left: 45%;

       padding: 10px;

       border: solid 2px #5D7B9D;

}

 

.UpdateProgressModalBackground

{

    z-index: 99999998;

    background-color: #6D7B8D;

    position: fixed;

    top: 0;

    left: 0;

    height: 100%;

    width: 100%;

    min-height: 100%;

    min-width: 100%;

    filter: alpha(opacity=50);

    opacity: 0.5;

    -moz-opacity: 0.5;

}

The UpdateProgress and these two classes work just fine in IE7+, FF2+.  So, now to fix IE6..

So, what’s the difference in IE6?  Well, we can’t use the positioning attributes in the above classes–-they won’t work properly. 

Issue #1 – Fitting the Popup and Background Without Positioning Attributes

Searching the web, I found an article by Damien White discussing his his same pains with this.  His solution involved using the IE-specific CSS “expressions” to calculate the height and width of the window.

height:

expression(

        document.documentElement.scrollTop +

        document.documentElement.clientHeight + “px”);

 

width: expression(document.body.clientWidth + “px”);

However, at least for me, Damien’s expressions wouldn’t handle scrolling down the page.

Damien explains:

The thinking behind this was to take the window height (which document.documentElement.clientHeight gives us) and then add the scroll top position, which will give us the upper portion if the user scrolls up.  The problem shows itself when the user scrolls down; that area is not covered.  The good thing about this is that I didn’t need to mess with the body height, but the solution isn’t optimal in the long haul.

That’s a bad deal because that’s the whole point!  Reading a bit more, there was a comment from Kunal Mukherjee on Damien’s post that solved the problem.

Kunal’s expressions looked at the scrollHeight of the window as compared to the offsetHeight and returned the larger.

height: expression(

document.body.scrollHeight > document.body.offsetHeight
? document.body.scrollHeight
: document.body.offsetHeight + ‘px’ )
;

Actually, that works really well. Cool.

Finally, I’d recommend, as Damien did, breaking out your CSS into two files—one for “IE6” and one for everyone else.  This is easily done using the IE-specific conditional statements.

<!–[if lt IE 7]>
<link rel=”stylesheet” type=”text/css” href=”App_Themes/ie6/ie6.css” />
<![endif]–>

I also included !important flags on each of the properties in the ie6.css file—just to be safe.

Issue #2 – IE6 Pushes <SELECT> tags above everything else…

This is where the solution gets dicey; however, I’m relying on Kunal’s solution again.  In his comment, he pointed out a way to hide <SELECT> tags in IE6 without causing the disappearing act that the ModalPopupExtender causes—cover them with an IFRAME.

To me, this hack seems… sketchy at best, but it works.

In the ProgressTemplate of the UpdateProgress control, add in the IFRAME.

<iframe id=”UpdateProgressHideSelect”></iframe>

In the default.css (or the non-ie6.css, whatever you’ve called it), I recommend setting the iframe’s style to {display: none}—it isn’t needed outside IE6, don’t render it. ๐Ÿ™‚

On the ie6.css, add the UpdateProgressHideSelect in—along with another expression to place the iframe over the entire page (like the standard BackgroundCssClass of a ModalPopupExtender):

#UpdateProgressHideSelect

{

    z-index: 15000;

    position: fixed;

    top: 0;

    left: 0;

    background-color: #fff;

    border: none;

    filter: alpha(opacity=0);

    -moz-opacity: 0;

    opacity: 0;

    height: 100%;

    width: 100%;

    display: inline !important;

}

 

* html #UpdateProgressHideSelect

{

    position: absolute;

    height: expression(

document.body.scrollHeight > document.body.offsetHeight

? document.body.scrollHeight

: document.body.offsetHeight + ‘px’);

}

The z-index of 15000 for the iframe ensures that it appears above the normal 10000 of a ModalPopupExtender panel; however, under our crazy high UpdateProgress control.

Problem solved—for now.

Here’s how they look, side by side.

FireFox 3:

FireFox 3 Output

Nice and clean, properly centered given the size of the box and window size.  Can see drop down lists and MPE behind the UpdateProgress, but cannot access them.

IE 7:

IE7 Output

Output as expected and where expected.  Can see drop down lists and MPE behind the UpdateProgress, but cannot access them.

IE 6:

IE6 Output

Output as expected—basically where expected.  Drop down lists are hidden behind the IFRAME to prevent input.  Other controls are visible, including the MPE, but behind the background.

What fun!

AnkhSVN 2.0 Released – How’s it look?

When I first started using Subversion full time for all of my personal projects, I stuck with the VisualSVN server and AnkhSVN as a Visual Studio client.  Both were free, easy to install, and easy to use.

However, after a few weeks, the AnkhSVN client could almost be called “annoying.”  It trampled over the existing SCC plugins for SourceSafe (for work) and made a mess out of several of my project uploads.  I ended up going back to using TortioiseSVN and doing everything through Explorer.

When AnkhSVN 2.0 was released, I figured I’d give it another shot.

The site claims quite a bit—including several unique additions:

  • Pending changes window; subversion status and commands available in one place
  • Full support for Visual Studio 2005 and 2008; AnkhSVN is now a SCC package instead of just an addin
  • Better log viewer
  • Merge support
  • Property editor
  • AnkhSVN now supports most project types previously unsupported via the SCC api
  • All solution explorer actions (rename, copy&paste, drag&drop) keep subversion history now
  • Enhanced build process and setup
  • Automatic check for updates
  • And last but certainly not least end user documentation

All of those look great—especially the SCC package and changes window.  But how does it compare once installed?

After installation and starting up VS2008, everything looks normal.

Brief Look

Pending Changes Window

The new pending changes window is FANTASTIC—much improved over the old 1.x versions.  I did run into a snafu when trying to resize the window where the scrollbars didn’t update on the screen; however, I’m not sure if it’s a VSS or AnkhSVN issue.

SCC Package

Under Options > Source Control, AnkhSVN shows up just like it should.

What does boggle me is that all of the Subversion commands and menus are available no matter what—even when the VSS SCC is enabled.  It still has the stink of VSS and SVN trying to step on one another (“pick me! control your project with me! no, I’m better! pick me!”).

Log/History Viewer

I really like the new history viewer.  It’s clean and easy to read; however, if you change the options at the top—there doesn’t appear to be a way to “change it back” and see the history again, close the view and review.

Annoyances

  • Opening a project from Subversion (File > Subversion > Open from Subversion) will open a project just fine, copy it down, but never opens it.  You have to go back and open the solution after it’s created the local structure.  Not huge, but annoying.
  • When viewing history; you cannot view the history of a single file (that I’ve found) in the Repository Explorer. 

I’m still planning to give it a whirl for the next couple of weeks and see what happens.  Hopefully over a couple weeks I’ll have more time to code—it’s been a busy July so far!

ReSharper 4.0 Beta Released!

The EAP from Monday (19 May) was elevated from Beta candidate to Beta status later this week—a tremendous step for the tool.  The JetBrains team has been cranking out build after build and the latest few have been great!

If you have been putting off checking out the new ReSharper—don’t wait!  The builds are extremely solid and if you do happen across an issue, submit it up and help the community!