• Post Calendar

    November 2018
    S M T W T F S
    « Sep    
     123
    45678910
    11121314151617
    18192021222324
    252627282930  

Productivity Power Tools 2015

These tools are great, and probably many of you have already found this Visual Studio 2015 extension. They really help when trying to review code changes.

The Benefit

Today I had to compare a file from two different points in time. Unfortunately, some developers had the productivity tools and others did not. As a result I had to painstakingly look at many lines where the difference might have been “this=that” rather than “this = that”.

Getting it Setup

Here are the settings that would have helped that situation… First make sure you have the tools:

image

Then go to the Tools –> Options… Productivity Power Tools, PowerCommands:

:image

With these settings your files will be kept tidy for proper formatting as well keeping the using statements under control.

But… make sure your fellow developers don’t go changing the definition of the format. Example, if some decides they like a Tab size of 5 rather than 4, then every line in your fill will show as changed between that developer and any version others worked on. Just leaves those defaults alone!

There are obviously lots of other cool things these tools can do… Here’s a link to their site. And they’re on Facebook as well, “Productivity Power Tools – Software

Long Live Live Writer!

I was so happy to see this on my most recent quest to install Live Writer when I got a new computer! http://www.computerworld.com/article/2934449/windows-apps/its-alive-microsoft-to-let-live-writer-live-on-as-open-source.html

This application does what it needs to do and makes it very easy to do attractive blog posts! I’m happy to help (if I can).

Skype for Business Location

Headline: If you have an entry in the “What’s happening today?” text box, that will show up. If you don’t, then the location will show up.

I want to see location information

As best I recall in Lync 2010 I would see a user’s name and status on one line, their “What’s happening today” on another, and the location on yet another. Lync of course was recently (mid 2015) renamed to Skype for Business. But even in Lync 2013 I didn’t see the location information.

How it works

After lots of trial and error I discovered the following:

If a user has set their location and checked “Show Others My Location” then you will see their location.

HOWEVER – if a user types in something into the “What’s happening today?” field, you’ll see that instead of the location!

Best Practice – If you do put something into “What’s happening today?” and you travel a fair bit, include your location in that text.

TDD Series for MVC 5

Here is a series of posts by Eric Vogel on testing MVC 5 applications:

Attain Code Management Nirvana via Test-Driven Development, Part 1

Oh, CRUD … It’s Test-Driven Development for ASP.NET MVC, Part 2

TDD for ASP.NET MVC, Part 3: Contact Service Class

Dynamically Load Bootswatch Themes

This post shows how I dynamically load a user’s selected theme in an MVC 5 application that’s using Bootstrap and Bootswatch.

App_Themes Folder

I didn’t use use that… So you can skip this section if you like.

In the past, different themes were placed in different folders and you could just enumerate the subdirectories in ~/App_Themes. But Bootswatch doesn’t use that.

Bootswatch Install Location

Bootswatch places two files in your ~/Content folder: 1) bootstrap.<theme name>.css, and 2) bootstrap.<theme name>.min.css.

Available Themes Code

So I just search that directory and look for all the files matching the “bootstrap.*.min.css” pattern and let the user select the one they want.

