RSS

Testable WebForms with MVP

Presentation materials for my “Testable WebForms with MVP” are available at the links below:

 
Leave a comment

Posted by on August 2, 2014 in Speaking Engagements

 

SQL Saturday Baton Rouge 2014

First, SQL Saturday Baton Rouge 2014 has opened registration and placed the session list online. If you’re interested in development at all this is a must attend event. The sessions span all areas of development. The tracks include: .NET, Business Intelligence, Career Development, CIO/IT Manager, DBA, IT Pro, PowerShell, SharePoint, SQL Dev, and Web/Mobile dev. Please visit the website and sign up if you’re interested.

Secondly, I will be presenting “Testable WebForms with MVP”. This will be an intermediate topic and I’ll be assuming experience using ASP.NET WebForms and a basic understanding of unit testing. All code examples will be in C#. Here’s the description I sent in:

MVC is all the rage but what about all the code you already have written in ASP.NET WebForms? How can you make it maintainable and testable? In this session, I’ll show how you can make WebForms applications testable using Model-View-Presenter.

 
Leave a comment

Posted by on July 7, 2014 in Speaking Engagements

 

Tags: , ,

ASP.NET Forms Bootstrap Menu Control

When I couldn’t find an ASP.NET Form menu control that was compatible with Bootstrap 3.1, I did what every other developer would do: I created one. Enjoy!

Here’s the HTML markup view:

<div class="navbar navbar-inverse navbar-static-top" role="navigation">
    <div class="container" style="padding: 0; margin: 0;">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
        </div>
        <div class="navbar-collapse collapse">
            <jk:BootstrapMenu ID="BootstrapMenu1" runat="server">
                <Items>
                    <asp:MenuItem Text="Home" NavigateUrl="#" />
                    <asp:MenuItem Text="About" NavigateUrl="#" />
                    <asp:MenuItem Text="Contact" NavigateUrl="#" />
                    <asp:MenuItem Text="Drop Down">
                        <asp:MenuItem Text="Action" NavigateUrl="#" />
                        <asp:MenuItem Text="Another action" NavigateUrl="#" />
                        <asp:MenuItem Text="Something else here" NavigateUrl="#" />
                    </asp:MenuItem>
                    <asp:MenuItem Text="Help" NavigateUrl="#" />
                    <asp:MenuItem Text="Nothing" />
                </Items>
            </jk:BootstrapMenu>
        </div><!--/.nav-collapse -->
    </div>
</div>

Here’s the HTML markup view for using with a SiteMapDataSource:

<div class="navbar navbar-inverse navbar-static-top" role="navigation">
    <div class="container" style="padding: 0; margin: 0;">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
        </div>
        <div class="navbar-collapse collapse">
            <jk:BootstrapMenu ID="BootstrapMenu2" runat="server" DataSourceId="SiteMapDataSource1" />
            <asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="False" />
        </div><!--/.nav-collapse -->
    </div>
</div>

In either case you’ll need a page directive

<%@ Register tagPrefix="jk" assembly="JK.Core.Web" namespace="JK.Core.Web.Controls" %>

Here’s the entire code for the class:

