<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Project Management and Consulting</title>
	<atom:link href="https://antonvishnyak.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://antonvishnyak.wordpress.com</link>
	<description>Anton&#039;s thoughts on consulting, project management and application development.</description>
	<lastBuildDate>Tue, 14 Feb 2012 07:10:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='antonvishnyak.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>https://s0.wp.com/i/buttonw-com.png</url>
		<title>Project Management and Consulting</title>
		<link>https://antonvishnyak.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="https://antonvishnyak.wordpress.com/osd.xml" title="Project Management and Consulting" />
	<atom:link rel='hub' href='https://antonvishnyak.wordpress.com/?pushpress=hub'/>
	<item>
		<title>Firefox &#038; Mvc-Mini-Profiler Gotcha!</title>
		<link>https://antonvishnyak.wordpress.com/2011/10/26/firefox-mvc-mini-profiler-gotcha/</link>
					<comments>https://antonvishnyak.wordpress.com/2011/10/26/firefox-mvc-mini-profiler-gotcha/#comments</comments>
		
		<dc:creator><![CDATA[Anton Vishnyak]]></dc:creator>
		<pubDate>Thu, 27 Oct 2011 06:14:27 +0000</pubDate>
				<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[asp.net mvc]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[mvc-mini-profiler]]></category>
		<guid isPermaLink="false">http://antonvishnyak.wordpress.com/?p=71</guid>

					<description><![CDATA[Update: Sam Saffron has fixed this issue in the latest version of Mvc-Mini-Profiler. It took days to figure out why Firefox was aborting all requests after my login screen. So, I will make the conclusion of my search bold and underlined: If you are using Mvc-mini-profiler and only logging to the database, you will eventually [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><strong>Update: Sam Saffron has fixed this issue in the <a href="http://code.google.com/p/mvc-mini-profiler/" title="latest version of Mvc-Mini-Profiler" target="_blank">latest version of Mvc-Mini-Profiler</a>.</strong></p>
<p>It took days to figure out why Firefox was aborting all requests after my login screen. So, I will make the conclusion of my search bold and underlined:</p>
<blockquote><p>If you are using Mvc-mini-profiler and only logging to the database, you will eventually come to a time when the number of GUIDs that Mvc-mini-profiler inserts into your HTTP responses (X-MiniProfiler-Id headers) will grow to the point where Firefox will silently drop any requests to your website.  Firefox will show GET requests with undefined response codes and refuse to load any further pages from your site until the Mvc-Mini-Profiler is turned off.</p></blockquote>
<p>The fix for this is to create a custom SqlStorage provider for Mvc-mini-profiler and override the HasUserViewed field.  Here is my attempt at this:</p>
<pre class="brush: csharp; title: ; notranslate">
public class MvcMiniProfilerStorage : SqlServerStorage
    {
        public MvcMiniProfilerStorage(string connectionString)
               : base(connectionString)
        {
        }

        /// &lt;summary&gt;
        /// 	Stores  to dbo.MiniProfilers under its ; 
        /// 	stores all child Timings and SqlTimings to their respective tables.
        /// &lt;/summary&gt;
        public override void Save(MiniProfiler profiler)
        {
            const string sql =
                @&quot;insert into MiniProfilers
            (Id,
             Name,
             Started,
             MachineName,
             [User],
             Level,
             RootTimingId,
             DurationMilliseconds,
             DurationMillisecondsInSql,
             HasSqlTimings,
             HasDuplicateSqlTimings,
             HasTrivialTimings,
             HasAllTrivialTimings,
             TrivialDurationThresholdMilliseconds,
             HasUserViewed)
select       @Id,
             @Name,
             @Started,
             @MachineName,
             @User,
             @Level,
             @RootTimingId,
             @DurationMilliseconds,
             @DurationMillisecondsInSql,
             @HasSqlTimings,
             @HasDuplicateSqlTimings,
             @HasTrivialTimings,
             @HasAllTrivialTimings,
             @TrivialDurationThresholdMilliseconds,
             @HasUserViewed
where not exists (select 1 from MiniProfilers where Id = @Id)&quot;;
            // this syntax works on both mssql and sqlite

            using (DbConnection conn = GetOpenConnection())
            {
                int insertCount = conn.Execute(sql,
                    new
                        {
                            profiler.Id,
                            Name = Truncate(profiler.Name, 200),
                            profiler.Started,
                            MachineName = Truncate(profiler.MachineName, 100),
                            User = Truncate(profiler.User, 100),
                            profiler.Level,
                            RootTimingId = profiler.Root.Id,
                            profiler.DurationMilliseconds,
                            profiler.DurationMillisecondsInSql,
                            profiler.HasSqlTimings,
                            profiler.HasDuplicateSqlTimings,
                            profiler.HasTrivialTimings,
                            profiler.HasAllTrivialTimings,
                            profiler.TrivialDurationThresholdMilliseconds,
                            // BUG: Too many X-MiniProfiler-Id headers cause
                            // Firefox to stop all requests
                            //
                            // This hack marks all entries as read so that
                            // they do not end up part of that header.
                            HasUserViewed = true    
                        });

                if (insertCount &gt; 0)
                {
                    SaveTiming(conn, profiler, profiler.Root);
                }
            }
        }

        private static string Truncate(string s, int maxLength)
        {
            return s != null &amp;&amp; s.Length &gt;
                        maxLength ? s.Substring(0, maxLength) : s;
        }
    }
</pre>
<p>Then it&#8217;s a simple matter of making sure that the Mvc-mini-profiler uses your version of this class rather than it&#8217;s own SqlServerStorage class.</p>
<pre class="brush: csharp; title: ; wrap-lines: true; notranslate">
MiniProfiler.Settings.Storage = new MvcMiniProfilerStorage(&quot;connStr&quot;);
</pre>
<p>This should take care of your Mvc-Mini-Profiler headaches.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://antonvishnyak.wordpress.com/2011/10/26/firefox-mvc-mini-profiler-gotcha/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		
		<media:content url="https://2.gravatar.com/avatar/8fc1505e270caa7b01e65478aab41e61fdca25f2a3ebcd465a528a0f664dd21d?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kernel128</media:title>
		</media:content>
	</item>
		<item>
		<title>Expanding the Mvc-Mini-Profiler to measure and report performance of ActionFilters</title>
		<link>https://antonvishnyak.wordpress.com/2011/09/13/expanding-the-mvc-mini-profiler-to-measure-and-report-performance-of-actionfilters/</link>
					<comments>https://antonvishnyak.wordpress.com/2011/09/13/expanding-the-mvc-mini-profiler-to-measure-and-report-performance-of-actionfilters/#respond</comments>
		
		<dc:creator><![CDATA[Anton Vishnyak]]></dc:creator>
		<pubDate>Tue, 13 Sep 2011 20:13:21 +0000</pubDate>
				<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[asp.net mvc]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[mvc-mini-profiler]]></category>
		<guid isPermaLink="false">http://antonvishnyak.wordpress.com/?p=52</guid>

					<description><![CDATA[Update: You may also be interested in my post about creating a dashboard to review Mvc-Mini-Profiler logs. Source code available on Google Code. I have recently integrated the mvc-mini-profiler tool into JobSeriously. One thing that JobSeriously does is make good use of ActionFilters to handle cross-cutting concerns. The more I thought about it the more I recognized [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><em><strong>Update: You may also be interested in my post about <a href="https://antonvishnyak.wordpress.com/2011/09/07/building-an-mvc-mini-profiler-dashboard/" title="Building an mvc-mini-profiler dashboard">creating a dashboard to review Mvc-Mini-Profiler logs</a>.  Source code available on <a href="http://code.google.com/p/mvc-mini-profiler-dashboard/" title="mvc-mini-profiler-dashboard">Google Code</a>.</strong></em></p>
<p>I have recently integrated the <a title="About mvc-mini-profiler" href="http://code.google.com/p/mvc-mini-profiler/" target="_blank">mvc-mini-profiler</a> tool into <a title="JobSeriously brings job opportunities from major job boards to one easy-to-use inbox." href="http://jobseriously.com/" target="_blank">JobSeriously</a>. One thing that JobSeriously does is make good use of ActionFilters to handle cross-cutting concerns. The more I thought about it the more I recognized a need to see the performance of those custom filters as part of the Mvc-mini-profiler stream. After all, what good is it to see an action that takes a long time only to find out that most of the time is spent in your new spiffy ActionFilter?</p>
<p>So, I set out on a path to automagically profile all of the ActionFilters (and ResultFilters) throughout my ASP.NET MVC application. The first logical step, is to come up with a wrapper class that can wrap an ActionFilterAttribute and attach profiling to it (without altering the implementation or imposing overhead while not profiling).</p>
<p>Due to some under-the-hood implementation choices by the MVC team, we have to wrap ActionFilterAttributes based on the interfaces they support. In this case, it&#8217;s IActionFilter and IResultFilter.</p>
<pre class="brush: csharp; title: ; notranslate">
    public class ProfiledFilterWrapper : IActionFilter, IResultFilter
    {
        private readonly IActionFilter actionFilter;
        private readonly IResultFilter resultFilter;

        public ProfiledFilterWrapper(IActionFilter actionFilter)
        {
            this.actionFilter = actionFilter;
        }

        public ProfiledFilterWrapper(IResultFilter resultFilter)
        {
            this.resultFilter = resultFilter;
        }

        public void OnActionExecuted(ActionExecutedContext filterContext)
        {
            using (MiniProfiler.StepStatic(&quot;Attribute: &quot; + actionFilter.GetType().Name + &quot;.OnActionExecuted&quot;))
            {
                actionFilter.OnActionExecuted(filterContext);
            }
        }

        public void OnActionExecuting(ActionExecutingContext filterContext)
        {
            using (MiniProfiler.StepStatic(&quot;Attribute: &quot; + actionFilter.GetType().Name + &quot;.OnActionExecuting&quot;))
            {
                actionFilter.OnActionExecuting(filterContext);
            }
        }

        public void OnResultExecuted(ResultExecutedContext filterContext)
        {
            using (MiniProfiler.StepStatic(&quot;Attribute: &quot; + resultFilter.GetType().Name + &quot;.OnResultExecuted&quot;))
            {
                resultFilter.OnResultExecuted(filterContext);
            }
        }

        public void OnResultExecuting(ResultExecutingContext filterContext)
        {
            using (MiniProfiler.StepStatic(&quot;Attribute: &quot; + resultFilter.GetType().Name + &quot;.OnResultExecuting&quot;))
            {
                resultFilter.OnResultExecuting(filterContext);
            }
        }
    }
</pre>
<p>Now that we have the AttributeWrapper, we need a way to wire it up. Fortunately, the MVC team made this relatively easy by providing the ability to customize the ControllerActionInvoker. Our next step is to create an ActionInvoker that will wrap all ActionFilterAttributes with our wrapper class.<br />
Note: We certainly don&#8217;t want to wrap things more than once or wrap the actual ProfilingActionFilter that you may be using from the mvc-mini-profiler. That&#8217;s what those LINQ operations in this class are doing.</p>
<pre class="brush: csharp; title: ; notranslate">
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.Mvc;

    using MvcMiniProfiler.MVCHelpers;

    /// &lt;summary&gt;
    ///	Custom ControllerActionInvoker that wraps attributes for profiling with MvcMiniProfiler
    /// &lt;/summary&gt;
    public class ProfiledActionInvoker : ControllerActionInvoker
    {
        protected override FilterInfo GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
        {
            FilterInfo baseFilters = base.GetFilters(controllerContext, actionDescriptor);

            WrapFilters(baseFilters.ActionFilters);
            WrapFilters(baseFilters.ResultFilters);

            return baseFilters;
        }

        private void WrapFilters(IList&lt;IActionFilter&gt; filters)
        {
            // Not tested with attribute ordering (may not honor the ordering)
            IList&lt;IActionFilter&gt; originalFilters = filters.ToList();

            // Avoid wrapping the ProfilingActionFilter (sometimes injected by MVC Mini Profiler) and Attributes that are already wrapped.
            IEnumerable&lt;IActionFilter&gt; wrappedFilters = originalFilters
                       .Where(t =&gt; t.GetType() != typeof(ProfiledFilterWrapper)
                              &amp;&amp; t.GetType() != typeof(ProfilingActionFilter))
                       .Select(item =&gt; new ProfiledFilterWrapper(item));

            IEnumerable&lt;IActionFilter&gt; unwrappedFilters = originalFilters
                       .Where(t =&gt; t.GetType() == typeof(ProfiledFilterWrapper)
                              || t.GetType() == typeof(ProfilingActionFilter));

            filters.Clear();

            foreach (IActionFilter actionFilter in wrappedFilters)
            {
                filters.Add(actionFilter);
            }

            foreach (IActionFilter actionFilter in unwrappedFilters)
            {
                filters.Add(actionFilter);
            }
        }

        private void WrapFilters(IList&lt;IResultFilter&gt; filters)
        {
            // Not tested with attribute ordering (may not honor the ordering)
            IList&lt;IResultFilter&gt; originalFilters = filters.ToList();

            // Avoid wrapping the ProfilingActionFilter (sometimes injected by MVC Mini Profiler) and Attributes that are already wrapped.
            IEnumerable&lt;IResultFilter&gt; wrappedFilters = originalFilters
                       .Where(t =&gt; t.GetType() != typeof(ProfiledFilterWrapper)
                              &amp;&amp; t.GetType() != typeof(ProfilingActionFilter))
                       .Select(item =&gt; new ProfiledFilterWrapper(item));

            IEnumerable&lt;IResultFilter&gt; unwrappedFilters = originalFilters
                       .Where(t =&gt; t.GetType() == typeof(ProfiledFilterWrapper)
                              || t.GetType() == typeof(ProfilingActionFilter));

            filters.Clear();

            foreach (IResultFilter actionFilter in wrappedFilters)
            {
                filters.Add(actionFilter);
            }

            foreach (IResultFilter actionFilter in unwrappedFilters)
            {
                filters.Add(actionFilter);
            }
        }
    }
</pre>
<p>Now that we have a way to wrap all of the attributes, we need some way to hook our ActionInvoker into the MVC pipeline. To do that, we need to create a custom ControllerFactory that will create use our ActionInvoker instead of the default one. The implementation below wraps the existing controller factory and swaps out the ActionInvoker. The reason I chose to create a wrapper rather than a concrete implementation is that I want to be able to use a controller factory from my IoC provider (Ninject). This pass-through approach gives us the best of both worlds.</p>
<pre class="brush: csharp; title: ; notranslate">
    using System;
    using System.Web.Mvc;
    using System.Web.Routing;
    using System.Web.SessionState;

    /// &lt;summary&gt;
    /// A wrapper ControllerFactory which can be used to profile the performance of attributes in MVC.
    /// &lt;/summary&gt;
    public class PerformanceControllerFactory : IControllerFactory
    {
        readonly IControllerFactory controllerFactory;

        public PerformanceControllerFactory(IControllerFactory controllerFactory)
        {
            this.controllerFactory = controllerFactory;
        }

        public IController CreateController(RequestContext requestContext, string controllerName)
        {
            var controller = controllerFactory.CreateController(requestContext, controllerName);

            var normalController = controller as Controller;
            if (normalController != null)
            {
                normalController.ActionInvoker = new ProfiledActionInvoker();
            }

            return controller;
        }

        public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
        {
            return controllerFactory.GetControllerSessionBehavior(requestContext, controllerName);
        }

        public void ReleaseController(IController controller)
        {
            controllerFactory.ReleaseController(controller);
        }
    }
</pre>
<p>With everything nicely wrapped and ready to go, we just need to add 2 lines of code to the App_Start procedure of the ASP.NET MVC application to hook in our custom ControllerFactory. I would suggest you place this code at the end of your App_Start to ensure any other code you have is able to hook in what it needs first.</p>
<pre class="brush: csharp; title: ; notranslate">
IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();

ControllerBuilder.Current.SetControllerFactory(new PerformanceControllerFactory(factory));
</pre>
]]></content:encoded>
					
					<wfw:commentRss>https://antonvishnyak.wordpress.com/2011/09/13/expanding-the-mvc-mini-profiler-to-measure-and-report-performance-of-actionfilters/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://2.gravatar.com/avatar/8fc1505e270caa7b01e65478aab41e61fdca25f2a3ebcd465a528a0f664dd21d?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kernel128</media:title>
		</media:content>
	</item>
		<item>
		<title>Building an mvc-mini-profiler dashboard</title>
		<link>https://antonvishnyak.wordpress.com/2011/09/07/building-an-mvc-mini-profiler-dashboard/</link>
					<comments>https://antonvishnyak.wordpress.com/2011/09/07/building-an-mvc-mini-profiler-dashboard/#comments</comments>
		
		<dc:creator><![CDATA[Anton Vishnyak]]></dc:creator>
		<pubDate>Thu, 08 Sep 2011 04:40:07 +0000</pubDate>
				<category><![CDATA[ASP.NET MVC]]></category>
		<category><![CDATA[asp.net mvc]]></category>
		<category><![CDATA[c#]]></category>
		<category><![CDATA[mvc-mini-profiler]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">http://antonvishnyak.wordpress.com/?p=28</guid>

					<description><![CDATA[Update: The sample project is now available on Google Code. In a departure from my normal blog topics, I thought I would dip a toe in writing about web development with ASP.NET MVC.  I have recently integrated the wonderful mvc-mini-profiler tool into JobSeriously and wanted to share how I set up a great dashboard for it. [&#8230;]]]></description>
										<content:encoded><![CDATA[<p><em><strong>Update: The sample project is now available on <a href="http://code.google.com/p/mvc-mini-profiler-dashboard" title="MVC-Mini-Profiler-Dashboard Google Code" target="_blank">Google Code</a>.</strong></em></p>
<p>In a departure from my normal blog topics, I thought I would dip a toe in writing about web development with ASP.NET MVC.  I have recently integrated the wonderful <a title="About mvc-mini-profiler" href="http://code.google.com/p/mvc-mini-profiler/" target="_blank">mvc-mini-profiler</a> tool into <a title="JobSeriously brings job opportunities from major job boards to one easy-to-use inbox." href="http://jobseriously.com" target="_blank">JobSeriously</a> and wanted to share how I set up a great dashboard for it.</p>
<p><img class="alignright" style="border-color:initial;border-style:initial;" title="mvc-mini-profiler chiclet" src="https://i0.wp.com/i.imgur.com/PsjLY.png" alt="" width="319" height="186" /></p>
<p>They typical use case for mvc-mini-profiler is to embed a floating UI on the page which looks like a hovering chicklet in the corner.  Clicking the mvc-mini-profiler UI shows a popup box that has detailed timings.  This works if you only want to profile a few people (e.g. only the site developers) and you want these stats in their face all the time.  However, this does not work well if you want to profile a segment of your real users.  Additionally, this approach usually relies on authentication cookies which can be stolen (as happened to some folks on the StackOverflow site itself).  It would be bad enough to have a bad guy effectively impersonating you on the site, you certainly wouldn&#8217;t want to expose the internals of your code via your profiler as well.</p>
<p>What I wanted to do for JobSeriously was to log these timings to our database and be able to review the results on a dashboard that only admins could see.  Using out-of-the box functionality of the mvc-mini-profiler, I was able to set up logging to the database fairly easily.  Then I sprinkled in some Google Visualization API and was able to come up with a dashboard that looks like this:</p>
<p><a href="https://antonvishnyak.wordpress.com/wp-content/uploads/2011/09/mvc-mini-profiler-dashboard.png"><img data-attachment-id="29" data-permalink="https://antonvishnyak.wordpress.com/2011/09/07/building-an-mvc-mini-profiler-dashboard/mvc-mini-profiler-dashboard/" data-orig-file="https://antonvishnyak.wordpress.com/wp-content/uploads/2011/09/mvc-mini-profiler-dashboard.png" data-orig-size="912,823" data-comments-opened="1" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;}" data-image-title="Mvc-mini-profiler Dashboard" data-image-description="" data-image-caption="" data-medium-file="https://antonvishnyak.wordpress.com/wp-content/uploads/2011/09/mvc-mini-profiler-dashboard.png?w=300" data-large-file="https://antonvishnyak.wordpress.com/wp-content/uploads/2011/09/mvc-mini-profiler-dashboard.png?w=540" class="size-medium wp-image-29 alignleft" title="Mvc-mini-profiler Dashboard" src="https://antonvishnyak.wordpress.com/wp-content/uploads/2011/09/mvc-mini-profiler-dashboard.png?w=300&#038;h=271" alt=""   srcset="https://antonvishnyak.wordpress.com/wp-content/uploads/2011/09/mvc-mini-profiler-dashboard.png?w=547&amp;h=494 547w, https://antonvishnyak.wordpress.com/wp-content/uploads/2011/09/mvc-mini-profiler-dashboard.png?w=150&amp;h=135 150w, https://antonvishnyak.wordpress.com/wp-content/uploads/2011/09/mvc-mini-profiler-dashboard.png?w=300&amp;h=271 300w, https://antonvishnyak.wordpress.com/wp-content/uploads/2011/09/mvc-mini-profiler-dashboard.png?w=768&amp;h=693 768w, https://antonvishnyak.wordpress.com/wp-content/uploads/2011/09/mvc-mini-profiler-dashboard.png 912w" sizes="(max-width: 547px) 100vw, 547px" /></a></p>
<p>My requirements were that the dashboard should help me target the worst offenders on the list without distracting me with outliers.  Therefore, I decided to use box plots to visualize the data.  For those of you who may not be familiar with box plots, the box portion shows every sample between the 25th and 75th percentiles.  The line at the top and bottom of the box plot shows the top and bottom 25% of samples. This helps you see if your distribution is skewed towards the top or  to the bottom (as is the case with JobSeriously).  Using the box plot also allows you to quickly see how much variability there is in page load times.  In short, the boxes represent what the majority of your users are experiencing while the wicks show the extremes. Read more about <a href="http://en.wikipedia.org/wiki/Box_plot" target="_blank">box plots</a> on WikiPedia.</p>
<p>The first step to setting up the dashboard is to configure your database with the proper tables for mvc-mini-profiler.  Fortunately, the profiler comes with the necessary scripts built in.  However, the create script is actually embedded in the compiled code with no way to get to it.  I recommend that you manually extract the code and create your own create/rollback scripts that suit your environment.  The script is actually located at the bottom of the <a href="http://code.google.com/p/mvc-mini-profiler/source/browse/MvcMiniProfiler/Storage/SqlServerStorage.cs">SqlServerStorage </a>source code file (<a title="Sql Create Scripts" href="http://pastebin.com/vg0iGcXx" target="_blank">extraced SQL Code</a>).</p>
<p>After configuring the SQL server itself, we need to configure the mvc-mini-profiler to log to the SQL server instead of outputting the results to the page.  Luckily, this is a single line of code change in the Globals.ascx.cs file.</p>
<p><code>MiniProfiler.Settings.Storage = new SqlServerStorage("your SQL connection string");</code></p>
<p>I placed the preceding code into my OnApplicationStarted method.</p>
<p>Next, we want to add a controller (or a method to an existing controller) that will display the results.  The code is very simple in that it just executes a single SQL statement and passes the data directly to the view we will create next.</p>
<pre class="brush: csharp; title: ; wrap-lines: false; notranslate">
    #region Imports

    using System.Collections.Generic;
    using System.Configuration;
    using System.Data;
    using System.Data.Common;
    using System.Data.SqlClient;
    using System.Web.Mvc;

    using Dapper;

    #endregion

    [Authorize(Roles = &quot;Administrator&quot;)]
    public class PerformanceController : Controller
    {
        #region Constants and Fields

	// Change this to point to your SQL Server
        private readonly string connectionString = &quot;Sql server connection string&quot;;

        #endregion

        #region Public Methods

        public ActionResult Index()
        {
            const string sql =
                @&quot;select SRC.Name as WebRoute, count(SRC.name) as Samples, avg(DurationMilliseconds) as AvgD, min(DurationMilliseconds) as Low, max(DurationMilliseconds) as High, max(Ranks.Under10) as LowSample, max(Ranks.Over90) as HighSample, max(LowRanks.LongestDuration) as BoxLow, max(HighRanks.LongestDuration) as BoxHigh
from
(
	select Name,
		DurationMilliseconds,
		Dense_Rank() over (partition by Name order by DurationMilliseconds) as drank
	from MiniProfilers
) AS src
LEFT OUTER JOIN (
	select Name, floor( (max(src2.drank) - min(src2.drank)) * 0.25 ) + 1 as Under10, ceiling( (max(src2.drank) - min(src2.drank)) * 0.75 ) + 1 as Over90
	from
	(
		select Name,
			DurationMilliseconds,
			Dense_Rank() over (partition by Name order by DurationMilliseconds) as drank
		from MiniProfilers
	) AS SRC2
	group by name
) AS Ranks ON Src.Name = Ranks.Name
LEFT OUTER JOIN (
	select Name,
		DurationMilliseconds as LongestDuration,
		Dense_Rank() over (partition by Name order by DurationMilliseconds) as drank
	from MiniProfilers
	group by name, DurationMilliseconds
) AS LowRanks ON Src.Name = LowRanks.Name AND Ranks.Under10 = LowRanks.drank
LEFT OUTER JOIN (
	select Name,
		DurationMilliseconds as LongestDuration,
		Dense_Rank() over (partition by Name order by DurationMilliseconds) as drank
	from MiniProfilers
	group by name, DurationMilliseconds
) AS HighRanks ON Src.Name = HighRanks.Name AND Ranks.Over90 = HighRanks.drank
group by SRC.Name
order by BoxHigh DESC;&quot;;
            IEnumerable&lt;dynamic&gt; data;

            using (DbConnection conn = GetOpenConnection())
            {
                data = conn.Query(sql);
            }

            return View(data);
        }

        #endregion

        #region Methods

        /// &lt;summary&gt;
        /// 	Returns a connection to Sql Server.
        /// &lt;/summary&gt;
        protected DbConnection GetConnection()
        {
            return new SqlConnection(connectionString);
        }

        /// &lt;summary&gt;
        /// 	Returns a DbConnection already opened for execution.
        /// &lt;/summary&gt;
        protected DbConnection GetOpenConnection()
        {
            DbConnection result = GetConnection();
            if (result.State != ConnectionState.Open)
            {
                result.Open();
            }
            return result;
        }

        #endregion
    }
</pre>
<p>The code I used relies on a lightweight ORM called <a title="Dapper is a single file you can drop in to your project that will extend your IDbConnection interface." href="http://code.google.com/p/dapper-dot-net/" target="_blank">Dapper</a>.  If you are not using Dapper, you may need to change the <code>data = conn.Query(sql);</code> line to use a DataReader to read the rows from the return set.</p>
<blockquote><p>I know that SQL statement is a huge mess.  Unfortunately, MS SQL Server 2008 lacks some of the basic statistical functions required to make this a little simpler.  If you have any tips for how to make the SQL statement any better I would love to get some feedback.</p></blockquote>
<p>The last step in creating the mvc-mini-profiler dashboard is to create the view.  You will likely need to change the MasterPage referenced in that example.  What the view does is include the Google Visualization API libraries and create the box plot with a table below it.  The table is page-able and sort-able.</p>
<pre class="brush: csharp; title: ; wrap-lines: false; notranslate">
&lt;%@ Page Title=&quot;&quot; Language=&quot;C#&quot; MasterPageFile=&quot;~/Areas/Admin/Views/Shared/Admin.Master&quot; Inherits=&quot;System.Web.Mvc.ViewPage&lt;dynamic&gt;&quot; %&gt;

&lt;asp:Content ID=&quot;Content1&quot; ContentPlaceHolderID=&quot;TitleContent&quot; runat=&quot;server&quot;&gt;
    Performance Reporting
&lt;/asp:Content&gt;

&lt;asp:Content ID=&quot;Content2&quot; ContentPlaceHolderID=&quot;MainContent&quot; runat=&quot;server&quot;&gt;

&lt;div id=&quot;visualization&quot; style=&quot;width: 100%; height: 450px;&quot;&gt;&lt;/div&gt;
&lt;div id=&quot;dataTable&quot;&gt;&lt;/div&gt;

&lt;script type=&quot;text/javascript&quot; src=&quot;https://www.google.com/jsapi&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
    google.load('visualization', '1', { packages: ['table', 'corechart'] });
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
    function drawVisualization() {
        // Populate the data table.
        var dataTable = new google.visualization.DataTable();

    	dataTable.addColumn('string', 'Route');
    	dataTable.addColumn('number', 'Low');
    	dataTable.addColumn('number', '25%');
    	dataTable.addColumn('number', '75%');
    	dataTable.addColumn('number', 'High');
    	dataTable.addColumn('number', 'Count');
    	dataTable.addColumn('number', 'Average');

        &lt;% foreach (var row in (IEnumerable&lt;dynamic&gt;)Model) { %&gt;
    	dataTable.addRow(['&lt;%: row.WebRoute %&gt;', &lt;%: row.Low %&gt; , &lt;%: row.BoxLow %&gt; , &lt;%: row.BoxHigh %&gt; , &lt;%: row.High %&gt; , &lt;%: row.Samples %&gt;, &lt;%: row.AvgD %&gt; ]);
        &lt;% } %&gt;

    	var dataView = new google.visualization.DataView(dataTable);
        dataView.setColumns([0, 1, 2, 3, 4]);
    	dataView.setRows(0, 9);

    	var table = new google.visualization.Table(document.getElementById('dataTable'));
        table.draw(dataTable, { page: 'enable', pageSize: 10 });

        // Draw the chart.
        var chart = new google.visualization.CandlestickChart(document.getElementById('visualization'));
        chart.draw(dataView, { legend: 'none', 'title': 'Highest peaks', 'vAxis': {'title': 'Milliseconds (1000 = 1s)'} });
    };

    google.setOnLoadCallback(drawVisualization);
    &lt;/script&gt;
&lt;/asp:Content&gt;
</pre>
<p>Please let me know if you have any questions regarding my code.  If you are <a href="http://jobseriously.com" target="_blank">looking for a job</a>, I would love to get some feedback on JobSeriously as well.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://antonvishnyak.wordpress.com/2011/09/07/building-an-mvc-mini-profiler-dashboard/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
		
		<media:content url="https://2.gravatar.com/avatar/8fc1505e270caa7b01e65478aab41e61fdca25f2a3ebcd465a528a0f664dd21d?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kernel128</media:title>
		</media:content>

		<media:content url="http://i.imgur.com/PsjLY.png" medium="image">
			<media:title type="html">mvc-mini-profiler chiclet</media:title>
		</media:content>

		<media:content url="https://antonvishnyak.wordpress.com/wp-content/uploads/2011/09/mvc-mini-profiler-dashboard.png" medium="image">
			<media:title type="html">Mvc-mini-profiler Dashboard</media:title>
		</media:content>
	</item>
		<item>
		<title>Why do so many workflow installations go wrong?</title>
		<link>https://antonvishnyak.wordpress.com/2007/07/20/why-do-so-many-workflow-installations-go-wrong/</link>
					<comments>https://antonvishnyak.wordpress.com/2007/07/20/why-do-so-many-workflow-installations-go-wrong/#respond</comments>
		
		<dc:creator><![CDATA[Anton Vishnyak]]></dc:creator>
		<pubDate>Fri, 20 Jul 2007 16:18:14 +0000</pubDate>
				<category><![CDATA[Project Management]]></category>
		<guid isPermaLink="false">http://antonvishnyak.wordpress.com/2007/07/20/why-do-so-many-workflow-installations-go-wrong</guid>

					<description><![CDATA[In my industry, workflow is considered by many as a holy grail.  Most leaders of litigation support departments feel that they can control risks, issues, schedules, and quality through one comprehensive workflow or even a checklist.  It is tempting to think that a machine could orchestrate a project to such a degree of success that the [&#8230;]]]></description>
										<content:encoded><![CDATA[<div id="msgcns!E2069F5E4B3A2575!194" class="bvMsg">
<p>In my industry, workflow is considered by many as a holy grail.  Most leaders of litigation support departments feel that they can control risks, issues, schedules, and quality through one comprehensive workflow or even a checklist.  It is tempting to think that a machine could orchestrate a project to such a degree of success that the humans involved cannot make errors. </p>
<p>Unfortunately, there is no perfect workflow in our industry.  Not a single litigation support manager I have spoken to feels that they have their hands around the problem.  And so, we look at vendor after vendor peddling their software with a state-of-the art workflow system built in. </p>
<p>So, why do these system&#8217;s fail to achieve their promised goals?  Here is my list of &quot;gotchas&quot; about attempting to automate your project management functions via workflow: </p>
<ul>
<li>Poor planning &#8211; insufficient involvement by everyone involved with the system (IT, front-line employees, and management) during the early evaluation and planning stages of the implementation can lead to ballooning budgets and quirky systems forcing the employees to use workarounds and introduce all new and unknown risk into the process.
<li>Poor understanding of the limitations of workflow &#8211; it may handle human-to-human task management but when you add human-to-system and system-to-system interactions, event management/correlation, performance monitoring, change management, and process rules many systems just fall apart.
<li>Poor change management &#8211; sometimes the implementation of the workflow takes several months to complete.  Even with perfect planning at the beginning of an implementation, sometimes changes in the business outpace workflow development.  Many implementers fail to keep up with the pace business causing the delivered workflow to be out of date and unsuitable.
<li>No implementation with LOB applications &#8211; users touch many systems during a business process.  Many of these interactions are not documented anywhere.  A good workflow system needs to take into account integration with billing systems, case management systems, etc.
<li>Automating chaos &#8211; if your process is not clearly understood, defined, and optimized you will be automating chaos via workflow.  The result of this can only be &quot;automated chaos.&quot;
<li>Forgetting the people &#8211;  sometimes it is important to understand that it is not all about nuts and bolts.  It may not be about the lack of Change Management or the way integration is done with LOB systems.  It’s about PEOPLE.  Involve the users, educate the users and get buy-in up-front, let the users champion the project direction, talk to the front-line employees and narrow the gap between IT techniques and the Business requirements.</ul>
<p>Keep these things in mind if you insist on purchasing a system that attempts to automate your project management.  However, I recommend that litigation support managers look spend some time and optimize their people and process before they attempt to automate things.  Sometimes, the right people are all it takes. </p>
<p>Technorati Tags: <a href="http://technorati.com/tags/project management" rel="tag">project management</a>, <a href="http://technorati.com/tags/workflow" rel="tag">workflow</a>, <a href="http://technorati.com/tags/litigation support" rel="tag">litigation support</a></div>
]]></content:encoded>
					
					<wfw:commentRss>https://antonvishnyak.wordpress.com/2007/07/20/why-do-so-many-workflow-installations-go-wrong/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://2.gravatar.com/avatar/8fc1505e270caa7b01e65478aab41e61fdca25f2a3ebcd465a528a0f664dd21d?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kernel128</media:title>
		</media:content>
	</item>
		<item>
		<title>Growing a client relationship</title>
		<link>https://antonvishnyak.wordpress.com/2007/04/23/growing-a-client-relationship/</link>
					<comments>https://antonvishnyak.wordpress.com/2007/04/23/growing-a-client-relationship/#respond</comments>
		
		<dc:creator><![CDATA[Anton Vishnyak]]></dc:creator>
		<pubDate>Mon, 23 Apr 2007 16:02:38 +0000</pubDate>
				<category><![CDATA[Project Management]]></category>
		<guid isPermaLink="false">http://antonvishnyak.wordpress.com/2007/04/23/growing-a-client-relationship</guid>

					<description><![CDATA[Craig Brown of Better Projects wrote an excellent post highlighting the reasons why a client might prefer to work with certain people even though other equally qualified people are available. &#34;Patients will [&#8230;] cross the city to visit their preferred GP [rather than visiting the nearest available doctor]. Patients are not in a good position to assess the quality [&#8230;]]]></description>
										<content:encoded><![CDATA[<div id="msgcns!E2069F5E4B3A2575!192" class="bvMsg">
<p>Craig Brown of <a href="http://betterprojects.blogspot.com/index.html">Better Projects</a> wrote an excellent <a title="RATER: Empathy" href="http://betterprojects.blogspot.com/2007/04/rater-empathy.html" target="_blank">post</a> highlighting the reasons why a client might prefer to work with certain people even though other equally qualified people are available.</p>
<blockquote>
<p>&quot;Patients will [&#8230;] cross the city to visit their preferred GP [rather than visiting the nearest available doctor]. Patients are not in a good position to assess the quality of medical advice they receive, so what makes them care enough about a doctor to make such efforts? The answer is the &quot;bedside manner&quot; which in the context of this [project management / consulting] is their empathy.&quot;</p>
</blockquote>
<p>Project managers and consultants need to empathize with their client, their employees, and other stakeholders.  Through empathy, one can truly understand the issues that the other party is dealing with and respond with sincerity.</p>
<p>Once, I was involved in a project where the client services manager had to relay a possible budget overrun to the client.  Unfortunately, the client had been under the impression that the supplier would absorb any cost overruns.  The first course of action that the client services manager took is to explain in detail to the customer how high the quality of our services has been and pointed out relevant passages in the contract to correct the client&#8217;s perception.  However, the client soured on the relationship feeling that he was being cheated.  When the issue was escalated, the executive from our company listened very carefully to the client&#8217;s pain points and empathized with him.  This led directly to an improvement of the client relationship and contributed to a successful negotiation and follow-on work.</p>
<p>Do you have any stories where empathy or lack thereof led to a change in the client relationship?  If so, leave a comment.</p>
<p> </p>
<div style="display:inline;margin:0;padding:0;">Technorati tags: <a href="http://technorati.com/tags/Empathy" rel="tag">Empathy</a>, <a href="http://technorati.com/tags/project management" rel="tag">project management</a>, <a href="http://technorati.com/tags/consulting" rel="tag">consulting</a></div>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://antonvishnyak.wordpress.com/2007/04/23/growing-a-client-relationship/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://2.gravatar.com/avatar/8fc1505e270caa7b01e65478aab41e61fdca25f2a3ebcd465a528a0f664dd21d?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kernel128</media:title>
		</media:content>
	</item>
		<item>
		<title>Operant Conditioning</title>
		<link>https://antonvishnyak.wordpress.com/2007/04/23/operant-conditioning/</link>
					<comments>https://antonvishnyak.wordpress.com/2007/04/23/operant-conditioning/#respond</comments>
		
		<dc:creator><![CDATA[Anton Vishnyak]]></dc:creator>
		<pubDate>Mon, 23 Apr 2007 15:07:57 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">http://antonvishnyak.wordpress.com/2007/04/23/operant-conditioning</guid>

					<description><![CDATA[In my previous article, Good Insights On Managing Knowledge Workers, I concluded that &#34;Empowering an employee is the only way to harness the talent that the company has and is a very challenging feat.&#34;  However, this is only the first step in the process.  Since posting that entry, I have been researching the psychology of [&#8230;]]]></description>
										<content:encoded><![CDATA[<div id="msgcns!E2069F5E4B3A2575!191" class="bvMsg">
<p>In my previous article, <a title="Good Insights On Managing Knowledge Workers" href="http://theitconsultant.spaces.live.com/blog/cns!E2069F5E4B3A2575!185.entry">Good Insights On Managing Knowledge Workers</a>, I concluded that &quot;Empowering an employee is the only way to harness the talent that the company has and is a very challenging feat.&quot;  However, this is only the first step in the process.  Since posting that entry, I have been researching the psychology of motivation.</p>
<p>In psychology, the process of learning new behaviors or responses as a result of their consequences is called conditioning.  I believe that the average employee has been conditioned to follow orders, to keep quiet, and do the minimum amount of work.  Through their experiences at previous jobs or projects, employees have picked up an attitude that prevents them from accepting empowerment even if given full authority to make their own decisions.</p>
<p>The first job of a project manager in this situation is to condition the employee to respond positively to empowerment.  The PM has to encourage positive behaviors and diminish the negative ones.  There are four commonly accepted methods of reinforcement to do just that:</p>
<p> </p>
<ul>
<li><strong>Positive Reinforcement</strong>. Something positive provided after a response in order to increase the probability of that response occurring in the future. For example, recognizing that an employee has stayed late last night and saying &quot;thank you.&quot;  The most common types of positive reinforcement or praise and rewards, and most of us have experienced this as both the giver and receiver.
<li><strong>Negative Reinforcement</strong>. Think of negative reinforcement as taking something negative away in order to increase a response. For example, nagging the employee to fill out his weekly timesheet on time until they start doing it automatically. The elimination of this negative stimulus is reinforcing and will likely increase the chances that the employee will fill out their timesheet next week.
<li><strong>Punishment</strong>. Punishment refers to adding something aversive in order to decrease a behavior. The most common example of this is disciplining an employee for being late. The reason we do this is because the employee begins to associate being punished with the negative behavior. The punishment is not liked and therefore to avoid it, he or she will stop behaving in that manner.
<li><strong>Extinction</strong>. When you remove something in order to decrease a behavior, this is called extinction. You are taking something away so that a response is decreased.  An example of this is removing an employees internet access to discourage them from playing games during work time.</li>
</ul>
<p>Being aware of how our actions reinforce behaviors is something that project managers need to keep in mind.  Have you ever let an employee slide with a poor excuse in a status meeting?  If you have, you just used positive reinforcement with an undesired behavior.</p>
<p> </p>
<p><div style="display:inline;margin:0;padding:0;">Technorati tags: <a href="http://technorati.com/tags/Knowledge Workers" rel="tag">Knowledge Workers</a>, <a href="http://technorati.com/tags/Motivation" rel="tag">Motivation</a>, <a href="http://technorati.com/tags/Operant conditioning" rel="tag">Operant conditioning</a>, <a href="http://technorati.com/tags/Positive reinforcement" rel="tag">Positive reinforcement</a>, <a href="http://technorati.com/tags/Management" rel="tag">Management</a>, <a href="http://technorati.com/tags/Project management" rel="tag">Project management</a></div>
</p>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://antonvishnyak.wordpress.com/2007/04/23/operant-conditioning/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://2.gravatar.com/avatar/8fc1505e270caa7b01e65478aab41e61fdca25f2a3ebcd465a528a0f664dd21d?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kernel128</media:title>
		</media:content>
	</item>
		<item>
		<title>Good Insights On Managing Knowledge Workers</title>
		<link>https://antonvishnyak.wordpress.com/2007/04/19/good-insights-on-managing-knowledge-workers/</link>
					<comments>https://antonvishnyak.wordpress.com/2007/04/19/good-insights-on-managing-knowledge-workers/#comments</comments>
		
		<dc:creator><![CDATA[Anton Vishnyak]]></dc:creator>
		<pubDate>Thu, 19 Apr 2007 15:05:16 +0000</pubDate>
				<category><![CDATA[Project Management]]></category>
		<guid isPermaLink="false">http://antonvishnyak.wordpress.com/2007/04/19/good-insights-on-managing-knowledge-workers</guid>

					<description><![CDATA[Raven at Raven&#8217;s Brain has posted a great quote regarding Good Insights On Managing Knowledge Workers that I think applies even more to the litigation support industry.  Litigation support is part of the information and support economy and most of the people in this industry are knowledge workers.  Knowledge workers are people who add value through their [&#8230;]]]></description>
										<content:encoded><![CDATA[<div id="msgcns!E2069F5E4B3A2575!185" class="bvMsg">
<p><a href="mailto:raven_young@hotmail.com">Raven</a> at <a href="http://ravenyoung.spaces.live.com/">Raven&#8217;s Brain</a> has posted a great quote regarding <a href="http://ravenyoung.spaces.live.com/blog/cns!17376F4C11A91E0E!3465.entry"><strong>Good Insights On Managing Knowledge Workers</strong></a> that I think applies even more to the litigation support industry.  Litigation support is part of the information and support economy and most of the people in this industry are knowledge workers.  Knowledge workers are people who add value through their intellect rather than physical attributes.  Because knowledge workers use intellect rather than brawn, old techniques of managing users by just assigning tasks and jobs has become harder.  Workers are no longer doing one task at one workstation.  They have valuable skills that should be fostered and used in the best possible combination.  </p>
<blockquote>
<p>&quot;A good manager doesn&#8217;t tell people <em>what </em>to do or how to accomplish their tasks, but removes roadblocks and makes the way clear [for employees to be] more productive.  [Another] important role that managers have is to identify and grow talent.  Unfortunately, many managers don&#8217;t place enough emphasis on helping the individuals within their teams grow and improve their capabilities.  Ultimately, a manager [ONLY] succeeds when the people who reported to him grow into new capabilities and roles.&quot; &#8212; <a href="mailto:jphillips@netcentrics.com">Jeffrey Phillips</a> at <a href="http://workingsmarter.typepad.com/my_weblog/">Think Faster</a></p></blockquote>
<p>Managers who do not foster each knowledge worker&#8217;s talents or hold on to the outdated &quot;workers as resources&quot; mantra will have a hard time keeping employees motivated in this industry.  Empowering an employee is the only way to harness the talent that the company has and is a very challenging feat.  That is something that I want to explore further in future posts. </p>
<p>How do you empower your employees? </p>
<p>Read the article on the <a href="http://workingsmarter.typepad.com/my_weblog/">Think Faster </a>blog entitled &quot;<a href="http://workingsmarter.typepad.com/my_weblog/2007/04/whats_a_manager.html"><em>What&#8217;s a manager to do?</em></a>&quot;<br />Read the article on <a href="http://ravenyoung.spaces.live.com/">Raven&#8217;s Brain</a> blog entitled &quot;<em><a href="http://ravenyoung.spaces.live.com/blog/cns!17376F4C11A91E0E!3465.entry">Good Insights On Managing Knowledge Workers</a></em>&quot; </p>
<p>Tags: <a title="Link to Technorati" href="http://technorati.com/tag/Knowledge+workers" rel="tag">Knowledge Workers</a>, <a title="Link to Technorati" href="http://technorati.com/tag/IT+Management" rel="tag">IT Management</a>, <a title="Link to Technorati" href="http://technorati.com/tag/management" rel="tag">Management</a>, <a href="http://technorati.com/tag/litigation+support">Litigation Support </a></p>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://antonvishnyak.wordpress.com/2007/04/19/good-insights-on-managing-knowledge-workers/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
		
		<media:content url="https://2.gravatar.com/avatar/8fc1505e270caa7b01e65478aab41e61fdca25f2a3ebcd465a528a0f664dd21d?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kernel128</media:title>
		</media:content>
	</item>
		<item>
		<title>Gathering requirements for small projects</title>
		<link>https://antonvishnyak.wordpress.com/2007/04/18/gathering-requirements-for-small-projects/</link>
					<comments>https://antonvishnyak.wordpress.com/2007/04/18/gathering-requirements-for-small-projects/#respond</comments>
		
		<dc:creator><![CDATA[Anton Vishnyak]]></dc:creator>
		<pubDate>Wed, 18 Apr 2007 21:02:39 +0000</pubDate>
				<category><![CDATA[Project Management]]></category>
		<guid isPermaLink="false">http://antonvishnyak.wordpress.com/2007/04/18/gathering-requirements-for-small-projects</guid>

					<description><![CDATA[In my new role as a Director of Project Management at Legal Science, I have the responsibility of setting up our project management practices and helping our customers manage their litigation support projects.  A few pain points that I hear often from our customers are the ambiguity of requirements, the short duration of projects, and [&#8230;]]]></description>
										<content:encoded><![CDATA[<div id="msgcns!E2069F5E4B3A2575!184" class="bvMsg">
<div>
<p>In my new role as a Director of Project Management at <a title="Legal Science LLC" href="http://www.caselawg.com/" target="_blank">Legal Science</a>, I have the responsibility of setting up our project management practices and helping our customers manage their litigation support projects.  A few pain points that I hear often from our customers are the ambiguity of requirements, the short duration of projects, and the fast pace of litigation support projects.  In fact, many have given up on requirements gathering and accept the fact that 50% of their projects will be over budget, low quality, or over schedule.</p>
<p>However, all is not lost.  Proper requirements gathering can set a project in the right course from the very beginning.  Unfortunately, requirements gathering is a tricky process fraught with red herrings.  Sometimes you interview a stakeholder and write down exactly what is said only to find out that is not what they intended.</p>
<p>The trick here is to find out what the client &quot;intends to do with the product&quot; not how they think the project should be done.  This is sometimes called the &quot;business requirements.&quot;  Many vendors in  the litigation support space jump right into checklists with options for stapling papers this way or that way.  But in doing so, they miss the more important point of what the customer intends to do with the end result of the project.  They are trying to find out the &quot;technical requirements&quot; before they even understand why they are undertaking a project.</p>
<p>Here is my list of best practices for gathering requirements for small projects:</p>
<ul>
<li>Use the following techniques to solicit requirements as fully as possible:
<ul>
<li>Interviews &#8211; Solicit requirements from project stakeholders.  However, take into account each person&#8217;s bias and background.  Use context-free questions, ones that do not favor one answer over another, to avoid bias
<li>Document Analysis &#8211; Any documentation generated at the beginning of a project is a treasure trove for requirements gathering.  These will give you a good foundation on which to build upon
<li>Brainstorming &#8211; Sometimes the stakeholder is not exactly sure what the requirements should be.  In this case, a brainstorming session will help flesh out ideas and potential uses of the end product</ul>
<li>Establish a process for evaluating and controlling changes to requirements.  This is not to discourage changes, but to fully understand the impact of a change and notify all of the appropriate parties of changes in scope
<li>Prioritize!  Some requirements are more important than others, if this is so, state it explicitly.  Nothing is worse than getting a project late because a minor requirement was slowing down important work
<li>Consider an incremental approach when requirements are volatile.  You don&#8217;t have to do the entire project at once
<li>Distribute requirements to all parties of the project.  This way everyone knows what needs to be done and why.  This is especially important so that the stakeholders see and verify your understanding of the project
<li>Check your final deliverables against the requirements</ul>
<p>If you have any horror stories or best practices regarding requirements gathering, leave a comment!</p>
<p>Good follow up post by Harrison Flakker at <a href="http://www.caselawg.com/wordpress/">Select Notes From Caselawg</a> entitled &quot;<a style="font-style:italic;" href="http://www.caselawg.com/wordpress/?p=11">How to gather requirements from an attorney walking backwards</a>&quot;</p>
<div>Technorati tags: <a href="http://technorati.com/tags/requirements" rel="tag">requirements</a>, <a href="http://technorati.com/tags/requirement gathering" rel="tag">requirement gathering</a>, <a href="http://technorati.com/tags/best practices" rel="tag">best practices</a>, <a href="http://technorati.com/tags/project management" rel="tag">project management</a>, <a href="http://technorati.com/tags/small projects" rel="tag">small projects</a>, <a href="http://technorati.com/tags/litigation support" rel="tag">litigation support</a></div>
</div>
</div>
]]></content:encoded>
					
					<wfw:commentRss>https://antonvishnyak.wordpress.com/2007/04/18/gathering-requirements-for-small-projects/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://2.gravatar.com/avatar/8fc1505e270caa7b01e65478aab41e61fdca25f2a3ebcd465a528a0f664dd21d?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kernel128</media:title>
		</media:content>
	</item>
		<item>
		<title>Small Project Management</title>
		<link>https://antonvishnyak.wordpress.com/2006/12/11/small-project-management/</link>
					<comments>https://antonvishnyak.wordpress.com/2006/12/11/small-project-management/#respond</comments>
		
		<dc:creator><![CDATA[Anton Vishnyak]]></dc:creator>
		<pubDate>Mon, 11 Dec 2006 18:56:28 +0000</pubDate>
				<category><![CDATA[Project Management]]></category>
		<guid isPermaLink="false">http://antonvishnyak.wordpress.com/2006/12/11/small-project-management</guid>

					<description><![CDATA[As a consultant, I visit many organizations and speak to them about project management. A large majority of managers who deal with small initiatives complain that project management methodologies are overkill for their project/organization. Furthermore, some use this logic to justify their lack of following any sort of project management processes or techniques. It is [&#8230;]]]></description>
										<content:encoded><![CDATA[<div id="msgcns!E2069F5E4B3A2575!179" class="bvMsg">As a consultant, I visit many organizations and speak to them about project management.  A large majority of managers who deal with small initiatives complain that project management methodologies are overkill for their project/organization.  Furthermore, some use this logic to justify their lack of following any sort of project management processes or techniques.  It is with these Project Managers in mind that I read Tom L. Barnett&#8217;s <a style="font-weight:bold;font-style:italic;" href="http://www.computerworld.com/action/article.do?command=viewArticleBasic&amp;taxonomyName=project_management&amp;articleId=270773&amp;taxonomyId=73">A Small-Project Playbook</a>  article on ComputerWorld.  An article that promised to find the solution for the manager of small projects.</p>
<p>In the article, Tom proposes that in such circumstances a Project Manager can use his Playbook &quot;tool&quot; to manage the project.  The &quot;tool,&quot; however, is nothing more than a chart consisting of &quot;eight columns: Task Name, Description, Due Date, Owner, Issues, Deliverables, To, and Waiting On.&quot;  Tom says this allows him to replace the WBS, meeting agendas, resource assignment matrix, and status reports.</p>
<p>However, I view this as a dangerous proposition when speaking to clients that are already weary of project management.  The playbook is <span style="font-style:italic;font-weight:bold;">just a tool</span> that will be rather useless in the hands of a person that does not already know the project management concepts that are used to populate it.  Project management is a set of processes, not tools.  Furthermore, it serves as a poor introduction to project management techniques for the beginner.  Rather than learning proper project management and using critical thought to apply the appropriate techniques, beginners will learn bad habits right from the start.  The tool does not even encourage a small project manager to split their activities into initiation, planning, execution, and closing.  It transforms a project manager into a task master.</p>
<p>Rather than taking the less-than-ideal approach, beginners should focus on light-weight management methodologies like <a href="http://en.wikipedia.org/wiki/SCRUM">SCRUM</a>, an agile methodology focused on small, cross-functional teams.  From this, they will learn the benefits of setting up and following processes without burdening the organization with heavy frameworks.  New project managers need to understand that success is more dependent on critical thinking and process than tools and technology.  The bottom line is: neither the playbook nor Microsoft Project will make one a project manager.</p>
<p>For more information about Agile methodologies, see <a href="mailto:raven_young@hotmail.com">Raven</a>&#8216;s article <a style="font-weight:bold;font-style:italic;" href="http://ravenyoung.spaces.live.com/blog/cns!17376F4C11A91E0E!2497.entry">Good List of Agile Program/Project Management Resources</a>.<span style="text-decoration:underline;"></span></div>
]]></content:encoded>
					
					<wfw:commentRss>https://antonvishnyak.wordpress.com/2006/12/11/small-project-management/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://2.gravatar.com/avatar/8fc1505e270caa7b01e65478aab41e61fdca25f2a3ebcd465a528a0f664dd21d?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kernel128</media:title>
		</media:content>
	</item>
		<item>
		<title>Expectations and Violations</title>
		<link>https://antonvishnyak.wordpress.com/2006/12/05/expectations-and-violations/</link>
					<comments>https://antonvishnyak.wordpress.com/2006/12/05/expectations-and-violations/#respond</comments>
		
		<dc:creator><![CDATA[Anton Vishnyak]]></dc:creator>
		<pubDate>Tue, 05 Dec 2006 20:55:02 +0000</pubDate>
				<category><![CDATA[Project Management]]></category>
		<guid isPermaLink="false">http://antonvishnyak.wordpress.com/2006/12/05/expectations-and-violations</guid>

					<description><![CDATA[In his article &#34;Expectations and Violations,&#34; Paul Glen discusses the human side of project failure. We consultants are often called in to a company as a last resort to save a failing project. Typically, this happens after a project has missed deadlines. The company realizes that the imminent failure of the project is not due [&#8230;]]]></description>
										<content:encoded><![CDATA[<div id="msgcns!E2069F5E4B3A2575!178" class="bvMsg">In his article &quot;<a style="font-weight:bold;font-style:italic;" href="http://www.computerworld.com/action/article.do?command=printArticleBasic&amp;articleId=273895">Expectations and Violations</a>,&quot; <a href="mailto:info@paulglen.com">Paul Glen</a> discusses the human side of project failure.  We consultants are often called in to a company as a last resort to save a failing project.  Typically, this happens after a project has missed deadlines.  The company realizes that the imminent failure of the project is not due to poor schedule or cost management but to human and business relationships.</p>
<div>&quot;It becomes clear that feelings have been hurt, mutual expectations have<br />
been violated and relationships have been strained, broken or severed.<br />
And these problems can’t be resolved with schedule changes, plan<br />
revisions or budget extensions.<br />[&#8230; In situations where projects miss deadlines or go over budget, strained relationships are perfectly normal.]  They result from violated expectations about what<br />
will be done, how and when it will happen, how people will relate to<br />
one another and what common values will be held. </p>
<p> The problem isn’t that expectations are violated over the<br />
course of projects; it’s that we believe that they shouldn’t be. But<br />
expectations are always violated. It is inevitable. Projects all start<br />
in ignorance and confusion and are completed in the relative clarity of<br />
hindsight. The process of completing projects is the process of<br />
learning. As we learn, assumptions change and feelings get hurt. </p>
<p> If you want to avoid calling me for a crisis intervention<br />
(not that I mind), think about the human issues, the mutual<br />
expectations and their violations at the first sign of trouble, rather<br />
than waiting until ill feelings become entrenched problems.&quot; &#8212; Paul Glen</div>
<p>I completely agree with Paul on this issue.  It is nearly impossible to avoid poor project performance without considering human issues and expectations.  Functional managers have dealt with human issues far longer than pure project managers.  However,  we must do our best to manager people as much as cost, schedule, and scope.</p>
<p>Do you have examples of projects that have failed because of human issues?  Leave a comment.</div>
]]></content:encoded>
					
					<wfw:commentRss>https://antonvishnyak.wordpress.com/2006/12/05/expectations-and-violations/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		
		<media:content url="https://2.gravatar.com/avatar/8fc1505e270caa7b01e65478aab41e61fdca25f2a3ebcd465a528a0f664dd21d?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">kernel128</media:title>
		</media:content>
	</item>
	</channel>
</rss>