AvailableThemes
  1. /// <summary>
  2. /// Helps find available themes so the user can choose one. Alwo helps
  3. /// find the selected theme for loading dynamically.
  4. /// </summary>
  5. public static class AvailableThemes
  6. {
  7.     public const string ContentDirectory = "Content";
  8.     internal static ICollection<string> GetThemesList(HttpRequestBase request)
  9.     {
  10.         return GetThemesList(request.PhysicalApplicationPath);
  11.     }
  12.  
  13.     public static ICollection<string> GetThemesList(string physicalApplicationPath)
  14.     {
  15.         var themes = new Collection<string>();
  16.         var dir = Path.Combine(physicalApplicationPath, ContentDirectory);
  17.         var dirInfo = new DirectoryInfo(dir);
  18.         foreach (var themeFile in dirInfo.GetFiles("bootstrap.*.min.css", SearchOption.TopDirectoryOnly))
  19.         {
  20.             var parts = themeFile.Name.Split(new[] { '.' });
  21.             // Based on our filter search pattern we know we'll have at least 2 parts.
  22.             var themeTitle = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(parts[1]);
  23.             themes.Add(themeTitle);
  24.         }
  25.         return themes;
  26.     }
  27.  
  28.     public static string GetThemeFile(string themeName)
  29.     {
  30.         return "/" + ContentDirectory + "/bootstrap." + themeName + ".min.css";
  31.     }
  32.  
  33.  
  34.     public static string GetValidTheme(HttpRequestBase request, string savedThemeName)
  35.     {
  36.         return GetValidTheme(request.PhysicalApplicationPath, savedThemeName);
  37.     }
  38.  
  39.     /// <summary>
  40.     /// If the user's saved theme name is still available use it. If they are using
  41.     /// a theme that has sense been uninstalled, then just have them use the first
  42.     /// available theme.
  43.     /// </summary>
  44.     /// <param name="physicalApplicationPath">The physical directory location.</param>
  45.     /// <param name="savedThemeName">The name of the theme the user has chosen.</param>
  46.     /// <returns>A valid theme name.</returns>
  47.     public static string GetValidTheme(string physicalApplicationPath, string savedThemeName)
  48.     {
  49.         var themes = GetThemesList(physicalApplicationPath).Select(t => t.ToLowerInvariant());
  50.         if (themes.Contains(savedThemeName.ToLowerInvariant()))
  51.             return savedThemeName.ToLowerInvariant();
  52.         return themes.First();
  53.     }
  54. }

Then the Razor File

This is the code from the Views/Shared/_Layout.cshtml file (toward the top). So 3 lines of code allowing us to have the right bootstrap.*.min.cs filename to load.

_Layout.cshtml
  1. @{
  2.     ViewBag.Title = "Google Maps Filter";
  3.     //Layout = null;
  4.     // Get the user's saved theme.
  5.     var savedThemeName = SettingsController.GetTheme(Request);
  6.     // Validate the theme. If it no longer is available, then return the first available theme.
  7.     var themeName = AvailableThemes.GetValidTheme(Request, savedThemeName);
  8.     // Now get the actual file to load using Syles.Render.
  9.     var boostrapThemeCss = AvailableThemes.GetThemeFile(themeName);
  10. }
  11. <!DOCTYPE html>
  12. <html>
  13. <head>
  14.     @*Load the user's selected theme*@
  15.     @Styles.Render(boostrapThemeCss)

 

Summary

It’s it quite easy to dynamically load the Bootswatch Bootstrap themes using well tested C# and Razor syntax rather than javascript as I’ve seen in so many places. This keeps your code much cleaner. And again, if you add new themes, you can find them easily to present to your user. Using the NuGet install you would just add one, then you don’t need to change a single line of code for everything to work. Again, the same is true if you uninstall an existing theme.

ClaimAuthorizeAttribute

Headline: Here is what I use for authorizing controller and actions in an MVC application that uses the new Claims based authorization.

Some Great Resources

Before I even begin, let me point people to some great resources I found today on this topic. The first has so many posts on the topic and they are well written. Check out the Claims based security section:

http://dotnetcodr.com/security-and-cryptography/ by Andras Nemes (Stockholm, Sweden)

The second has quite a few resources too.

http://leastprivilege.com/2012/10/26/using-claims-based-authorization-in-mvc-and-web-api/ by Dominick Baier (Heidelberg, Germany)

Motivation

I spent lots of time looking at claims based security as the new WIF (Windows Identity Foundation) 4.5 has rolled out.

There is an attribute called ClaimsPrincipalPermission that I thought would do the trick. However, I’m not impressed. I’d love to delete this post if someone can show me what I’m doing wrong.