using System;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace JK.Core.Web.Controls
{
    [ControlValueProperty("SelectedValue")]
    [DefaultEvent("MenuItemClick")]
    [SupportsEventValidation]
    [ToolboxData("<{0}:BootstrapMenu runat=\"server\"></{0}:BootstrapMenu>")]
    public sealed class BootstrapMenu : Menu
    {
        public override void RenderBeginTag(HtmlTextWriter writer)
        {
            // don't call base.RenderBeginTag()
        }

        public override void RenderEndTag(HtmlTextWriter writer)
        {
            // don't call base.RenderEndTag()
        }

        protected override void OnPreRender(EventArgs e)
        {
            // don't call base.OnPreRender(e);
            this.EnsureDataBound();
        }

        protected override void Render(HtmlTextWriter writer)
        {
            this.BuildItems(writer, this.Items, true);
        }

        protected override void EnsureDataBound()
        {
            base.EnsureDataBound();
        }

        private void BuildItems(HtmlTextWriter writer, MenuItemCollection items, bool isRoot = false)
        {
            if (items.Count <= 0)
            {
                return;
            }

            string cssClass = "dropdown-menu";

            if (isRoot)
            {
                cssClass = "nav navbar-nav";
                if (!string.IsNullOrEmpty(this.CssClass))
                {
                    cssClass += " " + this.CssClass;
                }
            }

            writer.AddAttribute(HtmlTextWriterAttribute.Class, cssClass);
            writer.RenderBeginTag(HtmlTextWriterTag.Ul);

            foreach (MenuItem item in items)
            {
                this.BuildItem(writer, item);
            }

            writer.RenderEndTag(); // </ul>
        }

        private void BuildItem(HtmlTextWriter writer, MenuItem item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }

            if (item.ChildItems.Count > 0)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Class, "dropdown");
            }

            writer.RenderBeginTag(HtmlTextWriterTag.Li);

            if (this.IsLink(item))
            {
                this.RenderLink(writer, item);
            }
            else if (this.HasChildren(item))
            {
                this.RenderDropDown(writer, item);
            }
            else
            {
                writer.RenderBeginTag(HtmlTextWriterTag.A);
                writer.Write(item.Text);
                writer.RenderEndTag();
            }

            writer.RenderEndTag(); // </li>
        }

        private bool HasChildren(MenuItem item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            return item.ChildItems.Count > 0;
        }

        private bool IsLink(MenuItem item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            return item.Enabled && !string.IsNullOrEmpty(item.NavigateUrl);
        }

        private void RenderLink(HtmlTextWriter writer, MenuItem item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }

            string href = !string.IsNullOrEmpty(item.NavigateUrl)
                    ? this.Page.Server.HtmlEncode(this.ResolveClientUrl(item.NavigateUrl))
                    : this.Page.ClientScript.GetPostBackClientHyperlink(
                        this,
                        "b" + item.ValuePath.Replace(this.PathSeparator.ToString(), "\\"),
                        true);
            writer.AddAttribute(HtmlTextWriterAttribute.Href, href);

            string toolTip = !string.IsNullOrEmpty(item.ToolTip)
                ? item.ToolTip
                : item.Text;
            writer.AddAttribute(HtmlTextWriterAttribute.Title, toolTip);

            writer.RenderBeginTag(HtmlTextWriterTag.A);
            writer.Write(item.Text);
            writer.RenderEndTag(); // </a>
        }

        private void RenderDropDown(HtmlTextWriter writer, MenuItem item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }

            writer.AddAttribute(HtmlTextWriterAttribute.Href, "#");
            writer.AddAttribute(HtmlTextWriterAttribute.Class, "dropdown-toggle");
            writer.AddAttribute("data-toggle", "dropdown");
            writer.RenderBeginTag(HtmlTextWriterTag.A);

            string anchorValue = item.Text + "&nbsp;";
            writer.Write(anchorValue);

            writer.AddAttribute(HtmlTextWriterAttribute.Class, "caret");
            writer.RenderBeginTag(HtmlTextWriterTag.B);
            writer.RenderEndTag(); // </b>

            writer.RenderEndTag(); // </a>

            this.BuildItems(writer, item.ChildItems);
        }
    }
}

Link: CodePlex Class Source Link
Link: CodePlex Sample Page Source

Updates:

  • 2014 August 15: Added page directive needed to use control in page markup
  • 2014 April 11: Updated to work with SiteMapDataSource
 
19 Comments

Posted by on February 25, 2014 in Software Development, Web Development

 

Tags: , , , , , ,

Uncle Bob on Professional Software Development

This is a video that I think every software developer should watch. It’s a great talk about professionalism and craftsmanship within the industry.

Link: https://vimeo.com/43536488

The video is from the 2012 Norwegian Developers Conference.

 
Leave a comment

Posted by on February 10, 2014 in Software Development

 

Tags: , ,

Review: ASUS Transformer Book T100

At the end of November, I bought my wife an ASUS Transformer T100 and she loves it. I’ve also used it occasionally (okay so I actually meant A LOT) and I wanted to write up a quick review.

The Good

The touch screen is responsive and the machine hasn’t shown any performance issues in web browsing, Microsoft Office, or video consumption. The battery has lasted for at least 8 hours consistently. Also, having a full version of Word, Excel, and PowerPoint included with the machine is a godsend.

The Tolerable