So the usage would be something like:

[ClaimsPrincipalPermission(SecurityAction.Demand, Resource = “Salary”, Operation = “Edit”)]

Now, suppose you have a claims system where you have addresses and salaries as resources. And some people can view both, but only edit the address.

I thought that you had name/value pairs like you do with the System.Security.Claims.Claim which has Type and Value. But it seems that if you add Resources of Address and Salary, and Operations of View and Edit there is no pairing.

So while I might give someone 1) Address/Edit, and Salary/View expecting them to not be able to edit Salary information it will let them.

What I’ve seen is it work this way: Look in all the Resources – do they have Salary? Good, now look in all the Operations – do they have Edit? Great, let them do it!

That’s not what I expected, wanted, and frankly I’ve not yet come up with a scenario where I think it would be useful.

ClaimAuthorize

So what I did instead was create a new attribute called ClaimAuthorizeAttribute.

So now if I have a ClaimIdentity with Claims of new Claim(“Address”, “Edit”) and new Claim(“Salary”, “View”) and place this on the action or controller:

[ClaimAuthorize(ClaimType=”Salary”, ClaimValue=”Edit”)]

The user would not get through.

So here is the code for that. If someone really wants it, I also have all the unit tests for it.

ClaimAuthorizeAttribute
  1. /// <summary>
  2. /// Specifies that access to a controller or action method is restricted
  3. /// to users who meet the claims requirement.
  4. /// </summary>
  5. [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
  6. public class ClaimAuthorizeAttribute : FilterAttribute, IAuthorizationFilter
  7. {
  8.     /// <summary>
  9.     /// Called when a process requests authorization.
  10.     /// </summary>
  11.     /// <param name="filterContext">The filter context, which encapsulates for information
  12.     /// using Ccr.Web.Mvc.ClaimAuthorizeAttribute.</param>
  13.     /// <exception cref="System.ArgumentNullException">The filterContext is null.</exception>
  14.     public void OnAuthorization(AuthorizationContext filterContext)
  15.     {
  16.         if (ReferenceEquals(filterContext, null))
  17.             throw new ArgumentNullException("filterContext");
  18.         if (!IsAuthorized(filterContext.HttpContext, ClaimType, ClaimValue))
  19.             HandleUnauthorizedRequest(filterContext);
  20.     }
  21.  
  22.     // Optional parameters to make unit testing easier.
  23.     internal static bool IsAuthorized(HttpContextBase httpContext, string claimType = "", string claimValue = "")
  24.     {
  25.         if (ReferenceEquals(httpContext, null))
  26.             throw new ArgumentNullException("httpContext");
  27.         var user = httpContext.User;
  28.         if (!user.Identity.IsAuthenticated)
  29.             return false;
  30.  
  31.         var claimsPrincipal = user as ClaimsPrincipal;
  32.         if (ReferenceEquals(claimsPrincipal, null))
  33.             return false;
  34.  
  35.         if (claimsPrincipal.HasClaim(claimType, claimValue))
  36.             return true;
  37.  
  38.         return false;
  39.     }
  40.  
  41.     /// <summary>
  42.     /// Gets or sets the claim type required for access to the controller or action.
  43.     /// </summary>
  44.     public string ClaimType { get; set; }
  45.  
  46.     /// <summary>
  47.     /// Optionally gets or sets the claim value required for access to the controller or action.
  48.     /// If not specified, then "True" will be used. The convention for most claims is that the
  49.     /// value is set to True.
  50.     /// </summary>
  51.  
  52.     private string _claimValue = true.ToString(CultureInfo.InvariantCulture);
  53.     public string ClaimValue
  54.     {
  55.         get { return _claimValue; }
  56.         set { _claimValue = value; }
  57.     }
  58.  
  59.     /// <summary>
  60.     /// Processes HTTP requests that fail authorization.
  61.     /// </summary>
  62.     /// <param name="filterContext">Encapsulates the information for using Ccr.Web.Mvc.ClaimAuthorizeAttribute.
  63.     /// The filterContext object contains the controller, HTTP context, reqest context,
  64.     /// action result, and route data.</param>
  65.     protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext)
  66.     {
  67.         if (ReferenceEquals(filterContext, null))
  68.             throw new ArgumentNullException("filterContext");
  69.         filterContext.Result = new HttpUnauthorizedResult();
  70.     }
  71. }