The touchpad on the keyboard dock could be made a bit better. The touchpad buttons are a bit hard to click but if you only left-click on the touchpad you’ll never notice. My wife hasn’t noticed but I’ve noticed because of how much I right-click (ex., right click open in new browser tab). I’ve learned to just use the touchscreen for these types of operations on the T100.

The Bad

The one real downside of this machine is charging it. Charging over USB takes forever and can be hindered by the keyboard dock. To get a good charge, you have to undock from the keyboard and leave it charging overnight. We can deal with charging overnight but I wish ASUS would have used a technology that charges much faster. If you kill the battery early in the day, you’ll be waiting a few hours to be able to use the T100 without it being plugged in.

Conclusion

This machine does exactly what we wanted it to do. It’s an excellent 2 in 1 convertible and it is definitely worth the price. I would recommend it for anyone that isn’t a power user or has another primary computer.

Power users will want something that can run more power hungry programs without having to remote. I have used the T100 with remote desktop for programs like Photoshop, Visual Studio, and Adobe Premiere Elements but latency was a bit too much to make it a realistic work scenario.

Update July 26, 2014

I finally decided to buy a new charger for the tablet and it has made a world of difference. We no longer have any issues with charging!

 
2 Comments

Posted by on January 10, 2014 in Personal Computing

 

Tags: ,

What Tools Do I Use?

At Houston TechFest 2013, Claudio Lassala presented “Want to Build Software? Get Your Act Together First!“. It got me thinking about how I work and what software I would recommend. The following tools fit into two categories. I either use it daily or it’s invaluable in specific situations (for example, taking screenshots or giving presentations).

The Data I Need When I Need It

I use a combination of three pieces of software to ensure that I always have all of the information I need at my fingertips. The three are: SkyDrive, OneNote, and KeePass.

SkyDrive is the Microsoft DropBox competitor. I use it for a 2 reasons. The first reason is it that it offers more storage for free. SkyDrive gives 7 GB while DropBox gives 2 GB. I actually have 25 GB due to an old SkyDrive promotion. The second reason is that I can view and edit all of my files directly through a browser. This has become extremely important to me. For example, I was recently in a meeting and a presentation that I was working on came up. I didn’t have my laptop but the meeting room had a computer connected to the screen. I was able to log into my SkyDrive and review the presentation directly from my SkyDrive.

OneNote is Microsoft’s note taking software. Evernote is a popular competitor and one that I have tried before. When OneNote was released for my mobile platform, I immediately switched back. Now I have access to my notes anywhere I have my phone or have access to an internet browser (I can view and edit my OneNote notebooks through SkyDrive).

KeePass is a password manager tool. We have passwords for everything now and they should all be unique and varied. How does it work? You create one password for your encrypted KeePass file and you place all of your other passwords into the file.

Collaboration

I currently work on a distributed team so having effective tools in place for collaboration and communication is a must.

For task and backlog tracking, we use Team Foundation Server. If TFS wouldn’t be available, I would be using Trello or a tool with similar features.

For voice, we use Skype. It’s simple, effective, and proven. Its screen sharing feature comes in handy if it’s just a quick discussion. For more complex screen sharing, we use TeamViewer. TeamViewer allows users to pass control around. This comes in extremely handy when working through code with another developer. Another plus is that TeamViewer has official apps for Android, Windows 8, Windows Phone 8, and iOS.

Let’s Develop Something Already!

I have already mentioned that I work in a Microsoft development team so Visual Studio is a must. I currently have 2010 and 2012 installed on my machine but we will be moving everything to 2013 on its release. If you’d like to know which plugins I’m using for Visual Studio, see my post “Visual Studio Add-ons“.

Everyone has their own favorite text editor and mine is Notepad++. It’s always the first thing that I install on a new machine and I immediately set it as my default text viewer. I’ve recommended it to every developer friend that I know. It has lots of goodies throughout the program including plugins. For example, the Compare plugin has taken the place of WinMerge on my machines and ToolBucket let’s me easily generate GUIDs and lorem ipsum, encode/decode to base 64, and more.

A great tool for testing .NET code snippets, LINQ statements, etc. is LINQPad. This little application is extremely feature packed and you’ll find more ways to use it every time you open it. One of my favorites is the ability to generate the SQL for a LINQ statement.

IETester by DebugBar is a must have for web developers wanting to test their website’s rendering in multiple IE versions.

Greenshot is my go to application for screenshots. It has multiple capture modes and a built in image editor which allows you to edit an image before saving the final version.