If someone sees something I’m doing with the ClaimsPrincipalPermission attribute, please let me know.

Thanks – Karl

Team Building

This is an excellent post by Christopher Avery that I frequently use when building a software development team:

5 Easy Steps That Will Make Any Team Better

The “WIIFM” or What’s In It For Me is always interesting.

UPPERCASE Menu Items in Visual Studio

I felt the tension go out of my shoulders today when I found this option!

image

Not sure what caused them to think all caps for the menu options would be a good idea.

My Daily Scrum Routine

Headline: This describes my daily routine as I participate on a virtual team scattered about the globe as we work on a project using the Scrum template.

The Situation

Currently I’m working with a team where no two people are in the same time zone!

We’re using Visual Studio Online (VSO) with the Scrum process template. We also use Visual Studio for our IDE (Integrated Development Environment). The tools are actually quite helpful for virtual teams. I point that out as I describe my daily routine.

Clear Things Out

There are all the non-development tasks. I try to clear those out of the way first. Handle the email on various topics it probably the biggest thing. Then I’m ready to begin.

Visit the Team Room

VSO has the concept of Team Rooms now. I wish I could filter out certain messages about people entering and leaving, but I still find the room valuable. This is where we each do our Daily Standup. Since we’re are scattered all over the globe there isn’t a good time for us all to talk in person each day. So instead, we write out a slightly modified version of the daily standup. Most do “what I did yesterday” and “what I plan to do today” since the daily standups tend to be in the morning.

We modify that and do it at the end of our day stating:

  1. What I did today
  2. What I plan to do tomorrow
  3. Blocking issues

We move pretty fast and by doing it at the end of our day, then the people in the other time zones have the benefit of what we did as soon as we completed it rather than waiting until the next day.

I visit the room at the beginning of the day to read everyone’s daily standup information. That allows me to not work on something if they are and also let’s me get an early start on resolving blocking issues (since I’m sort of the Scrum Master).

Visit the Task Board

In my last post I showed an image of the task board. Each row is either a PBI (Product Backlog Item) or a Bug that the team committed to do in this sprint. These are all in priority order.

Then there are three columns:

  1. To do
  2. In progress
  3. Done

At the beginning of the day I have no tasks in the In progress column, all are either To do or Done. I start at the top of the PBI/Bug list and work my way down. I look for a story I can really help with and prefer items at the top of the list over those further down. Sometimes I don’t have the skill or others have a story handled so I work my way down the list.

I then think about the day and perhaps a few more ahead. If tasks don’t exist yet I’ll create them. I’ll try to make sure that I have at least enough tasks for today. I want to change this so that we have all the tasks identified at the beginning of the sprint, but we’re just not there yet. I also try to break the tasks down into something that can be done in less than a day. I hate having a task go between To do and In progress for days on end.

Next I drag over the Task I plan to work on next and begin.

Develop

Now the fun begins! I strive to do test driven development, but it doesn’t always happen. But I work on the task until I have it done.

Definition of Done