Presentation Must Haves

If you’re giving presentations or sharing screens often, I have a couple of recommendations.

The first suggestion is Key Jedi. Presenters tend to forget that the viewers don’t know when you press Alt, Ctrl, etc. This is a little application displays those special combination keystrokes so that your audience doesn’t get lost when you’re flying around Visual Studio using only the keyboard.

The second is ZoomIt. This application allows you to Zoom in and out of any application running in Windows. It also has some markup features which are quite nice once you get used to the keyboard shortcuts.

 
1 Comment

Posted by on October 10, 2013 in Personal

 

Tags: , ,

Lazy Strategy Pattern

The following are some code samples that show how to use Lazy to clean up how your objects are initialized when using the Strategy pattern in .NET. The following code is taken from the DimeCast.Net Strategy pattern video. It uses an enum to select the correct logging strategy and logs the given message. The original code from the video before Lazy is applied looks like (by the way, I’m only posting the sections relevant to strategy and lazy):

public class LoggingService : ILoggingService
{
    private readonly Dictionary<LoggingStrategy, Logger> strategies;

    public LoggingService()
    {
        this.strategies = new Dictionary<LoggingStrategy, Logger>();
        this.DefineStrategies();
    }

    private void DefineStrategies()
    {
        this.strategies.Add(LoggingStrategy.Event, new EventLogger());
        this.strategies.Add(LoggingStrategy.Repository, new RepositoryLogger());
        this.strategies.Add(LoggingStrategy.Trace, new TraceLogger());
    }
}

Here is the same code using the Lazy<T> class in the System namespace.

public class LazyLoggingService : ILoggingService
{
    private readonly Dictionary<LoggingStrategy, Lazy<Logger>> strategies;

    public LazyLoggingService()
    {
        this.strategies = new Dictionary<LoggingStrategy, Lazy<Logger>>();
        this.DefineStrategies();
    }

    private void DefineStrategies()
    {
        this.strategies.Add(LoggingStrategy.Event, new Lazy<Logger>(() => new EventLogger()));
        this.strategies.Add(LoggingStrategy.Repository, new Lazy<Logger>(() => new RepositoryLogger()));
        this.strategies.Add(LoggingStrategy.Trace, new Lazy<Logger>(() => new TraceLogger()));
    }
}

And one final time just in case you don’t have access to Lazy<T>. This uses delegates to accomplish the same thing as the Lazy<T> class. I’ll be using the Func<TResult> delegate.

public class DelegateLoggingService : ILoggingService
{
    private readonly Dictionary<LoggingStrategy, Func<Logger>> strategies;

    public DelegateLoggingService()
    {
        this.strategies = new Dictionary<LoggingStrategy, Func<Logger>>();
        this.DefineStrategies();
    }

    private void DefineStrategies()
    {
        this.strategies.Add(LoggingStrategy.Event, () => new EventLogger());
        this.strategies.Add(LoggingStrategy.Repository, () => new RepositoryLogger());
        this.strategies.Add(LoggingStrategy.Trace, () => new TraceLogger());
    }
}

Now that all the code is out of the way, let’s talk a little about why you would want to use this. Let’s look at the original code sample. The DefineStrategies function initializes a Logger object and adds it to the Dictionary. Every single Dictionary.Add call in the original code is initializing an object. That’s additional memory and processing time for every object. By using Lazy(or the delegate method shown above), you postpone the initialization of the object until you actually ask for it.

Lazy initialization may not work well for everything but I’ve found that it makes strategy implementations much more lean and efficient in terms of machine resources.

 
Leave a comment

Posted by on May 2, 2013 in Software Development

 

Tags: , , ,

SQL If Exists Then Drop

This is one topic that I continually find myself refering to my notes and bookmarks on and I’ve finally decided to add this piece of very good reference information to my own blog.

Tables

Option 1:

IF OBJECT_ID('enterTableNameHere', 'U') IS NOT NULL
BEGIN
    DROP TABLE [dbo].[enterTableNameHere]
END
GO

Option 2:

IF EXISTS
(
    SELECT * FROM dbo.sysobjects
    WHERE id = object_id(N'[dbo].[enterTableNameHere]')
         AND OBJECTPROPERTY(id, N'IsUserTable') = 1
)
BEGIN
    DROP TABLE [dbo].[enterTableNameHere]