On thing that is important is the Definition of Done. My current project is still ramping up so we don’t have everything “done” just yet, but I think we’ll get there soon (this month). Here is my definition of done for developers on the team:

  • New code has unit tests
  • There are no code analysis warnings using the Microsoft All Rules
  • All public members have XML documentation (///<summary> type)
  • There are no strings in the code – they are all in the Resources file.
  • The code builds
  • There are no failing unit tests
  • When the code is checked in it is associated with 1 PBI and 1 Task
  • The CI (Continuous Integration) build was successful (built and had no failing unit tests)

Now there is a broader definition for the team regarding, “Is the PBI done?” Usually the story is sufficient, but many times we discover something someone didn’t think about up front. These might become new PBIs.

Iterate

Once I check in code, I go back to the task board again, drag something into the In progress column and keep moving.

Close Out The Day

At some point I’m ready to call it a day. I will do this after a check in. I never leave code sitting on my machine overnight. Venkat Subramaniam taught that in a course he taught in 2008. He said if you don’t check it in at night (and it better be good), then delete it all the next day and start again. I’ve been practicing that since then and it’s really help. The day I liked the most was when I spent 9 hours the day before and probably had 800 lines of code. I threw it all away and that day I realized I could do it with about 70 lines of code! The day before just taught me what the real problem was and once I knew it the solution was quite simple.

When I check in, I always associate that with one PBI and one Task (see my previous post).

Next I visit the task board and move any In progress tasks either to Done (but the check in process usually moves those) or more likely, back to In progress.

The final step is to go into the Team Room and write my Daily Standup Report.

When things are moving well (See Super-sonic Software Development) it’s not uncommon for me to have 3 to 6 check ins per day.

Related Work Items to Reinforce Good Process

Headline: Always associate related work items to your changesets upon check-in. This post shows an easy way to do that using a Query that also reinforces the process.

Scrum Sprint Board Overview

Most projects I work on with Visual Studio and Team Foundation Server use the Scrum process template. I also do some work using what is now called Visual Studio Online or VSO. This used to be called Team Foundation Service, but I’ll call it VSO from now on. The Scrum template has a nice flow. I won’t go into too much detail, but below I show what the Sprint Task Board looks like. On the left you have Product Backlog Items (PBIs) with blue left margins (or Bugs with red left margins) and in the three other lanes of To do, In progress, and Done you have Tasks which have yellow left margins.

image

It’s really nice for team members to see what your working on. So I like to make sure that any task I’m working on I move into the In progress column. I make a habit of doing that before I begin working on the task.

Changeset Related Work Items

In my role many times I’ve had to go back and review what work was done for a particular PBI or Bug. If someone says the bug was fixed but there is no associated changeset for the bug I have to ask myself, “Was it closed as not reproducible? Did they ask the right people? How do you fix a bug without changing code?” It is possible, but I hope there’s at least  a comment.

The easiest way to associate Work Items is at the time of checkin.

The Query

So, I said I had a query that made this easy. When you are trying to checkin, in Visual Studio (I’m using 2013 for this post) you see the Related Work Items section that has Queries and Add Work Item by ID.

image

I find it much easier to use a query and then just highlight the PBI (select with a mouse click) and the Task (select with Ctrl+Click so both are now selected) and drag them into that area just as the gray text says, “Drag work items here to link them to the check-in.”

Here is the query I use:

image

There are some groupings there, but they are very faint in the image, so I highlighted that in red. It is a simple query, but you’ll notice that it reinforces good process.

  • A PBI must be committed before it shows up.
  • A Task must be in progress.
  • A Bug must be committed.

You shouldn’t be working on a Bug or PBI if they’re not committed. And Tasks should obviously be In progress and not just in “To do”.

Note: If I’m working on a large team (which I seldom do) then I might change the task section to be Work Item Type = Task And State = In Progress And Assigned To = @Me

@Me is a special placeholder so that you can share the query with others and they don’t need to change that. It can figure out who “Me” is.

For a nicer query I should not that I have a tree view:

image

With these settings:

image

Summary

DO associate work items at the time of check-in.

DO  associate both the Product Backlog Item (or User Story if your using the Agile template) as well as a Task, not just one or the other.

And as you can see, this query forces you to move tasks into the In progress column so that you can easily drag it over into the Related Work Items area of Pending Change when you’re checking in code.