END
GO

Views

IF EXISTS
(
    SELECT * FROM INFORMATION_SCHEMA.VIEWS
    WHERE TABLE_SCHEMA = 'enterSchemaNameHere' AND TABLE_NAME = 'enterViewNameHere'
)
BEGIN
    DROP VIEW [dbo].[enterViewNameHere]
END
GO

Stored Procedures

IF EXISTS
(
    SELECT * FROM dbo.sysobjects
    WHERE id = object_id(N'[dbo].[enterStoredProcedureNameHere]')
        AND OBJECTPROPERTY(id, N'IsProcedure') = 1
)
BEGIN
    DROP PROCEDURE [dbo].[enterStoredProcedureNameHere]
END
GO

User-Defined Functions

IF EXISTS
(
    SELECT * FROM INFORMATION_SCHEMA.ROUTINES
    WHERE	ROUTINE_NAME = 'enterFunctionNameHere'
    AND ROUTINE_SCHEMA = 'dbo'
    AND ROUTINE_TYPE = 'FUNCTION'
)
BEGIN
    DROP FUNCTION [dbo].[enterFunctionNameHere]
END
GO
 
Leave a comment

Posted by on April 15, 2013 in Database Development

 

Tags: , , ,

Review: Nokia Lumia 920

I’ve had the Nokia Lumia 920 for a few months now and I think I can give a pretty good review. The phone was quite large to me at first but I did have an HTC Aria before this so anything was going to be huge to me. The phone is a bit heavy but the build quality is excellent. The screen looks great in a variety of lighting conditions. I’ve yet to use the “you can use gloves” feature since we never get glove weather but my wife loves that she can use her fingernails.

Side Note: The OtterBox case must be the best built OtterBox case I’ve ever seen. Even my carrier’s sales rep was amazed at how snug the phone sat in the case and how well it was made. I’m extremely glad I bought it considering I’ve dropped my phone multiple times now…

Wireless Charging

Wireless charging is also an interesting addition to the phone. The phone’s battery can easily go at least all day without a charge if you’re not using it much. With wireless charging, it really doesn’t matter how much you use it though. I usually just keep my phone on my desk anyway. Now I just make sure to drop it on the charging plate. As a bonus, the phone will never have the charging port/cable go bad which seems to be a common problem amongst my friends and family.

Camera

I was a bit worried about the camera with some people saying it doesn’t live up to the hype. They were wrong. The camera produces beautiful pictures. I will agree with some reviewers in that the built in software is a bit limited but a quick search on the marketplace for additional Lenses will fix that quickly.

Operating System

Not much to say about the operating system. Windows Phone is easy to use and intuitive. There are some great ease of use features like the ability to text a reply directly in the incoming call screen. There are two features suprisingly missing from the OS though: an incoming call blacklist and automatic silent/vibrate when appointment is marked busy. Add these 2 features Microsoft and you’ve got a perfect OS.

The browser (IE10) has worked amazing although I do wish they’d implement the full version’s InPrivate mode into the phone version. I keep my gaming accounts separate and InPrivate is an easy way to move between accounts.

Applications

Play and iTunes boast about the number of applications that they have but let’s be realistic. How many of those applications are actually be used by consumers. I have not had trouble finding applications for Windows Phone.

With that said, I don’t game much on my phone besides Sudoku and Word Search type applications and I never used Instagram which is the big one I hear people complain about. If I want to share photos with people, I put them on Facebook. And I’m blaming Google for YouTube. There are some great 3rd party YouTube applications (PrimeTube, MetroTube, etc) but Google keeps breaking them. I use Vimeo for my personal and work-related videos anyway since they have a group feature.

Conclusion

I would definitely recommend the Lumia 920 to anyone in the market for a easy to use phone.

 
Leave a comment

Posted by on April 5, 2013 in Personal Computing

 

Tags: , ,

Visual Studio Tips and Tricks: Debugging

Visual Studio Tips and Tricks was a topic in our local user group a while back. I decided why not do a series of videos instead of trying to publish all of the tips in a PowerPoint or some write up. Everything shown here can be done in at least Visual Studio 2010 and Visual Studio 2012.

The debugging video below is part 2 of this video series:

 

Tags: , , , ,

 
Follow

Get every new post delivered to your Inbox.

Join 111 other followers