<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Adam Anderly</title><description>Adam Anderly is the Founding Principal of Saint Systems and the builder of PubKeep. Solution architect, cloud architect and DevSecOps engineer.</description><link>https://anderly.com/</link><item><title>Publisher is gone. Here’s why I built PubKeep.</title><link>https://anderly.com/2026/10/01/why-i-built-pubkeep/</link><guid isPermaLink="true">https://anderly.com/2026/10/01/why-i-built-pubkeep/</guid><description>Microsoft pulled Publisher from Microsoft 365 on October 1. My mom called first. This is why I built PubKeep, the desktop app that keeps your .pub files editable.</description><pubDate>Thu, 01 Oct 2026 18:40:09 GMT</pubDate><content:encoded>&lt;p&gt;It started with a phone call from my mom.&lt;/p&gt;
&lt;p&gt;Microsoft had announced it was removing Publisher from Microsoft 365, and she, my aunt, and my cousin all had years of files made in it. Newsletters, wedding programs, labels, the family photo calendar we got every Christmas. She wanted to know if I could help them get their files out before the app went away.&lt;/p&gt;
&lt;p&gt;I had not used Publisher in years. But I knew exactly what she meant, because I had used it for our own wedding program and thank-you cards. Publisher was the tool ordinary people used to make something that came out looking finished. And it was a tool you bought once.&lt;/p&gt;
&lt;p&gt;The more I looked, the bigger the problem got. Church offices build the weekly bulletin from last week’s .pub file. Schools have years of newsletters and certificates. Nonprofits, small businesses, the volunteer who makes the monthly newsletter. The suggested replacements are good tools, but they are subscriptions, and none of them open the files people already have. Everyone was being told to start over.&lt;/p&gt;
&lt;p&gt;So I started building.&lt;/p&gt;
&lt;h2&gt;First, save the files&lt;/h2&gt;
&lt;p&gt;The urgent problem was the archive. If Publisher was going away, people needed a way to turn years of .pub files into something they could always open.&lt;/p&gt;
&lt;p&gt;The first thing I built was a converter: drop a whole folder of .pub files and get exact PDFs back, page for page. My family tried it the first day. My mom’s reply was “Oh hallelujah!”&lt;/p&gt;
&lt;p&gt;That saved the past. It didn’t help with next week’s bulletin.&lt;/p&gt;
&lt;h2&gt;Then, keep editing&lt;/h2&gt;
&lt;p&gt;A PDF only saves what you’ve already made. The real question was why Publisher users should have to stop publishing at all.&lt;/p&gt;
&lt;p&gt;So I built PubKeep, a desktop app for Windows and Mac that opens your .pub files and keeps them editable. The same text boxes, master pages, and fold-over booklets you already use, without Publisher on the computer. No converting first, and nothing to rebuild.&lt;/p&gt;
&lt;p&gt;It’s a one-time purchase, not a subscription. You buy it once and it keeps working. And it saves to .pubk, an open format you can always get your work out of. After watching people lose access to their own work, I wasn’t going to build another lock-in.&lt;/p&gt;
&lt;h2&gt;The people who helped build it&lt;/h2&gt;
&lt;p&gt;Before launch, more than 1,100 organizations signed up for early access, most of them churches. They opened their own bulletins and newsletters, told us what was missing, and sent the files that didn’t come through right so we could fix them.&lt;/p&gt;
&lt;p&gt;Some of what they wrote back has stuck with me. One church secretary said she got more done in 45 minutes than she had in other programs all week. An author told us she had thousands of Publisher files from 30 years of work, and that PubKeep was better than she had dared hope for.&lt;/p&gt;
&lt;h2&gt;Launch&lt;/h2&gt;
&lt;p&gt;PubKeep went on sale September 30, the day before Microsoft pulled Publisher from Microsoft 365, with a free 7-day trial.&lt;/p&gt;
&lt;h2&gt;What’s next&lt;/h2&gt;
&lt;p&gt;Support for the perpetual versions of Publisher ends October 13, so the next few weeks are about helping everyone who still depends on it. We keep widening what PubKeep opens, and the files people send us decide what we work on next.&lt;/p&gt;
&lt;p&gt;If you or someone you know has a pile of .pub files, PubKeep is at &lt;a href=&quot;https://pubkeep.com&quot;&gt;pubkeep.com&lt;/a&gt;, and the free trial needs no card.&lt;/p&gt;
&lt;p&gt;And if your mom calls about her Publisher files, now you know what to tell her.&lt;/p&gt;
</content:encoded><category>Uncategorized</category></item><item><title>Cross-Cutting Concerns with MediatR Pipeline Behaviors</title><link>https://anderly.com/2019/12/12/cross-cutting-concerns-with-mediatr-pipeline-behaviors/</link><guid isPermaLink="true">https://anderly.com/2019/12/12/cross-cutting-concerns-with-mediatr-pipeline-behaviors/</guid><description>I’ve recently been exploring MediatR Pipeline Behaviors and cross-cutting concerns (logging, validation, security, transactions) but also wanted to tackle some performance and resilience scenarios that may not always apply to every request/command (retry, fallback and caching). Here are some gists that tackle these concerns: Caching Behavior (using ASP.NET Core IDistributedCache): For caching, I’m using a…</description><pubDate>Thu, 12 Dec 2019 16:41:14 GMT</pubDate><content:encoded>&lt;p&gt;I’ve recently been exploring &lt;a href=&quot;https://github.com/jbogard/MediatR&quot;&gt;MediatR&lt;/a&gt; Pipeline &lt;a href=&quot;https://github.com/jbogard/MediatR/wiki/Behaviors&quot;&gt;Behaviors&lt;/a&gt; and cross-cutting concerns (logging, validation, security, transactions) but also wanted to tackle some performance and resilience scenarios that may not always apply to every request/command (retry, fallback and caching).&lt;/p&gt;
&lt;p&gt;Here are some gists that tackle these concerns:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Caching Behavior (using ASP.NET Core &lt;a href=&quot;https://docs.microsoft.com/en-us/aspnet/core/performance/caching/distributed?view=aspnetcore-3.1&quot;&gt;IDistributedCache&lt;/a&gt;):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For caching, I’m using a separately defined CachePolicy similar to a &lt;a href=&quot;https://fluentvalidation.net/&quot;&gt;FluentValidation&lt;/a&gt; Validator class.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class CacheService : ICache
	{
		private readonly string _keyPrefix;
		private readonly IDistributedCache _cache;
		private readonly IConfiguration _config;

		public CacheService(IDistributedCache cache, IConfiguration config)
		{
			_cache = cache;
			_config = config;
			var keyPrefix = _config[&quot;CacheKeyPrefix&quot;];
			_keyPrefix = keyPrefix ?? typeof(CacheService).FullName;
		}

		public string GetCacheKey(string key)
		{
			return MakeKey(key);
		}

		public async Task&amp;lt;T&amp;gt; GetAsync&amp;lt;T&amp;gt;(string key, CancellationToken token = default)
		{
			return await GetInternalAsync&amp;lt;T&amp;gt;(key, token);
		}

		public async Task&amp;lt;T&amp;gt; GetOrCreateAsync&amp;lt;T&amp;gt;(string key, Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; factory, CancellationToken token = default)
		{
			return await GetOrCreateInternalAsync&amp;lt;T&amp;gt;(key, null, null, null, factory, token);
		}

		public async Task&amp;lt;T&amp;gt; GetOrCreateAsync&amp;lt;T&amp;gt;(string key, TimeSpan slidingExpiration, Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; factory, CancellationToken token = default)
		{
			return await GetOrCreateInternalAsync&amp;lt;T&amp;gt;(key, slidingExpiration, null, null, factory, token);
		}

		public async Task&amp;lt;T&amp;gt; GetOrCreateAsync&amp;lt;T&amp;gt;(string key, DateTime absoluteExpiration, Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; factory, CancellationToken token = default)
		{
			return await GetOrCreateInternalAsync&amp;lt;T&amp;gt;(key, null, absoluteExpiration, null, factory, token);
		}

		public async Task&amp;lt;T&amp;gt; GetOrCreateAsync&amp;lt;T&amp;gt;(string key, TimeSpan slidingExpiration, DateTime absoluteExpiration, Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; factory, CancellationToken token = default)
		{
			return await GetOrCreateInternalAsync&amp;lt;T&amp;gt;(key, slidingExpiration, absoluteExpiration, null, factory, token);
		}

		public async Task&amp;lt;T&amp;gt; GetOrCreateAsync&amp;lt;T&amp;gt;(string key, TimeSpan slidingExpiration, TimeSpan absoluteExpirationRelativeToNow, Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; factory, CancellationToken token = default)
		{
			return await GetOrCreateInternalAsync&amp;lt;T&amp;gt;(key, slidingExpiration, null, absoluteExpirationRelativeToNow, factory, token);
		}

		public async Task&amp;lt;T&amp;gt; GetOrCreateAsync&amp;lt;T&amp;gt;(string key, TimeSpan? slidingExpiration, DateTime? absoluteExpiration, TimeSpan? absoluteExpirationRelativeToNow, Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; factory, CancellationToken token = default)
		{
			return await GetOrCreateInternalAsync&amp;lt;T&amp;gt;(key, slidingExpiration, absoluteExpiration, absoluteExpirationRelativeToNow, factory, token);
		}

		public async Task SetAsync&amp;lt;T&amp;gt;(string key, T value, CancellationToken token = default)
		{
			await SetInternalAsync(key, value, null, null, null, token);
		}

		public async Task SetAsync&amp;lt;T&amp;gt;(string key, T value, DateTime absoluteExpiration,
			CancellationToken token = default)
		{
			await SetInternalAsync(key, value, null, absoluteExpiration, null, token);
		}

		public async Task SetAsync&amp;lt;T&amp;gt;(string key, T value, TimeSpan slidingExpiration,
			CancellationToken token = default)
		{
			await SetInternalAsync(key, value, slidingExpiration, null, null, token);
		}

		public async Task SetAsync&amp;lt;T&amp;gt;(string key, T value, TimeSpan? slidingExpiration, DateTime? absoluteExpiration,
			CancellationToken token = default)
		{
			await SetInternalAsync(key, value, slidingExpiration, absoluteExpiration, null, token);
		}

		public async Task SetAsync&amp;lt;T&amp;gt;(string key, T value, TimeSpan? slidingExpiration, TimeSpan? absoluteExpirationRelativeToNow,
			CancellationToken token = default)
		{
			await SetInternalAsync(key, value, slidingExpiration, null, absoluteExpirationRelativeToNow, token);
		}

		public async Task SetAsync&amp;lt;T&amp;gt;(string key, T value, TimeSpan? slidingExpiration, DateTime? absoluteExpiration,
			TimeSpan? absoluteExpirationRelativeToNow, CancellationToken token = default)
		{
			await SetInternalAsync(key, value, slidingExpiration, absoluteExpiration, absoluteExpirationRelativeToNow, token);
		}

		public async Task RefreshAsync(string key, CancellationToken token = default)
		{
			await _cache.RefreshAsync(key, token);
		}

		public async Task RemoveAsync(string key, CancellationToken token = default)
		{
			await _cache.RemoveAsync(key, token);
		}

		private string MakeKey(string key)
		{
			return $&quot;{(string.IsNullOrWhiteSpace(_keyPrefix) ? &quot;&quot; : _keyPrefix + &quot;:&quot;)}{key}&quot;;
		}

		private async Task&amp;lt;T&amp;gt; GetInternalAsync&amp;lt;T&amp;gt;(string key, CancellationToken token = default)
		{
			return await _cache.GetAsync&amp;lt;T&amp;gt;(MakeKey(key), token);
		}

		private async Task&amp;lt;T&amp;gt; GetOrCreateInternalAsync&amp;lt;T&amp;gt;(string key, TimeSpan? slidingExpiration, DateTime? absoluteExpiration, TimeSpan? absoluteExpirationRelativeToNow, Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; factory, CancellationToken token = default)
		{
			var value = await GetInternalAsync&amp;lt;T&amp;gt;(key, token);

			if (value != null) return value;

			value = await factory();

			if (value != null)
			{
				await SetInternalAsync&amp;lt;T&amp;gt;(key, value, slidingExpiration, absoluteExpiration, absoluteExpirationRelativeToNow, token);
			}

			return value;
		}

		private async Task SetInternalAsync&amp;lt;T&amp;gt;(string key, T value, TimeSpan? slidingExpiration, DateTime? absoluteExpiration, TimeSpan? absoluteExpirationRelativeToNow,
			CancellationToken token = default)
		{
			var cacheEntryOptions = new DistributedCacheEntryOptions();
			if (slidingExpiration.HasValue)
			{
				cacheEntryOptions.SlidingExpiration = slidingExpiration.Value;
			}

			if (absoluteExpiration.HasValue)
			{
				cacheEntryOptions.AbsoluteExpiration = absoluteExpiration.Value;
			}

			if (absoluteExpirationRelativeToNow.HasValue)
			{
				cacheEntryOptions.AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow.Value;
			}

			if (!slidingExpiration.HasValue &amp;amp;&amp;amp; !absoluteExpiration.HasValue &amp;amp;&amp;amp; !absoluteExpirationRelativeToNow.HasValue)
			{
				cacheEntryOptions.SetSlidingExpiration(TimeSpan.FromSeconds(30));
				cacheEntryOptions.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5);
				//cacheEntryOptions.SetAbsoluteExpiration(DateTime.UtcNow.AddMinutes(5));
			}

			await _cache.SetAsync&amp;lt;T&amp;gt;(MakeKey(key), value, cacheEntryOptions, token);
		}

	}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// MediatR Caching Pipeline Behavior
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;typeparam name=&quot;TRequest&quot;&amp;gt;&amp;lt;/typeparam&amp;gt;
/// &amp;lt;typeparam name=&quot;TResponse&quot;&amp;gt;&amp;lt;/typeparam&amp;gt;
public class CachingBehavior&amp;lt;TRequest, TResponse&amp;gt; : IPipelineBehavior&amp;lt;TRequest, TResponse&amp;gt; where TRequest : IRequest&amp;lt;TResponse&amp;gt;
{
    private readonly IEnumerable&amp;lt;ICachePolicy&amp;lt;TRequest, TResponse&amp;gt;&amp;gt; _cachePolicies;
    // ICache is a helper wrapper over IDistributedCache that adds some read-through cache methods, etc.
    private readonly ICache _cache;
    private readonly ILogger&amp;lt;CachingBehavior&amp;lt;TRequest, TResponse&amp;gt;&amp;gt; _logger;

    public CachingBehavior(ICache cache, ILogger&amp;lt;CachingBehavior&amp;lt;TRequest, TResponse&amp;gt;&amp;gt; logger, IEnumerable&amp;lt;ICachePolicy&amp;lt;TRequest, TResponse&amp;gt;&amp;gt; cachePolicies)
    {
        _cache = cache;
        _logger = logger;
        _cachePolicies = cachePolicies;
    }

    public async Task&amp;lt;TResponse&amp;gt; Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate&amp;lt;TResponse&amp;gt; next)
    {
        var cachePolicy = _cachePolicies.FirstOrDefault();
        if (cachePolicy == null)
        {
            // No cache policy found, so just continue through the pipeline
            return await next();
        }
        var cacheKey = cachePolicy.GetCacheKey(request);
        var cachedResponse = await _cache.GetAsync&amp;lt;TResponse&amp;gt;(cacheKey, cancellationToken);
        if (cachedResponse != null)
        {
            _logger.LogDebug($&quot;Response retrieved {typeof(TRequest).FullName} from cache. CacheKey: {cacheKey}&quot;);
            return cachedResponse;
        }

        var response = await next();
        _logger.LogDebug($&quot;Caching response for {typeof(TRequest).FullName} with cache key: {cacheKey}&quot;);

        await _cache.SetAsync(cacheKey, response, cachePolicy.SlidingExpiration, cachePolicy.AbsoluteExpiration, cachePolicy.AbsoluteExpirationRelativeToNow, cancellationToken);
        return response;
    }
 }
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;public class Details
{
  
    // Query definition
    public class Query : IRequest&amp;lt;Models.Customer&amp;gt;
    {
        [FromRoute]
        public string CustomerNumber { get; set; }
    }
    
    // Simply defining a CachePolicy for ICachePolicy&amp;lt;TRequest,TResponse&amp;gt; sets up caching
    // similar to setting up a FluentValidation Validator that inherits from AbstractValidator&amp;lt;TRequest&amp;gt;.
    // This could be in the same file or in a separate file, but doesn&apos;t clutter up the &quot;Handler&quot;.
    public class CachePolicy : ICachePolicy&amp;lt;Query, Models.Customer&amp;gt;
    {
        // Optionally, change defaults
        public TimeSpan? AbsoluteExpirationRelativeToNow =&amp;gt; TimeSpan.FromMinutes(10);
        public TimeSpan? SlidingExpiration =&amp;gt; TimeSpan.FromMinutes(1);

        // Optionally, provide a different implementation here. By default the CacheKey will be in the following format:
        //     Query{CustomerNumber:001425}
        public string GetCacheKey(Query query)
        {
            return $&quot;Customers.{query.CustomerNumber}&quot;;
        }
    }
    
    // Query Handler
    public class Handler : IRequestHandler&amp;lt;Query, Models.Customer&amp;gt;
    {
        private readonly CustomerContext _db;
        private readonly IConfigurationProvider _configuration;

        public Handler(CustomerContext db, IConfigurationProvider configuration)
        {
            _db = db;
            _configuration = configuration;
        }

        public async Task&amp;lt;Models.Customer&amp;gt; Handle(Query message, CancellationToken token)
        {
            return await _db.Customers.Where(c =&amp;gt; c.Number == message.CustomerNumber)
                .ProjectTo&amp;lt;Models.Customer&amp;gt;(_configuration)
                .FirstOrDefaultAsync(token);
        }
    }
    
   }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;public interface ICache
	{
		string GetCacheKey(string key);

		/// &amp;lt;summary&amp;gt;Gets a value with the given key.&amp;lt;/summary&amp;gt;
		/// &amp;lt;param name=&quot;key&quot;&amp;gt;A string identifying the requested value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;token&quot;&amp;gt;Optional. The &amp;lt;see cref=&quot;T:System.Threading.CancellationToken&quot; /&amp;gt; used to propagate notifications that the operation should be canceled.&amp;lt;/param&amp;gt;
		/// &amp;lt;returns&amp;gt;The &amp;lt;see cref=&quot;T:System.Threading.Tasks.Task&quot; /&amp;gt; that represents the asynchronous operation, containing the located value or null.&amp;lt;/returns&amp;gt;
		Task&amp;lt;T&amp;gt; GetAsync&amp;lt;T&amp;gt;(string key, CancellationToken token = default);

		Task&amp;lt;T&amp;gt; GetOrCreateAsync&amp;lt;T&amp;gt;(
			string key,
			Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; factory,
			CancellationToken token = default);

		Task&amp;lt;T&amp;gt; GetOrCreateAsync&amp;lt;T&amp;gt;(
			string key,
			TimeSpan slidingExpiration,
			Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; factory,
			CancellationToken token = default);

		Task&amp;lt;T&amp;gt; GetOrCreateAsync&amp;lt;T&amp;gt;(
			string key,
			DateTime absoluteExpiration,
			Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; factory,
			CancellationToken token = default);

		Task&amp;lt;T&amp;gt; GetOrCreateAsync&amp;lt;T&amp;gt;(
			string key,
			TimeSpan slidingExpiration,
			DateTime absoluteExpiration,
			Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; factory,
			CancellationToken token = default);

		Task&amp;lt;T&amp;gt; GetOrCreateAsync&amp;lt;T&amp;gt;(
			string key,
			TimeSpan? slidingExpiration,
			DateTime? absoluteExpiration,
			TimeSpan? absoluteExpirationRelativeToNow,
			Func&amp;lt;Task&amp;lt;T&amp;gt;&amp;gt; factory,
			CancellationToken token = default);

		/// &amp;lt;summary&amp;gt;Sets the value with the given key.&amp;lt;/summary&amp;gt;
		/// &amp;lt;param name=&quot;key&quot;&amp;gt;A string identifying the requested value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;value&quot;&amp;gt;The value to set in the cache.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;token&quot;&amp;gt;Optional. The &amp;lt;see cref=&quot;T:System.Threading.CancellationToken&quot; /&amp;gt; used to propagate notifications that the operation should be canceled.&amp;lt;/param&amp;gt;
		/// &amp;lt;returns&amp;gt;The &amp;lt;see cref=&quot;T:System.Threading.Tasks.Task&quot; /&amp;gt; that represents the asynchronous operation.&amp;lt;/returns&amp;gt;
		Task SetAsync&amp;lt;T&amp;gt;(
			string key,
			T value,
			CancellationToken token = default);

		/// &amp;lt;summary&amp;gt;Sets the value with the given key.&amp;lt;/summary&amp;gt;
		/// &amp;lt;param name=&quot;key&quot;&amp;gt;A string identifying the requested value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;value&quot;&amp;gt;The value to set in the cache.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;absoluteExpiration&quot;&amp;gt;The cache options for the value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;token&quot;&amp;gt;Optional. The &amp;lt;see cref=&quot;T:System.Threading.CancellationToken&quot; /&amp;gt; used to propagate notifications that the operation should be canceled.&amp;lt;/param&amp;gt;
		/// &amp;lt;returns&amp;gt;The &amp;lt;see cref=&quot;T:System.Threading.Tasks.Task&quot; /&amp;gt; that represents the asynchronous operation.&amp;lt;/returns&amp;gt;
		Task SetAsync&amp;lt;T&amp;gt;(
			string key,
			T value,
			DateTime absoluteExpiration,
			CancellationToken token = default);

		/// &amp;lt;summary&amp;gt;Sets the value with the given key.&amp;lt;/summary&amp;gt;
		/// &amp;lt;param name=&quot;key&quot;&amp;gt;A string identifying the requested value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;value&quot;&amp;gt;The value to set in the cache.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;slidingExpiration&quot;&amp;gt;The cache options for the value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;token&quot;&amp;gt;Optional. The &amp;lt;see cref=&quot;T:System.Threading.CancellationToken&quot; /&amp;gt; used to propagate notifications that the operation should be canceled.&amp;lt;/param&amp;gt;
		/// &amp;lt;returns&amp;gt;The &amp;lt;see cref=&quot;T:System.Threading.Tasks.Task&quot; /&amp;gt; that represents the asynchronous operation.&amp;lt;/returns&amp;gt;
		Task SetAsync&amp;lt;T&amp;gt;(
			string key,
			T value,
			TimeSpan slidingExpiration,
			CancellationToken token = default);

		/// &amp;lt;summary&amp;gt;Sets the value with the given key.&amp;lt;/summary&amp;gt;
		/// &amp;lt;param name=&quot;key&quot;&amp;gt;A string identifying the requested value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;value&quot;&amp;gt;The value to set in the cache.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;slidingExpiration&quot;&amp;gt;The cache options for the value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;absoluteExpiration&quot;&amp;gt;The cache options for the value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;token&quot;&amp;gt;Optional. The &amp;lt;see cref=&quot;T:System.Threading.CancellationToken&quot; /&amp;gt; used to propagate notifications that the operation should be canceled.&amp;lt;/param&amp;gt;
		/// &amp;lt;returns&amp;gt;The &amp;lt;see cref=&quot;T:System.Threading.Tasks.Task&quot; /&amp;gt; that represents the asynchronous operation.&amp;lt;/returns&amp;gt;
		Task SetAsync&amp;lt;T&amp;gt;(
			string key,
			T value,
			TimeSpan? slidingExpiration,
			DateTime? absoluteExpiration,
			CancellationToken token = default);

		/// &amp;lt;summary&amp;gt;Sets the value with the given key.&amp;lt;/summary&amp;gt;
		/// &amp;lt;param name=&quot;key&quot;&amp;gt;A string identifying the requested value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;value&quot;&amp;gt;The value to set in the cache.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;slidingExpiration&quot;&amp;gt;The cache options for the value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;absoluteExpirationRelativeToNow&quot;&amp;gt;The cache options for the value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;token&quot;&amp;gt;Optional. The &amp;lt;see cref=&quot;T:System.Threading.CancellationToken&quot; /&amp;gt; used to propagate notifications that the operation should be canceled.&amp;lt;/param&amp;gt;
		/// &amp;lt;returns&amp;gt;The &amp;lt;see cref=&quot;T:System.Threading.Tasks.Task&quot; /&amp;gt; that represents the asynchronous operation.&amp;lt;/returns&amp;gt;
		Task SetAsync&amp;lt;T&amp;gt;(
			string key,
			T value,
			TimeSpan? slidingExpiration,
			TimeSpan? absoluteExpirationRelativeToNow,
			CancellationToken token = default);

		/// &amp;lt;summary&amp;gt;Sets the value with the given key.&amp;lt;/summary&amp;gt;
		/// &amp;lt;param name=&quot;key&quot;&amp;gt;A string identifying the requested value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;value&quot;&amp;gt;The value to set in the cache.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;slidingExpiration&quot;&amp;gt;The cache options for the value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;absoluteExpiration&quot;&amp;gt;The cache options for the value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;absoluteExpirationRelativeToNow&quot;&amp;gt;The cache options for the value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;token&quot;&amp;gt;Optional. The &amp;lt;see cref=&quot;T:System.Threading.CancellationToken&quot; /&amp;gt; used to propagate notifications that the operation should be canceled.&amp;lt;/param&amp;gt;
		/// &amp;lt;returns&amp;gt;The &amp;lt;see cref=&quot;T:System.Threading.Tasks.Task&quot; /&amp;gt; that represents the asynchronous operation.&amp;lt;/returns&amp;gt;
		Task SetAsync&amp;lt;T&amp;gt;(
			string key,
			T value,
			TimeSpan? slidingExpiration,
			DateTime? absoluteExpiration,
			TimeSpan? absoluteExpirationRelativeToNow,
			CancellationToken token = default);

		/// &amp;lt;summary&amp;gt;
		/// Refreshes a value in the cache based on its key, resetting its sliding expiration timeout (if any).
		/// &amp;lt;/summary&amp;gt;
		/// &amp;lt;param name=&quot;key&quot;&amp;gt;A string identifying the requested value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;token&quot;&amp;gt;Optional. The &amp;lt;see cref=&quot;T:System.Threading.CancellationToken&quot; /&amp;gt; used to propagate notifications that the operation should be canceled.&amp;lt;/param&amp;gt;
		/// &amp;lt;returns&amp;gt;The &amp;lt;see cref=&quot;T:System.Threading.Tasks.Task&quot; /&amp;gt; that represents the asynchronous operation.&amp;lt;/returns&amp;gt;
		Task RefreshAsync(string key, CancellationToken token = default);

		/// &amp;lt;summary&amp;gt;Removes the value with the given key.&amp;lt;/summary&amp;gt;
		/// &amp;lt;param name=&quot;key&quot;&amp;gt;A string identifying the requested value.&amp;lt;/param&amp;gt;
		/// &amp;lt;param name=&quot;token&quot;&amp;gt;Optional. The &amp;lt;see cref=&quot;T:System.Threading.CancellationToken&quot; /&amp;gt; used to propagate notifications that the operation should be canceled.&amp;lt;/param&amp;gt;
		/// &amp;lt;returns&amp;gt;The &amp;lt;see cref=&quot;T:System.Threading.Tasks.Task&quot; /&amp;gt; that represents the asynchronous operation.&amp;lt;/returns&amp;gt;
		Task RemoveAsync(string key, CancellationToken token = default);
	}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;// Using C# 8.0 to provide a default interface implementation.
// Optionally, could move this to an AbstractCachingPolicy like AbstractValidator.
public interface ICachePolicy&amp;lt;TRequest, TResponse&amp;gt; where TRequest : IRequest&amp;lt;TResponse&amp;gt;
{
    DateTime? AbsoluteExpiration =&amp;gt; null;
    TimeSpan? AbsoluteExpirationRelativeToNow =&amp;gt; TimeSpan.FromMinutes(5);
    TimeSpan? SlidingExpiration =&amp;gt; TimeSpan.FromSeconds(30);

    string GetCacheKey(TRequest request)
    {
        var r = new {request};
        var props = r.request.GetType().GetProperties().Select(pi =&amp;gt; $&quot;{pi.Name}:{pi.GetValue(r.request, null)}&quot;);
        return $&quot;{typeof(TRequest).FullName}{{{String.Join(&quot;,&quot;, props)}}}&quot;;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;View &lt;a href=&quot;https://gist.github.com/anderly/9ccab0c57c593975f32cce3ad6430652&quot;&gt;MediatR Caching Pipeline Behavior&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fallback Behavior (using &lt;a href=&quot;https://github.com/App-vNext/Polly&quot;&gt;Polly&lt;/a&gt;):&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For Fallback and Retry behavior, I’m using separate interfaces IFallbackHandler and IRetryableRequest to get the behavior.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class Handler : IRequestHandler&amp;lt;Query, Customer&amp;gt;, IFallbackHandler&amp;lt;Query, Customer&amp;gt;
{
    private readonly ICustomerRepository _db;
    private readonly ICustomerRepository&amp;lt;SourceSystem.Secondary&amp;gt; _db2;
    private readonly IConfigurationProvider _configuration;

    public Handler(ICustomerRepository db, ICustomerRepository&amp;lt;SourceSystem.Secondary&amp;gt; db2, IConfigurationProvider configuration)
    {
        _db = db;
        _db2 = db2;
        _configuration = configuration;
    }

    public async Task&amp;lt;Customer&amp;gt; Handle(Query message, CancellationToken token)
    {
        return await _db.GetCustomerByNumberAsync(message.CustomerNumber);
    }

    // HandleFallback method from IFallbackHandler&amp;lt;TRequest, TResponse&amp;gt; interface.
    // This method will get called if my Handle method fails.
    public async Task&amp;lt;Customer&amp;gt; HandleFallback(Query message, CancellationToken token)
    {
        return await _db2.GetCustomerByNumberAsync(message.CustomerNumber);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// MediatR Fallback Pipeline Behavior
/// &amp;lt;/summary&amp;gt;
/// &amp;lt;typeparam name=&quot;TRequest&quot;&amp;gt;&amp;lt;/typeparam&amp;gt;
/// &amp;lt;typeparam name=&quot;TResponse&quot;&amp;gt;&amp;lt;/typeparam&amp;gt;
public class FallbackBehavior&amp;lt;TRequest, TResponse&amp;gt; : IPipelineBehavior&amp;lt;TRequest, TResponse&amp;gt;
    where TRequest : IRequest&amp;lt;TResponse&amp;gt;
{
    private readonly IEnumerable&amp;lt;IFallbackHandler&amp;lt;TRequest, TResponse&amp;gt;&amp;gt; _fallbackHandlers;
    private readonly ILogger&amp;lt;FallbackBehavior&amp;lt;TRequest, TResponse&amp;gt;&amp;gt; _logger;

    public FallbackBehavior(IEnumerable&amp;lt;IFallbackHandler&amp;lt;TRequest, TResponse&amp;gt;&amp;gt; fallbackHandlers, ILogger&amp;lt;FallbackBehavior&amp;lt;TRequest, TResponse&amp;gt;&amp;gt; logger)
    {
        _fallbackHandlers = fallbackHandlers;
        _logger = logger;
    }

    public async Task&amp;lt;TResponse&amp;gt; Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate&amp;lt;TResponse&amp;gt; next)
    {
        var fallbackHandler = _fallbackHandlers.FirstOrDefault();
        if (fallbackHandler == null)
        {
            // No fallback handler found, continue through pipeline
            return await next();
        }

        var fallbackPolicy = Policy&amp;lt;TResponse&amp;gt;
            .Handle&amp;lt;Exception&amp;gt;()
            .FallbackAsync(async (cancellationToken) =&amp;gt;
            {
                _logger.LogDebug($&quot;Initial handler failed. Falling back to `{fallbackHandler.GetType().FullName}@HandleFallback`&quot;);
                return await fallbackHandler.HandleFallback(request, cancellationToken)
                    .ConfigureAwait(false);
            });

        var response = await fallbackPolicy.ExecuteAsync(async () =&amp;gt; await next());

        return response;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;public interface IFallbackHandler&amp;lt;TRequest, TResponse&amp;gt; where TRequest : IRequest&amp;lt;TResponse&amp;gt;
{
    Task&amp;lt;TResponse&amp;gt; HandleFallback(TRequest request, CancellationToken cancellationToken);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;View &lt;a href=&quot;https://gist.github.com/anderly/576aece4c7c37ce8a6cc1fc5a7f6bb9e&quot;&gt;MediatR Fallback Pipeline Behavior&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Retry Behavior (using &lt;a href=&quot;https://github.com/App-vNext/Polly&quot;&gt;Polly&lt;/a&gt;):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class Handler : IRequestHandler&amp;lt;Query, Customer&amp;gt;, IRetryableRequest&amp;lt;Query, Customer&amp;gt;
{
    private readonly CustomerContext _db;
    private readonly IConfigurationProvider _configuration;

    // By implementing IRetryableRequest&amp;lt;TRequest, TResponse&amp;gt; I get the following
    // properties to control how my &quot;Handle&quot; method will get retried.
    public int RetryAttempts =&amp;gt; 2;
    public int RetryDelay =&amp;gt; 500;
    public bool RetryWithExponentialBackoff =&amp;gt; true;
    public int ExceptionsAllowedBeforeCircuitTrip =&amp;gt; 2;

    public Handler(CustomerContext db, IConfigurationProvider configuration)
    {
        _db = db;
        _configuration = configuration;
    }

    public async Task&amp;lt;Customer&amp;gt; Handle(Query message, CancellationToken token)
    {
        return await _db.Customers.Where(c =&amp;gt; c.Number == message.CustomerNumber)
            .ProjectTo&amp;lt;Models.Customer&amp;gt;(_configuration)
            .FirstOrDefaultAsync(token);
    }

}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;public interface IRetryableRequest&amp;lt;TRequest, TResponse&amp;gt; where TRequest : IRequest&amp;lt;TResponse&amp;gt;
{
    int RetryAttempts =&amp;gt; 1;

    int RetryDelay =&amp;gt; 250;

    bool RetryWithExponentialBackoff =&amp;gt; false;

    int ExceptionsAllowedBeforeCircuitTrip =&amp;gt; 1;

}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;public class RetryBehavior&amp;lt;TRequest, TResponse&amp;gt; : IPipelineBehavior&amp;lt;TRequest, TResponse&amp;gt; where TRequest : IRequest&amp;lt;TResponse&amp;gt;
{
    private readonly IEnumerable&amp;lt;IRetryableRequest&amp;lt;TRequest, TResponse&amp;gt;&amp;gt; _retryHandlers;
    private readonly ILogger&amp;lt;RetryBehavior&amp;lt;TRequest, TResponse&amp;gt;&amp;gt; _logger;

    public RetryBehavior(IEnumerable&amp;lt;IRetryableRequest&amp;lt;TRequest, TResponse&amp;gt;&amp;gt; retryHandlers, ILogger&amp;lt;RetryBehavior&amp;lt;TRequest, TResponse&amp;gt;&amp;gt; logger)
    {
        _retryHandlers = retryHandlers;
        _logger = logger;
    }

    public async Task&amp;lt;TResponse&amp;gt; Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate&amp;lt;TResponse&amp;gt; next)
    {
        var retryHandler = _retryHandlers.FirstOrDefault();
        if (retryHandler == null)
        {
            // No retry handler found, continue through pipeline
            return await next();
        }

        var circuitBreaker = Policy&amp;lt;TResponse&amp;gt;
            .Handle&amp;lt;Exception&amp;gt;()
            .CircuitBreakerAsync(retryHandler.ExceptionsAllowedBeforeCircuitTrip, TimeSpan.FromMilliseconds(5000),
                (exception, things) =&amp;gt;
                {
                    _logger.LogDebug(&quot;Circuit Tripped!&quot;);
                },
                () =&amp;gt;
                {
                });

        var retryPolicy = Policy&amp;lt;TResponse&amp;gt;
            .Handle&amp;lt;Exception&amp;gt;()
            .WaitAndRetryAsync(retryHandler.RetryAttempts, retryAttempt =&amp;gt;
            {
                var retryDelay = retryHandler.RetryWithExponentialBackoff
                    ? TimeSpan.FromMilliseconds(Math.Pow(2, retryAttempt) * retryHandler.RetryDelay)
                    : TimeSpan.FromMilliseconds(_handler.RetryDelay);

                _logger.LogDebug($&quot;Retrying, waiting {retryDelay}...&quot;);

                return retryDelay;
            });

        var response = await retryPolicy.ExecuteAsync(async () =&amp;gt; await next());

        return response;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;View &lt;a href=&quot;https://gist.github.com/anderly/49f34162605d639a2a0c265bb5a0d00a&quot;&gt;MediatR Retry Pipeline Behavior&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;p&gt;These can all be combined as well and work based on the order they’re registered in Startup.cs. In my case, I want my main &lt;strong&gt;Handle&lt;/strong&gt; method to retry, then, optionally, fallback to my &lt;strong&gt;HandleFallback&lt;/strong&gt;, then finally cache the result based on the defined CachePolicy.&lt;/p&gt;
&lt;p&gt;I’m debating between using separately defined classes/policies (like &lt;a href=&quot;https://fluentvalidation.net/&quot;&gt;FluentValidation&lt;/a&gt; Validators) vs. making Handlers implement the interfaces to get the behavior. On one hand, if they’re separate, I could move the Cache, Fallback and Retry policies to separate files, folders, etc. and keep my main MediatR handlers very lean and clean. If you want to see them in the same place, you could put them in the same file like many of Jimmy Bogard’s &lt;a href=&quot;https://github.com/jbogard/ContosoUniversityDotNetCore-Pages&quot;&gt;examples&lt;/a&gt; with &lt;a href=&quot;https://github.com/jbogard/ContosoUniversityDotNetCore-Pages/blob/master/ContosoUniversity/Pages/Courses/Edit.cshtml.cs#L80&quot;&gt;Validators&lt;/a&gt;, etc. But if the files get too big and you want to separate them out, you could do that. However, with Retry and Fallback, it’s kind of nice seeing that with the main request handler.&lt;/p&gt;
&lt;p&gt;Of course, all this gets wired-up and registered in &lt;strong&gt;Startup.cs&lt;/strong&gt;. I’m using &lt;a href=&quot;https://github.com/khellang/Scrutor&quot;&gt;Scrutor&lt;/a&gt; to aid in discovery my Caching, Fallback and Retry policies. See below.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Register MediatR Pipeline Behaviors
services.AddTransient(typeof(IPipelineBehavior&amp;lt;,&amp;gt;), typeof(LoggingBehavior&amp;lt;,&amp;gt;));
services.AddTransient(typeof(IPipelineBehavior&amp;lt;,&amp;gt;), typeof(ValidationBehavior&amp;lt;,&amp;gt;));
services.AddTransient(typeof(IPipelineBehavior&amp;lt;,&amp;gt;), typeof(CachingBehavior&amp;lt;,&amp;gt;));
services.AddTransient(typeof(IPipelineBehavior&amp;lt;,&amp;gt;), typeof(FallbackBehavior&amp;lt;,&amp;gt;));
services.AddTransient(typeof(IPipelineBehavior&amp;lt;,&amp;gt;), typeof(RetryBehavior&amp;lt;,&amp;gt;));

// ICachePolicy discovery and registration
services.Scan(scan =&amp;gt; scan
    .FromAssemblies(assembly)
    .AddClasses(classes =&amp;gt; classes.AssignableTo(typeof(ICachePolicy&amp;lt;,&amp;gt;)))
    .AsImplementedInterfaces()
    .WithTransientLifetime());

// IFallbackHandler discovery and registration
services.Scan(scan =&amp;gt; scan
    .FromAssemblies(typeof(Startup).Assembly)
    .AddClasses(classes =&amp;gt; classes.AssignableTo(typeof(IFallbackHandler&amp;lt;,&amp;gt;)))
    .UsingRegistrationStrategy(RegistrationStrategy.Skip)
    .AsImplementedInterfaces()
    .WithTransientLifetime());

// IFallbackHandler discovery and registration
services.Scan(scan =&amp;gt; scan
    .FromAssemblies(typeof(Startup).Assembly)
    .AddClasses(classes =&amp;gt; classes.AssignableTo(typeof(IRetryableRequest&amp;lt;,&amp;gt;)))
    .UsingRegistrationStrategy(RegistrationStrategy.Skip)
    .AsImplementedInterfaces()
    .WithTransientLifetime());
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;View &lt;a href=&quot;https://gist.github.com/anderly/53e3b98c440479a9171643a79d2720d7&quot;&gt;MediatR Pipeline Behavior Registration&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;p&gt;What do you think? Which approach do you prefer? Let me know in the comments.&lt;/p&gt;
</content:encoded><category>.NET</category><category>ASP.NET Core</category><category>MediatR</category></item><item><title>Laravel User Timezone Aware Trait</title><link>https://anderly.com/2017/12/21/laravel-user-timezone-aware-trait/</link><guid isPermaLink="true">https://anderly.com/2017/12/21/laravel-user-timezone-aware-trait/</guid><description>Next up in the series on useful Laravel model traits is the UserTimezoneAware Trait. This trait is useful when you have dates on models that you need to display in the user’s timezone. It’s a simple trait you can drop onto one of your eloquent models to add timezone support like so: Now when you…</description><pubDate>Thu, 21 Dec 2017 17:36:21 GMT</pubDate><content:encoded>&lt;p&gt;Next up in the series on &lt;a href=&quot;https://anderly.com/category/laravel-traits/&quot;&gt;useful Laravel model traits&lt;/a&gt; is the &lt;code&gt;UserTimezoneAware&lt;/code&gt; Trait.&lt;/p&gt;
&lt;p&gt;This trait is useful when you have dates on models that you need to display in the user’s timezone.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// app\Traits\UserTimezoneAware.php
namespace App\Traits;
trait UserTimezoneAware
{
    /**
     * The attribute name containing the timezone (defaults to &quot;timezone&quot;).
     *
     * @var string
     */
    public $timezoneAttribute = &apos;timezone&apos;;
     
    /**
     * Return the passed date in the user&apos;s timezone (or default to the app timezone)
     *
     * @return string
    */
    public function getDateToUserTimezone($date, $timezone = null)
    {
        if ($timezone == null) {
            if (Auth::check()) {
                $timezone = Auth::user()-&amp;gt;timezone;
            } else {
                $timezone = Config::get(&apos;app.timezone&apos;);
            }
        }
        $datetime = new DateTime($date);
        $datetime-&amp;gt;setTimezone(new datetimezone($timezone));
        
        return $datetime-&amp;gt;format(&apos;c&apos;);
    }   
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’s a simple trait you can drop onto one of your eloquent models to add timezone support like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// app\Models\User.php
namespace App\Models;

use App\Traits\UserTimezoneAware

class User
{
    use UserTimezoneAware;

    public function getLastLoginAttribute()
    {
        return $this-&amp;gt;getDateToUserTimezone($this-&amp;gt;attributes[&apos;last_login&apos;]);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now when you access the &lt;code&gt;$user-&amp;gt;lastLogin&lt;/code&gt; attribute anywhere in your app, you’ll get the date in the user’s timezone.&lt;/p&gt;
&lt;p&gt;The UserTimezoneAware trait expects the model to have a &lt;code&gt;timezone&lt;/code&gt; attribute. If your column/attribute is named something other than &lt;code&gt;timezone&lt;/code&gt; simply override the &lt;code&gt;$timezoneAttribute&lt;/code&gt; property on the &lt;code&gt;UserTimezoneAware&lt;/code&gt; trait.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;namespace App\Models;

use App\Traits\UserTimezoneAware
 
class User
{
    use UserTimezoneAware;

    public $timezoneAttribute= &apos;time_zone&apos;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</content:encoded><category>Laravel</category><category>Laravel Traits</category><category>PHP</category></item><item><title>Useful Laravel Model Traits: Gravatar</title><link>https://anderly.com/2016/09/09/useful-laravel-traits-gravatar/</link><guid isPermaLink="true">https://anderly.com/2016/09/09/useful-laravel-traits-gravatar/</guid><description>Starting a little series here on useful Laravel model traits. This first one I use quite often. It’s a simple trait you can drop onto one of your eloquent models to add gravatar support like so: Now you can do something like this in your blade views: And you’ll get the gravatar.com URL you’re expecting…</description><pubDate>Fri, 09 Sep 2016 14:38:45 GMT</pubDate><content:encoded>&lt;p&gt;Starting a little series here on &lt;a href=&quot;https://anderly.com/category/laravel-traits/&quot;&gt;useful Laravel model traits&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This first one I use quite often.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// app\Traits\HasGravatar.php
namespace App\Traits;

trait HasGravatar
{
    
    /**
     * The attribute name containing the email address.
     *
     * @var string
     */
    public $gravatarEmail = &apos;email&apos;;
    
    /**
     * Get the model&apos;s gravatar
     *
     * @return string
     */
    public function getGravatarAttribute()
    {
        $hash = md5(strtolower(trim($this-&amp;gt;attributes[$this-&amp;gt;gravatarEmail])));
        return &quot;https://www.gravatar.com/avatar/$hash&quot;;
    }

}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’s a simple trait you can drop onto one of your eloquent models to add gravatar support like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// app\Models\User.php
namespace App\Models;

use App\Traits\HasGravatar

class User
{
    use HasGravatar;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now you can do something like this in your blade views:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;img src=&quot;{{ Auth::user()-&amp;gt;gravatar }}&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And you’ll get the gravatar.com URL you’re expecting. No need to create a gravatar column, variable, method, or anything else.&lt;/p&gt;
&lt;p&gt;The HasGravatar Trait expects the model to have an &lt;code&gt;email&lt;/code&gt; attribute. If your column/attribute is named something other than &lt;code&gt;email&lt;/code&gt; simply override the &lt;code&gt;$gravatarEmail&lt;/code&gt; property on the &lt;code&gt;HasGravatar&lt;/code&gt; trait.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;namespace App\Models;

use App\Traits\HasGravatar

class User
{
    use HasGravatar;

    public $gravatarEmail = &apos;email_address&apos;;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</content:encoded><category>Laravel</category><category>Laravel Traits</category></item><item><title>Laravel Transformable – An Eloquent Model Trait for Consumable Models</title><link>https://anderly.com/2016/09/08/laravel-transformable-a-model-trait-for-consumable-models/</link><guid isPermaLink="true">https://anderly.com/2016/09/08/laravel-transformable-a-model-trait-for-consumable-models/</guid><description>In working on a new Laravel-based REST API over an existing database, I quickly realized the need to shield API consumers from my underlying database structure, especially since I knew the structure would be changing. This is a common concern in API design and many times I would turn to creating DTOs (Data Transfer Objects)…</description><pubDate>Thu, 08 Sep 2016 21:37:31 GMT</pubDate><content:encoded>&lt;p&gt;In working on a new Laravel-based REST API over an existing database, I quickly realized the need to shield API consumers from my underlying database structure, especially since I knew the structure would be changing. This is a common concern in API design and many times I would turn to creating DTOs (Data Transfer Objects) or transformer classes using either a scaled-down Transformer pattern or the excellent &lt;a href=&quot;http://fractal.thephpleague.com/&quot;&gt;Fractal&lt;/a&gt; package. However, for this project time was of the essence so I needed a very quick way to simply provide a transformation map without having to create new transformer classes for each model and without having to update the &lt;code&gt;visible&lt;/code&gt; and &lt;code&gt;appends&lt;/code&gt; attributes on every model.&lt;/p&gt;
&lt;p&gt;Hence, the &lt;code&gt;Transformable&lt;/code&gt; trait was born. It’s a simple PHP trait that you drop into your model and then override the &lt;code&gt;$transformation_map&lt;/code&gt; property to specify your consumable model attributes.&lt;/p&gt;
&lt;p&gt;Here’s an example:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Traits\Transformable;

class Group extends Model
{
    use Transformable;

    protected $transformation_map = [
        &apos;Group_ID&apos; =&amp;gt; &apos;id&apos;,
        &apos;Name&apos; =&amp;gt; &apos;name&apos;,
        &apos;PublicGroup&apos; =&amp;gt; &apos;public&apos;,
    ];
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A quick explanation: we’re importing the Transformable trait (which I’ll cover shortly) and then we’re providing a database column name-to-consumable attribute name mapping. That’s it.&lt;/p&gt;
&lt;p&gt;A consumer of this model will not see the underlying database column names on the left hand of the mapping such as “Group_ID”, “Name”, or “PublicGroup.” Instead, they’ll see the names on the right hand side: “id”, “name” and “public.” In essence, it’s a simple transformer. Here’s an example usage:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;use App\Models\Group;

class GroupsController
{
    public function index()
    {
        return Group::all();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With a call to the above &lt;code&gt;GroupsController@index&lt;/code&gt; method, we’d end up with the following JSON:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[
    {
        &quot;id&quot;: 1,
        &quot;name&quot;: &quot;Group 1&quot;,
        &quot;public&quot;: &quot;0&quot;
    },
    {
        &quot;id&quot;: 2,
        &quot;name&quot;: &quot;Group 2&quot;,
        &quot;public&quot;: &quot;0&quot;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Additionally, we can create the model specifying the consumable attribute names (not the database column names):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$group = new App\Models\Group([&apos;name&apos; =&amp;gt; &apos;Group 3&apos;, &apos;public&apos; =&amp;gt; true]);

// Calling this
$group-&amp;gt;toJson();

// Will yield this
{
    &quot;id&quot;: 3,
    &quot;name&quot;: &quot;Group 3&quot;,
    &quot;public&quot;:&quot;1&quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The magic of this is in the Transformable trait. Normally, to achieve this, we’d have to specify the &lt;code&gt;$visible&lt;/code&gt; and &lt;code&gt;$appends&lt;/code&gt; properties on our model and provide get and set mutators for each attribute mapping. Instead, with Transformable, we simply provide the &lt;code&gt;$transformation_map&lt;/code&gt; and the Transformable trait takes care of the rest.&lt;/p&gt;
&lt;p&gt;It does this by overriding several methods of the Eloquent model that determine if get and set mutators exist to include checking the &lt;code&gt;$transformation_map&lt;/code&gt; property. This is how it can return you an instance of your model as well as create an instance of your model with the consumable attribute names without you needing to specify the source database column names.&lt;/p&gt;
&lt;p&gt;I’m working on an enhancement to Transformable to allow queries (i.e. where* methods) on the models so that you can query with the consumable attribute names and not the database column names. As soon as I wrap up those changes, I’ll look at making this a composer package.&lt;/p&gt;
&lt;p&gt;Here’s the entire trait implementation:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;namespace App\Traits;

use Illuminate\Support\Str;

Trait Transformable
{
	protected $transformation_map = [];

    /**
     * Determine if a get mutator exists for an attribute.
     *
     * @param  string  $key
     * @return bool
     */
    public function hasGetMutator($key)
    {
        return $this-&amp;gt;keyExistsInTransformationMap($key) || parent::hasGetMutator($key);
    }

    /**
     * Determine if a set mutator exists for an attribute.
     *
     * @param  string  $key
     * @return bool
     */
    public function hasSetMutator($key)
    {
        return $this-&amp;gt;keyExistsInTransformationMap($key) || parent::hasSetMutator($key);
    }

    /**
     * Get the value of an attribute using its mutator.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return mixed
     */
    protected function mutateAttribute($key, $value)
    {
        if ($this-&amp;gt;keyExistsInTransformationMap($key)) {
            return $this-&amp;gt;{$this-&amp;gt;getTransformationMapInverse()[$key]};
        }
        return parent::mutateAttribute($key, $value);
    }

    /**
     * Set a given attribute on the model.
     *
     * @param  string  $key
     * @param  mixed  $value
     * @return $this
     */
    public function setAttribute($key, $value)
    {
        if ($this-&amp;gt;keyExistsInTransformationMap($key)) {
            if (method_exists($this, &apos;set&apos;.Str::studly($key).&apos;Attribute&apos;)) {
                parent::setAttribute($key, $value);
            }
            $key = $this-&amp;gt;getTransformationMapInverse()[$key];
        }
        return parent::setAttribute($key, $value);
    }

    public function keyExistsInTransformationMap($key)
    {
        return array_key_exists($key, $this-&amp;gt;getTransformationMapInverse());
    }

    public function getTransformationMapInverse()
    {
        return array_flip($this-&amp;gt;transformation_map);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This could certainly be enhanced further to support casting to/from datatypes and supporting compound properties via a Closure or similar.&lt;/p&gt;
&lt;p&gt;Let me know what you think in the comments.&lt;/p&gt;
</content:encoded><category>Laravel</category><category>PHP</category><category>REST</category></item><item><title>Gravity Forms + Microsoft Dynamics CRM</title><link>https://anderly.com/2015/09/02/gravity-forms-microsoft-dynamics-crm/</link><guid isPermaLink="true">https://anderly.com/2015/09/02/gravity-forms-microsoft-dynamics-crm/</guid><description>I’ve been hard at work on a brand new WordPress plugin that brings you easy web-to-lead and web-to-contact forms for Microsoft Dynamics CRM through the powerful Gravity Forms plugin for WordPress. At my company, Saint Systems, we have a non-profit client that uses Office 365 and Microsoft Dynamics CRM plus WordPress for their front-end website…</description><pubDate>Wed, 02 Sep 2015 21:57:43 GMT</pubDate><content:encoded>&lt;p&gt;I’ve been hard at work on a brand new WordPress plugin that brings you easy web-to-lead and web-to-contact forms for Microsoft Dynamics CRM through the powerful &lt;a href=&quot;http://www.gravityforms.com/&quot;&gt;Gravity Forms&lt;/a&gt; plugin for WordPress.&lt;/p&gt;
&lt;p&gt;At my company, &lt;a href=&quot;http://www.saintsystems.com&quot;&gt;Saint Systems&lt;/a&gt;, we have a non-profit client that uses &lt;a href=&quot;https://products.office.com/en-us/business/office&quot;&gt;Office 365&lt;/a&gt; and &lt;a href=&quot;http://www.microsoft.com/en-us/dynamics/crm.aspx&quot;&gt;Microsoft Dynamics CRM&lt;/a&gt; plus WordPress for their front-end website. Initially we searched for an existing plugin, add-on or integration between Gravity Forms and Dynamics CRM to no avail. So, we decided to build one and scratch our own itch.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.saintsystems.com/products/gravity-forms-dynamics-crm-add-on/&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/edd/2016/10/gravity-forms-dynamics-crm-add-on-logo.png&quot; alt=&quot;Gravity Forms Dynamics CRM Add-On&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The result is the &lt;a href=&quot;http://www.saintsystems.com/products/gravity-forms-dynamics-crm-add-on/&quot;&gt;Gravity Forms Dynamics CRM Add-On&lt;/a&gt; – a WordPress plugin that allows you to quickly integrate Gravity Forms with Microsoft Dynamics CRM. Easily create leads or contacts in Microsoft Dynamics CRM when a form is submitted.&lt;/p&gt;
&lt;h2&gt;Key Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Quickly and easily integrate with Dynamics CRM when a form is submitted.&lt;/li&gt;
&lt;li&gt;Create a lead in Dynamics CRM when a form is submitted.&lt;/li&gt;
&lt;li&gt;Create a contact in Dynamics CRM when a form is submitted.&lt;/li&gt;
&lt;li&gt;Update a lead in Dynamics CRM when a form is submitted.&lt;/li&gt;
&lt;li&gt;Update a contact in Dynamics CRM when a form is submitted.&lt;/li&gt;
&lt;li&gt;Choose a Dynamics CRM user as the lead or contact owner.&lt;/li&gt;
&lt;li&gt;Avoid duplicates by checking for existing leads and contacts by email address.&lt;/li&gt;
&lt;li&gt;Use Gravity Forms built-in Conditional Logic to only integrate with Dynamics CRM when you want to!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;s&gt;We’re planning on an October 2015 release and are anxious to get it in your hands.&lt;/s&gt; The plugin is now available for purchase.&lt;/p&gt;
&lt;p&gt;Find out more about it on the &lt;a href=&quot;http://www.saintsystems.com/products/gravity-forms-dynamics-crm-add-on/&quot;&gt;Gravity Forms Dynamics CRM Add-On product page&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>WordPress</category><category>WordPress Plugins</category></item><item><title>DNS from the command line: dnsimple-cli for Node.js</title><link>https://anderly.com/2014/10/27/dns-from-the-command-line-dnsimple-cli-for-node-js/</link><guid isPermaLink="true">https://anderly.com/2014/10/27/dns-from-the-command-line-dnsimple-cli-for-node-js/</guid><description>Too busy to do a full write-up now, but I’m working on a new Node.js dnsimple-cli package based on azure-cli. Of course, it starts with ASCII art: After logging in, you can do something like this: And, you’ll get: Initially, the command structure I’ve stubbed out is as follows (subject to change): More to come!</description><pubDate>Mon, 27 Oct 2014 14:47:21 GMT</pubDate><content:encoded>&lt;p&gt;Too busy to do a full write-up now, but I’m working on a new Node.js dnsimple-cli package based on &lt;a href=&quot;https://www.npmjs.org/package/azure-cli&quot;&gt;azure-cli&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Of course, it starts with ASCII art:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ander.ly/1e0Ei&quot;&gt;&lt;img src=&quot;http://ander.ly/1jGJU+&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After logging in, you can do something like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dnsimple domain list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And, you’ll get:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://ander.ly/1e0Ei&quot;&gt;&lt;img src=&quot;http://ander.ly/1e0Ei+&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Initially, the command structure I’ve stubbed out is as follows (subject to change):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dnsimple
	|- domain
		|- list
		|- add
		|- show
		|- delete
		--------------
		|- reset (reset token)
		|- push
		--------------
		|- check
		|- register
		|- transfer (in)
		|- renew
		|- transferout
		|- autorenew [true|false]
		--------------
		|- member
			|- list
			|- add
			|- delete
		--------------
		|- record
			|- list
			|- add
			|- show
			|- update
			|- delete
		--------------
		|- ns (name server)
			|- update
			|- register (add)
			|- unregister (delete)
		--------------
		|- vns (vanity name server)
			|- enable
			|- disable
		--------------
		|- whois [true|false] (WHOIS privacy)
		--------------
		|- cert (ssl)
			|- list
			|- add (purchase/buy)
			|- show
			|- configure
			|- submit (update)
		--------------
		|- email (email forwards)
			|- list
			|- add
			|- delete
		--------------
		|- zone
			|- import
			|- export
	--------------
	|- contact
		|- list
		|- add
		|- show
		|- update
		|- delete
	--------------
	|- server
		|- list
		|- show
	--------------
	|- template
		|- list
		|- add
		|- show
		|- delete
	--------------
	|- extendedattributes
		|- list
	--------------
	|- user
	--------------
	|- subscription
		|- add
		|- show
	--------------
	|- price
		|- list
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More to come!&lt;/p&gt;
</content:encoded><category>Node.js</category><category>REST</category></item><item><title>WooCommerce MailChimp 1.2 Released</title><link>https://anderly.com/2014/01/10/woocommerce-mailchimp-1-2-released/</link><guid isPermaLink="true">https://anderly.com/2014/01/10/woocommerce-mailchimp-1-2-released/</guid><description>WooCommerce MailChimp version 1.2 is now available on the WordPress Plugin Repository which brings enhancements to provide even greater control over the opt-in settings to better support international laws. There were also a couple of changes to better support i18n (Internationalization) support and localization as well as a minor change to append interest groups to…</description><pubDate>Fri, 10 Jan 2014 19:21:17 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;https://anderly.com/woocommerce-mailchimp&quot;&gt;WooCommerce MailChimp version 1.2&lt;/a&gt; is now available on the WordPress Plugin Repository which brings enhancements to provide even greater control over the opt-in settings to better support international laws. There were also a couple of changes to better support i18n (Internationalization) support and localization as well as a minor change to append interest groups to existing MailChimp subscribers. Below are the details on the changes included in version 1.2:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Added new setting to control whether or not the opt-in checkbox is checked or unchecked by default&lt;/li&gt;
&lt;li&gt;Added new setting to control the placement of the opt-in checkbox on the checkout page (under billing info or order info)&lt;/li&gt;
&lt;li&gt;Added .pot file to support international translations&lt;/li&gt;
&lt;li&gt;Added wpml-config.xml file to support WPML translations for values stored in wp_options&lt;/li&gt;
&lt;li&gt;Change to MailChimp API subscribe call to append interest groups to existing subscribers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please update your plugin today to take advantage of these features and stay tuned for the upcoming release of &lt;a href=&quot;http://www.saintsystems.com/products/woocommerce-mailchimp-pro&quot;&gt;WooCommerce MailChimp Pro&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Join our &lt;a href=&quot;https://trello.com/b/VWBdLVuI/woocommerce-mailchimp-development&quot;&gt;Trello Board&lt;/a&gt; to see what’s on our roadmap and vote on features. As always, please provide your feedback and/or enhancement requests &lt;a href=&quot;https://anderly.com/contact&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</content:encoded><category>WordPress</category><category>WordPress Plugins</category></item><item><title>WooCommerce MailChimp Update</title><link>https://anderly.com/2014/01/08/woocommerce-mailchimp-update/</link><guid isPermaLink="true">https://anderly.com/2014/01/08/woocommerce-mailchimp-update/</guid><description>WooCommerce MailChimp will soon surpass the 3,500 download mark after just under 3 months on the WordPress Plugin Repository. The response has been incredible, interest has been steadily gaining and many users have provided very constructive feedback, comments and suggestions. As such, I felt an update was in order to make you aware of what’s…</description><pubDate>Wed, 08 Jan 2014 17:07:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;a href=&quot;http://wordpress.org/plugins/woocommerce-mailchimp/&quot;&gt;WooCommerce MailChimp&lt;/a&gt; will soon surpass the 3,500 download mark after just under 3 months on the WordPress Plugin Repository. The response has been incredible, interest has been steadily gaining and many users have provided very constructive feedback, comments and suggestions. As such, I felt an update was in order to make you aware of what’s coming for WooCommerce MailChimp.&lt;/p&gt;
&lt;h2&gt;Version 1.2&lt;/h2&gt;
&lt;p&gt;We are currently working on version 1.2 of the plugin which will include the following requested features to name a few:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New setting to control whether or not the double opt-in checkbox is checked/unchecked by default on the checkout page.&lt;/li&gt;
&lt;li&gt;Small modification to append to MailChimp interest groups for existing users so that group settings are not lost for users who were already subscribed.&lt;/li&gt;
&lt;li&gt;Preparations for i18n (Internationalization) support. Several users have already asked and offered to translate the plugin into other languages. We had always planned on that, but now are making that a reality.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Trello Board&lt;/h2&gt;
&lt;p&gt;We have setup a public &lt;a href=&quot;https://trello.com/b/VWBdLVuI/woocommerce-mailchimp-development&quot;&gt;Trello board&lt;/a&gt; where you can see what’s next on our radar, vote on features and see the status of enhancements, bug fixes, etc.&lt;/p&gt;
&lt;h2&gt;WooCommerce MailChimp Pro&lt;/h2&gt;
&lt;p&gt;We are planning a paid/pro version of this plugin (&lt;a href=&quot;http://www.saintsystems.com/products/woocommerce-mailchimp-pro/&quot;&gt;coming soon&lt;/a&gt;) which will include advanced features for more fine-grained control over the integration with MailChimp and more “power user” features. This will allow us more time to dedicate to making this the best possible plugin to integrate WooCommerce and MailChimp, while also allowing us to feed our families. 🙂&lt;/p&gt;
&lt;p&gt;While pricing has not yet been announced, there will be license options based on the number of sites you wish to install the plugin on. Stay tuned for further details.&lt;/p&gt;
&lt;h2&gt;What about the free version?&lt;/h2&gt;
&lt;p&gt;Don’t worry! There will always be a &lt;a href=&quot;http://wordpress.org/plugins/woocommerce-mailchimp/&quot;&gt;free version&lt;/a&gt; on the WordPress Plugin Repository which will include the current functionality plus some enhancements but support will happen as we can get to it.&lt;/p&gt;
&lt;h2&gt;That’s all for now!&lt;/h2&gt;
&lt;p&gt;Please subscribe to our &lt;a href=&quot;https://trello.com/b/VWBdLVuI/woocommerce-mailchimp-development&quot;&gt;Trello board&lt;/a&gt; and stay tuned for version 1.2 release and the upcoming Pro version.&lt;/p&gt;
&lt;p&gt;Thank you so much for your support and feedback. The response to the plugin has been truly amazing!&lt;/p&gt;
</content:encoded><category>WordPress</category><category>WordPress Plugins</category></item><item><title>WooCommerce MailChimp 1.1 Released</title><link>https://anderly.com/2013/11/12/woocommerce-mailchimp-1-1-released/</link><guid isPermaLink="true">https://anderly.com/2013/11/12/woocommerce-mailchimp-1-1-released/</guid><description>The response has been huge to my WooCommerce MailChimp plugin but there have been quite a few international users who haven’t been able to use it due to laws requiring the ability for customers to explicitly opt-in to the email list during checkout vs. the default behavior of automatically subscribing customers to the list after…</description><pubDate>Tue, 12 Nov 2013 13:21:24 GMT</pubDate><content:encoded>&lt;p&gt;The response has been huge to my &lt;a href=&quot;https://anderly.com/woocommerce-mailchimp&quot;&gt;WooCommerce MailChimp plugin&lt;/a&gt; but there have been quite a few international users who haven’t been able to use it due to laws requiring the ability for customers to explicitly opt-in to the email list during checkout vs. the default behavior of automatically subscribing customers to the list after making a purchase. Well, the wait is over, &lt;strong&gt;WooCommerce MailChimp 1.1&lt;/strong&gt; is &lt;a href=&quot;http://wordpress.org/plugins/woocommerce-mailchimp/&quot;&gt;now available&lt;/a&gt; and adds this capability (see screenshot below) so that customers can choose whether or not to opt-in during the checkout process. This feature is completely optional and you have full control over the opt-in text displayed next to the checkbox (figure 2).&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/opt-in.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/opt-in-300x258.png&quot; alt=&quot;WooCommerce MailChimp Checkout Opt-In&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Figure 1: WooCommerce MailChimp Checkout Opt-In&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/woocommerce-mailchimp-options.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/woocommerce-mailchimp-options-300x215.png&quot; alt=&quot;Figure 2: WooCommerce MailChimp Options&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Figure 2: WooCommerce MailChimp Options&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This feature was contributed by &lt;a href=&quot;http://find.brentshepherd.com/&quot;&gt;Brent Shepherd&lt;/a&gt; (developer of the excellent &lt;a href=&quot;http://www.woothemes.com/products/woocommerce-subscriptions/&quot;&gt;WooCommerce Subscriptions extension&lt;/a&gt;). Many thanks Brent!&lt;/p&gt;
&lt;p&gt;Please update your plugin today to take advantage of this feature. The update is also available for download on the WordPress plugin directory here: &lt;a href=&quot;http://wordpress.org/plugins/woocommerce-mailchimp/&quot;&gt;http://wordpress.org/plugins/woocommerce-mailchimp/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</content:encoded><category>WordPress</category><category>WordPress Plugins</category></item><item><title>WooCommerce MailChimp WordPress plugin now on MailChimp Integrations Directory</title><link>https://anderly.com/2013/10/24/woocommerce-mailchimp-wordpress-plugin-now-on-mailchimp-integrations-directory/</link><guid isPermaLink="true">https://anderly.com/2013/10/24/woocommerce-mailchimp-wordpress-plugin-now-on-mailchimp-integrations-directory/</guid><description>Quick Update: MailChimp users can now find the WooCommerce MailChimp WordPress plugin on the MailChimp Integrations Directory. To find out more about the WooCommerce MailChimp WordPress plugin, see the plugin page or download it from the WordPress Plugin Directory.</description><pubDate>Thu, 24 Oct 2013 15:28:31 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Quick Update:&lt;/strong&gt; MailChimp users can now find the WooCommerce MailChimp WordPress plugin on the &lt;a href=&quot;http://connect.mailchimp.com/integrations/woocommerce-mailchimp&quot;&gt;MailChimp Integrations Directory&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To find out more about the WooCommerce MailChimp WordPress plugin, see the &lt;a href=&quot;https://anderly.com/woocommerce-mailchimp&quot;&gt;plugin page&lt;/a&gt; or download it from the &lt;a href=&quot;http://wordpress.org/plugins/woocommerce-mailchimp/&quot;&gt;WordPress Plugin Directory&lt;/a&gt;.&lt;/p&gt;
</content:encoded><category>WordPress</category><category>WordPress Plugins</category></item><item><title>New WordPress Plugin: Wistia Responsive</title><link>https://anderly.com/2013/10/24/wistia-responsive/</link><guid isPermaLink="true">https://anderly.com/2013/10/24/wistia-responsive/</guid><description>Wistia Responsive is a simple and straightforward WordPress plugin I developed while working on the website for the New Saint Thomas Institute (NSTI) that automatically makes all of your Wistia video embeds responsive. Problem: On the NSTI site, we have lots of video content and we’re using a responsive theme because we know that many…</description><pubDate>Thu, 24 Oct 2013 13:47:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/wistia-logo.jpg&quot; alt=&quot;wistia-logo&quot; /&gt;&lt;strong&gt;Wistia Responsive&lt;/strong&gt; is a simple and straightforward WordPress plugin I developed while working on the website for the &lt;a href=&quot;http://newsaintthomas.com&quot;&gt;New Saint Thomas Institute&lt;/a&gt; (NSTI) that automatically makes all of your &lt;a href=&quot;http://wistia.com&quot;&gt;Wistia&lt;/a&gt; video embeds responsive.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; On the NSTI site, we have lots of video content and we’re using a responsive theme because we know that many of the site’s members would be accessing content on mobile devices, smartphones or tablets. However, we quickly noticed that the Wistia video player was not inherently responsive and was hindering the experience for users on mobile and tablet devices.&lt;/p&gt;
&lt;p&gt;The good news is the team at Wistia has a solution in the form of their “&lt;a href=&quot;http://wistia.com/labs/videofoam/&quot;&gt;video foam&lt;/a&gt;” feature currently on their &lt;a href=&quot;http://wistia.com/labs/&quot;&gt;labs site&lt;/a&gt;. This works with their &lt;a href=&quot;http://wistia.com/doc/player-api&quot;&gt;iframe api&lt;/a&gt; to make your Wistia embedded video players responsive.&lt;/p&gt;
&lt;p&gt;The problem is that, because the video foam features uses the javascript iframe api, there wasn’t an easy way to have content authors easily make their videos responsive when generating embeds on Wistia’s site without manually appending the “videoFoam” parameter to the end of their embeds inside of WordPress.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; What we came up with was a simple plugin that first registers the iframe api script needed for video foam to work and then hooks into &lt;code&gt;the_content&lt;/code&gt; and &lt;code&gt;the_excerpt&lt;/code&gt; filters to automatically append the video foam parameter to the end of all video embeds. The plugin looks for wistia video embeds, adds the video foam parameter, and the rest takes care of itself!&lt;/p&gt;
&lt;p&gt;Simply activate the plugin and the rest will happen automatically!&lt;/p&gt;
&lt;p&gt;See it in action in the embedded video below. Try resizing your browser or access this page from your phone or tablet and the Wistia player should resize automatically to fit your screen.&lt;/p&gt;
&lt;iframe src=&quot;https://fast.wistia.net/embed/iframe/fte0mnjeyq&quot; title=&quot;Wistia video&quot; allowfullscreen&gt;&lt;/iframe&gt;
&lt;p&gt;The plugin is now on the WordPress Plugin Repository and you can get it by clicking on the following link:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://wordpress.org/plugins/wistia-responsive/&quot;&gt;Download Wistia Responsive&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://github.com/anderly/wistia-responsive&quot;&gt;Get the Source on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h4&gt;Multisite&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;All features should work for each blog in multisite installations but this has not yet been tested.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Feedback&lt;/h3&gt;
&lt;p&gt;Feedback is welcome!&lt;/p&gt;
&lt;p&gt;If you need help, have problems, want to leave feedback or want to provide constructive criticism, please do so here at the &lt;a href=&quot;https://anderly.com/wistia-responsive&quot;&gt;Wistia Responsive plugin page&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;Twitter&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://twitter.com/anderly&quot;&gt;Follow @anderly on Twitter&lt;/a&gt; for updates on this and other plugins.&lt;/p&gt;
&lt;h3&gt;Installation&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Upload or extract the &lt;code&gt;wistia-responsive&lt;/code&gt; folder to your site’s &lt;code&gt;/wp-content/plugins/&lt;/code&gt; directory. You can also use the &lt;em&gt;Add new&lt;/em&gt; option found in the &lt;em&gt;Plugins&lt;/em&gt; menu in WordPress.&lt;/li&gt;
&lt;li&gt;Enable the plugin from the &lt;em&gt;Plugins&lt;/em&gt; menu in WordPress.&lt;/li&gt;
&lt;li&gt;Voila! Your Wistia video embeds will now be responsive!&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Changelog&lt;/h3&gt;
&lt;h4&gt;1.0&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;This is the first public release.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>WordPress</category><category>WordPress Plugins</category></item><item><title>New WordPress Plugin: WooCommerce MailChimp</title><link>https://anderly.com/2013/10/09/woocommerce-mailchimp/</link><guid isPermaLink="true">https://anderly.com/2013/10/09/woocommerce-mailchimp/</guid><description>After a frustrating and fruitless search for a simple and free solution to basic WooCommerce integration with MailChimp, I decided to sit down and write a little plugin to do just that. There are a couple of paid solutions, but, in my opinion, most are overpriced for providing such vanilla functionality. Also, it seems this…</description><pubDate>Wed, 09 Oct 2013 15:57:17 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/woocommerce_mailchimp_500x500_no_bg-300x300.png&quot; alt=&quot;WooCommerce MailChimp&quot; title=&quot;WooCommerce MailChimp&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The WooCommerce logo and MailChimp logo are trademarks of &lt;a href=&quot;http://automattic.com&quot;&gt;Automattic&lt;/a&gt; and &lt;a href=&quot;http://mailchimp.com&quot;&gt;MailChimp&lt;/a&gt; respectively.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;After a frustrating and fruitless search for a simple and free solution to basic WooCommerce integration with MailChimp, I decided to sit down and write a little plugin to do just that. There are a couple of paid solutions, but, in my opinion, most are overpriced for providing such vanilla functionality. Also, it seems this functionality was previously bundled with WooCommerce and WooThemes has since removed it and made it a paid “extension.”&lt;/p&gt;
&lt;p&gt;So, without further ado, here is my new &lt;strong&gt;WooCommerce MailChimp&lt;/strong&gt; plugin for WordPress:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;WooCommerce MailChimp&lt;/strong&gt; provides simple MailChimp integration for WooCommerce.&lt;/p&gt;
&lt;p&gt;Easily add customers to a designated MailChimp list and, optionally, MailChimp interest groups upon order creation or order completion.&lt;/p&gt;
&lt;p&gt;Double opt-in option for anti-spam compliance.&lt;/p&gt;
&lt;p&gt;The plugin is now on the WordPress Plugin Repository and you can get it by clicking on the following link:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;http://wordpress.org/plugins/woocommerce-mailchimp/&quot;&gt;Download WooCommerce MailChimp&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://github.com/anderly/woocommerce-mailchimp&quot;&gt;&lt;strong&gt;Get the Source on GitHub&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Join our &lt;a href=&quot;https://trello.com/b/VWBdLVuI/woocommerce-mailchimp-development&quot;&gt;Trello Board&lt;/a&gt; to see what’s on our roadmap and vote on features. As always, please provide your feedback and/or enhancement requests &lt;a href=&quot;https://anderly.com/contact&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://github.com/anderly/woocommerce-mailchimp#features&quot;&gt;&lt;/a&gt;Features&lt;/h3&gt;
&lt;h4&gt;&lt;a href=&quot;https://github.com/anderly/woocommerce-mailchimp#woocommerce-event-selection&quot;&gt;&lt;/a&gt;WooCommerce Event Selection&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Subscribe customers to MailChimp after order creation&lt;/li&gt;
&lt;li&gt;Subscribe customers to MailChimp after order completion&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;&lt;a href=&quot;https://github.com/anderly/woocommerce-mailchimp#works-with-mailchimp-interest-groups&quot;&gt;&lt;/a&gt;Works with MailChimp Interest Groups&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Set one or more interest groups to add users to based on the selected MailChimp list.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;&lt;a href=&quot;https://github.com/anderly/woocommerce-mailchimp#multisite&quot;&gt;&lt;/a&gt;Multisite&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;All features should work for each blog in multisite installations but this has not yet been tested.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;&lt;a href=&quot;https://github.com/anderly/woocommerce-mailchimp#feedback&quot;&gt;&lt;/a&gt;Feedback&lt;/h3&gt;
&lt;p&gt;Feedback is welcome!&lt;/p&gt;
&lt;p&gt;If you need help, have problems, want to leave feedback or want to provide constructive criticism, please do so here at the &lt;a href=&quot;https://anderly.com/woocommerce-mailchimp/&quot;&gt;WooCommerce MailChimp plugin page&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;&lt;a href=&quot;https://github.com/anderly/woocommerce-mailchimp#twitter&quot;&gt;&lt;/a&gt;Twitter&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://twitter.com/anderly&quot;&gt;Follow @anderly on Twitter&lt;/a&gt; for updates on this and other plugins.&lt;/p&gt;
&lt;h3&gt;&lt;a href=&quot;https://github.com/anderly/woocommerce-mailchimp#translations&quot;&gt;&lt;/a&gt;Translations&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;English (default)&lt;/li&gt;
&lt;li&gt;No other translations yet.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks in advance for your help on any translation efforts!&lt;/p&gt;
&lt;h3&gt;Installation&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Upload or extract the &lt;code&gt;woocommerce-mailchimp&lt;/code&gt; folder to your site’s &lt;code&gt;/wp-content/plugins/&lt;/code&gt; directory. You can also use the &lt;em&gt;Add new&lt;/em&gt; option found in the &lt;em&gt;Plugins&lt;/em&gt; menu in WordPress.&lt;/li&gt;
&lt;li&gt;Enable the plugin from the &lt;em&gt;Plugins&lt;/em&gt; menu in WordPress.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Usage&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Go to WooCommerce &amp;gt; Settings &amp;gt; Integration &amp;gt; MailChimp&lt;/li&gt;
&lt;li&gt;First, enable the plugin and set your MailChimp API Key and hit save.&lt;/li&gt;
&lt;li&gt;Select whether you want customers subscribed to your MailChimp list after order creation or order completion (there’s a difference in WooCommerce).&lt;/li&gt;
&lt;li&gt;Next, select your MailChimp list and set any interest group settings (optional) and hit save.&lt;/li&gt;
&lt;li&gt;That’s it, now customers who purchase products from your WooCommerce store will automatically be subscribed to the selected list (and optional interest groups) in MailChimp!&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Screenshots&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;WooCommerce MailChimp options screen.&lt;br /&gt;
&lt;a href=&quot;https://anderly.com/wp-content/uploads/2013/10/screenshot-1.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2013/10/screenshot-1-300x288.png&quot; alt=&quot;screenshot-1&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
</content:encoded><category>WordPress</category><category>WordPress Plugins</category></item><item><title>Sublime Text 2/Textmate port of studiostyl.es “Son of Obsidian” theme for Visual Studio</title><link>https://anderly.com/2013/02/15/sublime-text-2textmate-port-of-studiostyl-es-son-of-obsidian-theme-for-visual-studio/</link><guid isPermaLink="true">https://anderly.com/2013/02/15/sublime-text-2textmate-port-of-studiostyl-es-son-of-obsidian-theme-for-visual-studio/</guid><description>I’ve been a fan of the popular Son of Obsidian theme for Visual Studio since it came out a couple of years ago. However, I’ve found myself using Sublime Text 2 more and more because it’s lightweight, fast and has some great features that almost make it full like a full IDE without the bulk…</description><pubDate>Fri, 15 Feb 2013 14:59:26 GMT</pubDate><content:encoded>&lt;p&gt;I’ve been a fan of the popular &lt;a href=&quot;http://studiostyl.es/schemes/son-of-obsidian&quot;&gt;Son of Obsidian theme&lt;/a&gt; for Visual Studio since it came out a couple of years ago. However, I’ve found myself using &lt;a href=&quot;http://www.sublimetext.com/2&quot;&gt;Sublime Text 2&lt;/a&gt; more and more because it’s lightweight, fast and has some great features that almost make it full like a full IDE without the bulk. However, I missed my Son of Obsidian theme, so awhile back I decided to port the theme and create a Sublime/Textmate compatible version.&lt;/p&gt;
&lt;p&gt;You can find it on GitHub &lt;a href=&quot;https://github.com/anderly/son-of-obsidian-tm&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you have any changes, please feel free to fork it and contribute.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</content:encoded><category>Uncategorized</category></item><item><title>Why Microsoft Developers Should Care About Node.js</title><link>https://anderly.com/2012/07/06/why-microsoft-developers-should-care-about-node-js/</link><guid isPermaLink="true">https://anderly.com/2012/07/06/why-microsoft-developers-should-care-about-node-js/</guid><description>I’ve been a Microsoft developer since I started programming straight out of college and I know there are many others out there just like me. It’s been a comfortable space that has grown steadily over the past 10+ years. However, in the last 3-5 years or so, I branched out of my Microsoft comfort zone…</description><pubDate>Fri, 06 Jul 2012 17:08:53 GMT</pubDate><content:encoded>&lt;p&gt;I’ve been a Microsoft developer since I started programming straight out of college and I know there are many others out there just like me. It’s been a comfortable space that has grown steadily over the past 10+ years. However, in the last 3-5 years or so, I branched out of my Microsoft comfort zone and dipped my toes into other languages, platforms and frameworks such as iOS development, Android, Ruby on Rails, PHP and most recently &lt;a href=&quot;http://nodejs.org&quot;&gt;Node.js&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There’s been a lot of debate since Node’s arrival as to whether or not this is a step backwards for software development. JavaScript on the server? You mean the almost 20-year-old scripting language that I’m still using on the client but only because jQuery makes it look easy? Yes, that JavaScript!&lt;/p&gt;
&lt;p&gt;Likewise, if you came from a &lt;a href=&quot;http://en.wikipedia.org/wiki/Active_Server_Pages&quot;&gt;Classic ASP&lt;/a&gt; development background like me, then you probably knew that with Classic ASP, you usually had 2 languages to pick from: &lt;a href=&quot;http://en.wikipedia.org/wiki/VBscript&quot;&gt;VBScript&lt;/a&gt; (the most common) and &lt;a href=&quot;http://en.wikipedia.org/wiki/JScript&quot;&gt;JScript&lt;/a&gt; (Microsoft’s Implementation of ECMAScript). Other languages such as PerlScript, Python and others could also be installed via third-party Active Scripting Engines, but the two main ones that came built-in were VBScript and JScript/JavaScript.&lt;/p&gt;
&lt;p&gt;While most folks (myself included) used VBScript for Classic ASP development, JScript (JavaScript) was (and still is) an interesting option. It’s dynamic like VBScript, but more structured and case-sensitive like C#. Personally, I always liked JavaScript because of this blend between its dynamic nature and its structured C roots. If you’re in a corporate Microsoft-shop environment like I was up until a year and a half ago, you may still find yourself maintaining some legacy Classic ASP systems. If so, I encourage you to experiment with JavaScript and Classic ASP. It will prepare you for getting used to JavaScript on the server with Node.js. If you’re strictly a .NET developer, think a malleable C# without so many rules. To use JavaScript for Classic ASP, you simply add the following language directive to the top of your .asp files:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;%@ language=&quot;javascript&quot;%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then you can do something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;%
// CustomerRepository class

var CustomerRepository = function() {
  this.save = function(customer) {
    // insert/update in db
  };

  this.findById = function(id) {
    // retrieve from db by id
  };

  this.delete = function(id) {
    // delete from db by id
  };
};

var customerRepository = new CustomerRepository();

// In Classic ASP or other programming languages, this would block the current thread until the database returned the customer
var customer = customerRepository.findById(12345);
%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you’re a C# developer, this probably looks very familiar. It’s not statically typed like C#, but the syntax is familiar and clean.&lt;/p&gt;
&lt;p&gt;Now, as far as Node.js goes, this same “class” could be made into a simple Node.js module with some minor changes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First, we’d remove the angle-bracket percent (&amp;lt;%%&amp;gt;) tags&lt;/li&gt;
&lt;li&gt;Next, we’d rename the file to CustomerRepository.js and export this as a module&lt;/li&gt;
&lt;li&gt;Finally, using Node’s callback convention, we’d add a callback parameter to our methods like below. Or, we could use an event-driven approach by inheriting from Node’s EventEmitter.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Then, we’d end up with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// CustomerRepository class

var CustomerRepository = function() {
  this.save = function(customer, callback) {
    // insert/update in db
  };
  this.findById = function(id, callback) {
    // in a real app, we&apos;d kick off some I/O and retrieve the customer from
    // a database, web service or somewhere else
    // since this isn&apos;t a real app, we need to throw this on the event loop/queue 
    // so as not to block the current thread. We do that using process.nextTick
    // if I hadn&apos;t wrapped this in process.nextTick, then this would actually
    // fire immediately which would block Node&apos;s main thread which is a
    // bad thing since there&apos;s only one of them!!!
    process.nextTick(function() {
      callback({ id:123456, name:&apos;Joe Customer&apos;, email:&apos;joe@somewhere.com&apos; });
    });
  };

  this.delete = function(id, callback) {
    // delete from db by id
  };
};

module.exports = new CustomerRepository();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using Node’s &lt;strong&gt;require&lt;/strong&gt; statement (akin to &lt;strong&gt;include&lt;/strong&gt; in Classic ASP or &lt;strong&gt;using&lt;/strong&gt; in C#), we could then import this module like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var customerRepository = require(&apos;./lib/CustomerRepository.js&apos;);

// In Node.js this will not block the current thread since this is an I/O operation
customerRepository.findById(12345, function(err, customer){
  if (err) {
    console.log(&apos;Oh no, something bad happened: &apos; + err);
  } else {
    console.log(&apos;Yippee! We got a customer back: &apos; + customer.name);
    // now, do something with the customer object
  }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nothing revolutionary here. My point is to simply show you that there is nothing inherently magical or complicated about JavaScript on the server. It’s still the same JavaScript you use on the client today with libraries like jQuery etc. and the same JavaScript you could have used with Classic ASP 15 years ago.&lt;/p&gt;
&lt;p&gt;However, the part that does make JavaScript magical on the server is Node. It’s built on top of Google Chrome’s &lt;a href=&quot;http://code.google.com/p/v8/&quot;&gt;V8 JavaScript Engine&lt;/a&gt;. For those of you that are using Chrome, you know how fast Google Chrome is. Well, V8 is the magic behind Chrome’s speed performance when it comes to JavaScript.&lt;/p&gt;
&lt;p&gt;What Node does is bring that speed and performance to the server in the form of a fast, lightweight, single-threaded event loop. Wait! Hold Up! Did you say “single-threaded?” Yes, I said “single-threaded.” Rather than spawn new threads or use a pool of worker threads to service new requests, Node takes a different approach to performance in the form of a non-blocking evented model that is designed to be asynchronous. This is good for developers because it means we don’t have to worry about thread pool management, sync locks, mutexes, race conditions and the joy (sarcasm) that is debugging multi-threaded programs. However, in order for Node to allow a single thread to handle multiple concurrent requests, you can never allow the main thread to wait on blocking, synchronous or CPU-bound operations. Note the phrase “&lt;strong&gt;you&lt;/strong&gt; can never allow” in the previous sentence. Node will not prevent you from writing blocking, synchronous or high CPU-bound operations. Node will handle making I/O operations non-blocking for you, but for anything else, It is your responsibility as the developer to make sure you are writing non-blocking, asynchronous code. Node simply gives you the framework and &lt;a href=&quot;http://wekeroad.com/2012/02/25/nodejs-callback-conventions-and-your-app/&quot;&gt;conventions&lt;/a&gt; for doing so, but it does not mandate this. You read more about how Node works &lt;a href=&quot;http://nodejs.org/about/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Still, you may ask, “Why JavaScript on the server?” Well, if you’re doing web development these days you are probably using JavaScript on the client for things like form validation, DOM manipulation, ajax, lazy content-loading, etc. If you’re working with web services, you have probably consumed &lt;a href=&quot;http://www.json.org/&quot;&gt;JSON&lt;/a&gt; through an API like Twitter, Facebook or maybe you’ve rolled your own. So, you’re using JavaScript on the client. JavaScript in transport (in the form of JSON) and you may even be storing some JSON on the server whether as serialized data in a relational-database such as SQL Server, Oracle, MySQL or PostGres. Or, maybe you’re using a NoSQL database such as MongoDB, CouchDB or even Azure Table Storage.&lt;/p&gt;
&lt;p&gt;So, if you’re using JavaScript on the client, JavaScript in-transport and JavaScript for persistence. It only begs the question, should JavaScript be used on the server?&lt;/p&gt;
&lt;p&gt;Node’s answer is “yes” and many developers have come to that same conclusion (end-to-end JavaScript) and that is why Node.js has gone from an obscure project just a few short years ago to one of the most actively followed projects on GitHub today.&lt;/p&gt;
&lt;p&gt;Now, we get to the part of why you should care about Node.js as a Microsoft / .NET developer.&lt;/p&gt;
&lt;p&gt;Microsoft has taken notice of Node’s growing popularity and its merits and they have worked with the Node.js community on Windows support for node and IIS support through &lt;a href=&quot;https://github.com/tjanczuk/iisnode/&quot;&gt;iisnode&lt;/a&gt;. Microsoft has embraced Node.js as a first-class citizen in Windows Azure, going from MIA a little over a year ago to being listed as the first language (below .NET) on their &lt;a href=&quot;https://www.windowsazure.com/en-us/develop/overview/&quot;&gt;Window Azure Developer Center&lt;/a&gt;, ahead of Java, PHP and Python.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2012/07/2012-07-06_13-48-17.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2012/07/2012-07-06_13-48-17-300x153.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Node.js on Azure is actually a great story that has &lt;a href=&quot;http://blogs.msdn.com/b/hanuk/archive/2012/05/05/top-benefits-of-running-node-js-on-windows-azure.aspx&quot;&gt;many benefits&lt;/a&gt; aside from running Node yourself.&lt;/p&gt;
&lt;p&gt;As &lt;a href=&quot;http://www.guardian.co.uk/technology/blog/2011/nov/09/programming-microsoft&quot;&gt;this article&lt;/a&gt; points out, Microsoft doesn’t adopt outside technologies that aren’t established. Just like their official support for jQuery, Microsoft’s support of Node.js signifies a shift from “cool fringe technology that carries too much risk to use on a real project” to “something I should at least start becoming familiar with in case it becomes the next jQuery.”&lt;/p&gt;
&lt;p&gt;Despite this, you may ask yourself, “Is JavaScript-development the direction I want to take my career?” Well, look no further than Windows 8 and its support for building Metro apps with HTML5, CSS and…..JavaScript. I submit that just like writing Classic ASP with JavaScript wouldn’t make you any less of a Microsoft developer 15 years ago, writing Node.js apps with JavaScript won’t make you any less of a Microsoft developer today. JavaScript is here to stay. If you don’t like the language or its syntax, then take a look at &lt;a href=&quot;http://coffeescript.org/&quot;&gt;CoffeeScript&lt;/a&gt;, a little syntactic sugar over JavaScript.&lt;/p&gt;
&lt;p&gt;Who knows, your next project might be an HTML5, CSS and JavaScript Windows 8 Metro App that communicates with a Node.js server running on Windows Azure backed by MongoDb. Sneak in a little JavaScript into that Classic ASP app you’re still supporting 12 years later and you’ll feel right at home.&lt;/p&gt;
&lt;p&gt;If you’re a Microsoft developer, let me know what you think of Node.js in the comments.&lt;/p&gt;
&lt;p&gt;Happy JavaScripting!&lt;/p&gt;
</content:encoded><category>Node.js</category></item><item><title>Status of SimpleMembership.Mvc3 and SimpleMembership.Mvc3.Sample</title><link>https://anderly.com/2012/03/09/status-of-simplemembership-mvc3-and-simplemembership-mvc3-sample/</link><guid isPermaLink="true">https://anderly.com/2012/03/09/status-of-simplemembership-mvc3-and-simplemembership-mvc3-sample/</guid><description>I have received a couple of questions and requests over the past 6 months or so regarding my plans to update both the SimpleMembership.Mvc3 and SimpleMembership.Mvc3.Sample packages. In short, I’m planning on updating these but I just haven’t gotten to it yet. I’ve been very busy lately with some other projects such as Expansive and…</description><pubDate>Fri, 09 Mar 2012 16:56:29 GMT</pubDate><content:encoded>&lt;p&gt;I have received a couple of questions and requests over the past 6 months or so regarding my plans to update both the SimpleMembership.Mvc3 and SimpleMembership.Mvc3.Sample packages.&lt;/p&gt;
&lt;p&gt;In short, I’m planning on updating these but I just haven’t gotten to it yet. I’ve been very busy lately with some other projects such as &lt;a href=&quot;https://github.com/anderly/Expansive&quot;&gt;Expansive&lt;/a&gt; and my &lt;a href=&quot;https://github.com/anderly/dnsimple-csharp&quot;&gt;C# wrapper for the DNSimple REST API&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, in preparation for these changes I have started a Trello board here: &lt;a href=&quot;https://trello.com/board/simplemembership/4f23419c0fa7e50d34585d9e&quot;&gt;https://trello.com/board/simplemembership/4f23419c0fa7e50d34585d9e&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I’m using this to track requests I have received and to communicate the status of the features that have been requested.&lt;/p&gt;
&lt;p&gt;Please feel free to comment on them or vote or request new features.&lt;/p&gt;
&lt;p&gt;However, these being open source projects on GitHub, please also feel free to fork them, add your desired features and submit a pull request to me to merge your changes back into the trunk.&lt;/p&gt;
&lt;p&gt;Both projects can be found on GitHub using the following links:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/anderly/SimpleMembership.Mvc3&quot;&gt;https://github.com/anderly/SimpleMembership.Mvc3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/anderly/SimpleMembership.Mvc3.Sample&quot;&gt;https://github.com/anderly/SimpleMembership.Mvc3.Sample&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I am going to try to get these changes done soon, but I just haven’t been able to dedicate any time to them yet.&lt;/p&gt;
&lt;p&gt;In the meantime, thanks again for your interest, feedback, questions and requests regarding SimpleMembership.&lt;/p&gt;
&lt;p&gt;Stay tuned…&lt;/p&gt;
</content:encoded><category>.NET</category><category>ASP.NET MVC</category><category>NuGet</category></item><item><title>Expansive 1.5 Released</title><link>https://anderly.com/2011/10/14/expansive-1-5-released/</link><guid isPermaLink="true">https://anderly.com/2011/10/14/expansive-1-5-released/</guid><description>Yesterday, I blogged about my new .NET string expansion library called Expansive. Today, I made some key changes to, hopefully, make it easier to use and more flexible by providing 4 token style format providers out of the box. Removed the startToken and endToken delimiters that could be set by the consumer as this was…</description><pubDate>Fri, 14 Oct 2011 19:43:27 GMT</pubDate><content:encoded>&lt;p&gt;Yesterday, I &lt;a href=&quot;https://anderly.com/2011/10/13/expansive-a-powerful-string-expansion-library-for-dotnet-you-never-knew-you-always-wanted/&quot;&gt;blogged&lt;/a&gt; about my new .NET string expansion library called &lt;strong&gt;Expansive&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Today, I made some key changes to, hopefully, make it easier to use and more flexible by providing 4 token style format providers out of the box.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Removed the startToken and endToken delimiters that could be set by the consumer as this was unreliable&lt;/li&gt;
&lt;li&gt;Added 4 new Token Style Formats to pick from:
&lt;ul&gt;
&lt;li&gt;MvcRoute Style “{token}” (default)&lt;/li&gt;
&lt;li&gt;Razor Style “@token” or “@(token)”&lt;/li&gt;
&lt;li&gt;NAnt Style “${token}”&lt;/li&gt;
&lt;li&gt;MSBuild Style “$(token)”&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, the following are all valid:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// MvcRoute-Style (default)
var mvcRouteStyleString = &quot;Hello, {FirstName}&quot;.Expand(new { FirstName = &quot;John&quot; });

// Razor-Style
Expansive.DefaultTokenStyle = TokenStyle.Razor;
var razorStyleString = &quot;Hello, @FirstName&quot;.Expand(new { FirstName = &quot;John&quot; });

// NAnt-Style
Expansive.DefaultTokenStyle = TokenStyle.NAnt;
var nantStyleString = &quot;Hello, ${FirstName}&quot;.Expand(new { FirstName = &quot;John&quot; });

// MSBuild-Style
Expansive.DefaultTokenStyle = TokenStyle.MSBuild;
var msBuildStyleString = &quot;Hello, $(FirstName)&quot;.Expand(new { FirstName = &quot;John&quot; });

// all return &quot;Hello, John&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can also specify the TokenStyle on the call to Expand() such as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var expandedString = &quot;Hello, @FirstName&quot;.Expand(new { FirstName = &quot;John&quot; }, TokenStyle.Razor);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The addition of TokenStyle makes the API a little cleaner and provide 4 popular token formats.&lt;/p&gt;
&lt;p&gt;You can of course add your own by grabbing the source on &lt;a href=&quot;https://github.com/anderly/Expansive&quot;&gt;GitHub&lt;/a&gt; and opening the hood.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</content:encoded><category>.NET</category><category>ASP.NET MVC</category><category>NuGet</category></item><item><title>Expansive – A powerful string expansion library for .NET you never knew you always wanted.</title><link>https://anderly.com/2011/10/13/expansive-a-powerful-string-expansion-library-for-dotnet-you-never-knew-you-always-wanted/</link><guid isPermaLink="true">https://anderly.com/2011/10/13/expansive-a-powerful-string-expansion-library-for-dotnet-you-never-knew-you-always-wanted/</guid><description>Expansive having a capacity or tendency to expand. causing or tending to cause expansion characterized by richness, abundance or magnificence While working on a recent project involving lots of appSettings keys and values in my web.config/app.config files and some values that have overlapping information (server names, file paths, etc.), I realized how much I missed…</description><pubDate>Thu, 13 Oct 2011 19:23:30 GMT</pubDate><content:encoded>&lt;p&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/expansive.png&quot; alt=&quot;expansive&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Expansive&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;having a capacity or tendency to expand.&lt;/li&gt;
&lt;li&gt;causing or tending to cause expansion&lt;/li&gt;
&lt;li&gt;characterized by richness, abundance or magnificence&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;While working on a recent project involving lots of appSettings keys and values in my web.config/app.config files and some values that have overlapping information (server names, file paths, etc.), I realized how much I missed the property expansion capabilities of &lt;a href=&quot;http://nant.sourceforge.net/&quot;&gt;NAnt&lt;/a&gt; and, more recently, &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/0k6kkbsd.aspx&quot;&gt;MSBuild&lt;/a&gt;. So, I set out to see if I could quickly build a simple string property expansion library to solve this common problem and maybe some others along the way.&lt;/p&gt;
&lt;p&gt;While I knew that true &lt;a href=&quot;http://en.wikipedia.org/wiki/String_interpolation&quot;&gt;string interpolation&lt;/a&gt; would be somewhat tricky and probably best left to the framework developers, I felt that an easy add-on API using extension methods and possibly some new helper classes could at least make my life easier.&lt;/p&gt;
&lt;p&gt;Channeling &lt;a href=&quot;http://blog.wekeroad.com&quot;&gt;Rob Conery&lt;/a&gt;, I named my new library &lt;strong&gt;Expansive&lt;/strong&gt; as a play on Expansion and Expensive (sarcasm) as I wanted something that wasn’t expensive (technically) and was easy to implement and easy to learn.&lt;/p&gt;
&lt;p&gt;You can check out the full capabilities via the readme over on &lt;a href=&quot;http://github.com/anderly/Expansive&quot;&gt;GitHub&lt;/a&gt;, but I’ll give you a couple of examples and ideas on how it can be used.&lt;/p&gt;
&lt;h3&gt;1. Solve web.config / app.config nightmares&lt;/h3&gt;
&lt;p&gt;Many times I find that in large applications, I have many web.config / app.config appSettings keys, connection strings, etc and that many of the values have redundant information. For instance server names, IP Addresses or paths may be strewn throughout several appSettings keys and I find myself wishing I could just define the data once, so as to “normalize” my appSettings, and then simply reference one key from the value of another. What I really want is a composition model where I can compose different appSettings (or other strings for that matter) using previously defined values.&lt;/p&gt;
&lt;p&gt;Here’s a common scenario:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I may have a connection string defined with a server name: dbserver01&lt;/li&gt;
&lt;li&gt;I may have environment specific naming conventions like (dbserver01-dev, dbserver01-qa, dbserver01-stg, dbserver01-prod, etc)&lt;/li&gt;
&lt;li&gt;I may have other server names in my appSettings like urls for services, unc paths for fileshares, report server urls, etc.&lt;/li&gt;
&lt;li&gt;While I can certainly duplicate the server names and environment suffix throughout the various appSettings keys, it quickly becomes a chore to make sure these are all correct for a specific environment.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://msdn.microsoft.com/en-us/library/dd465326.aspx&quot;&gt;Web.config transforms&lt;/a&gt; help a little bit in that they allow me to define values for different configurations, but it still doesn’t give me a composition model where I can simplify my web.config / app.config settings so that they are easier to manage and maintain. Plus web.config transforms only help at build/deploy time. There is no story for runtime changes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Expansive aims to solve that problem by allowing for NAnt-like &lt;a href=&quot;http://nant.sourceforge.net/release/0.85/help/fundamentals/properties.html&quot;&gt;property expansion&lt;/a&gt; (scroll down to section 6) whereby I can define an appSetting once such as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;add key=&quot;env&quot; value=&quot;dev&quot;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then be able to reuse that value in other settings such as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;add key=&quot;ServerName&quot; value=&quot;dbserver01-{env}&quot;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And, then finally use that value inside of a connection string such as:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;add name=&quot;Default&quot; connectionString=&quot;server={ServerName};Initial Catalog=master;uid=uid;pwd=pwd&quot; provider=&quot;System.Data.SqlClient&quot;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, I’m defining the &lt;strong&gt;“&lt;strong&gt;env&lt;/strong&gt;“&lt;/strong&gt; setting once and then reusing that in the “ServerName” setting, which is then used in the connection string.&lt;/p&gt;
&lt;p&gt;To get the “expanded” values, you simply call the Expand() extension method on string. For instance:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var connectionString = ConfigurationManager.ConnectionStrings[&quot;Default&quot;].ConnectionString.Expand();
// returns &quot;server=dbserver01-dev;Initial Catalog=master;uid=uid;pwd=pwd&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or you can use the dynamic ConfigurationManager wrapper “Config” as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var connectionString = Config.ConnectionStrings.Default;
// returns &quot;server=dbserver01-dev;Initial Catalog=master;uid=uid;pwd=pwd&quot; without needing explicit call to Expand()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By default expansive looks in your web.config or app.config appSettings for the tokens to lookup and expand. However, you can change this or provide your own “source” in the form of a Func&amp;lt;string, string&amp;gt; lambda on the call to Expand() which you’ll see in one of the examples below.&lt;/p&gt;
&lt;p&gt;While you obviously have to take care in setting this up the first time, it allows for easily making changes to a series of settings by following a composition model where settings build on one another.&lt;/p&gt;
&lt;p&gt;This web.config / app.config example is probably the most common, but this can also be used for string formatting / templating.&lt;/p&gt;
&lt;h3&gt;2. String Formatting&lt;/h3&gt;
&lt;p&gt;How many times have you written something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var welcomeMessage = string.Format(&quot;Hello, {0}&quot;, &quot;John&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While it’s a fairly simple example and pretty easy to see from the argument context that the name “John” will get substituted in place of the “{0},” often times these types of strings are in a resource file, config file or database and when looking at them alone and without argument context, it’s not always easy to see what the ‘expectations’ of that string are. For instance if this were localized, it might just read “{0}, {1}” in a resource file. While the key may be something like “welcomeMessage,” it still may not be immediately apparent what that string format requires.&lt;/p&gt;
&lt;p&gt;How much more readable and explicit would it be if we could write:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Simple positional based formatting
// Essentially gets transformed into string.Format(&quot;{0} {1}&quot;,&quot;Hello&quot;, &quot;John&quot;)
var welcomeMessage = &quot;{greeting}, {firstName}&quot;.Expand(&quot;Hello&quot;, &quot;John&quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is is the simple alternative to string.Format() that Expansive provides in the form of an a simple Expand() extension method on string.&lt;/p&gt;
&lt;p&gt;Remember, if I hadn’t provided the arguments (“Hello” and “John”) to the Expand() method, it would have looked for “greeting” and “firstName” keys in my web.config / app.config appSettings. Again, this is just the default, but you can change it globally or on a per call basis. For instance, you could tell Expansive to pull these values out of resource file, a database table, from a webservice, what have you.&lt;/p&gt;
&lt;p&gt;Some other ways in which you could accomplish the same thing with Expansive would be:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Same as above just with variables defined first
// NOTE: This is positional replacement, not actual string interpolation based on variable names
// Again, this gets tranformed into string.Format(&quot;{0}, {1}&quot;, &quot;Hello&quot;, &quot;John&quot;)
var greeting = &quot;Hello&quot;;
var firstName = &quot;John&quot;;
var welcomeMessage = &quot;{greeting}, {firstName}&quot;.Expand(greeting, firstName);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Example using a Dictionary&amp;lt;string, string&amp;gt; and containing key/value pairs for expansion
// This could come from a database, file, web service, etc.
var resourceDictionary = new Dictionary&amp;lt;string, string&amp;gt; {
 {&quot;greeting&quot;,&quot;Hello&quot;}
 ,{&quot;firstName&quot;,&quot;John&quot;}
};

// call Expand() passing in a custom Func&amp;lt;string, string&amp;gt; lamda for key/value lookup
var welcomeMessage = &quot;{greeting}, {firstName}&quot;.Expand(key =&amp;gt; resourceDictionary[key]);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note, you could also do this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// Example of reusing tokens inside of another string
// NOTE: This is positional replacement, not actual string interpolation based on variable names
// This essentially becomes string.Format(&quot;FirstName: {0}, LastName:{1}, FullName: {0} {1}&quot;, &quot;John&quot;, &quot;Smith&quot;)
var firstName = &quot;John&quot;;
var lastName = &quot;Smith&quot;;
var fullName = &quot;{firstName} {lastName}&quot;
var welcomeMessage = &quot;FirstName: {firstName}, LastName: {lastName}, FullName: {fullName}&quot;.Expand(firstName, lastName, fullName);

// NOTE: For fullName to work above, the &quot;{firstName}&quot; &quot;{lastName}&quot; tokens must have been in the string to be expanded.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, as you can see this is pretty powerful and easy to read in that you can assign friendly names to the tokens vs. just have {0}, {1}, {2}… etc.&lt;/p&gt;
&lt;h3&gt;3. Model-based Templating&lt;/h3&gt;
&lt;h3&gt;Additionally, Expansive can be used for model-based templating using the Expand(object model) method.&lt;/h3&gt;
&lt;p&gt;This allows you to do the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;var model = new { FirstName = &quot;John&quot;, LastName = &quot;Smith&quot; };

var testString = &quot;First:{FirstName}, Last:{LastName}&quot;.Expand(model);
// returns &quot;First:John, Last:Smith&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, Expansive replaces the tokens in the string with the values of the corresponding properties on the passed model object. Nice and clean!&lt;/p&gt;
&lt;p&gt;Arguably, this is the most powerful feature and my favorite to use, but I’m curious to get your take.&lt;/p&gt;
&lt;p&gt;Download it from &lt;a href=&quot;https://github.com/anderly/Expansive&quot;&gt;GitHub&lt;/a&gt; or install it using &lt;a href=&quot;http://nuget.org/List/Packages/Expansive&quot;&gt;NuGet&lt;/a&gt; and let me know what you think.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</content:encoded><category>.NET</category><category>ASP.NET MVC</category><category>NuGet</category></item><item><title>Using SimpleMembership in MVC3</title><link>https://anderly.com/2011/08/11/using-simplemembership-in-mvc3/</link><guid isPermaLink="true">https://anderly.com/2011/08/11/using-simplemembership-in-mvc3/</guid><description>I have received a couple of questions over the past few weeks regarding how to properly get SimpleMembership to work with an MVC3 application. While it is pretty straightforward, the purpose of this post is to serve as a step-by-step “How To” setup SimpleMembership with an MVC 3 application from start to finish. The following…</description><pubDate>Thu, 11 Aug 2011 21:43:53 GMT</pubDate><content:encoded>&lt;p&gt;I have received a couple of questions over the past few weeks regarding how to properly get SimpleMembership to work with an MVC3 application. While it is pretty straightforward, the purpose of this post is to serve as a step-by-step “How To” setup SimpleMembership with an MVC 3 application from start to finish.&lt;/p&gt;
&lt;p&gt;The following 4 simple steps will get you up and running with SimpleMembership in your MVC3 application in a matter of minutes. We’ll go into each step in more detail below.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create new Mvc3 Internet Application or use an existing one.&lt;/li&gt;
&lt;li&gt;Create your SqlServer, SqlExpress or SqlCompact4 database (we’ll be using SqlCompact4 in this example)&lt;/li&gt;
&lt;li&gt;Update Web.config with connection string to point to your database from step 2&lt;/li&gt;
&lt;li&gt;Install &amp;amp; Configure SimpleMembership.Sample package&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Creating your MVC 3 Application&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Select File &amp;gt; New Project and Select &lt;strong&gt;ASP.NET MVC 3 Web Application.&lt;br /&gt;
&lt;a href=&quot;https://anderly.com/wp-content/uploads/2011/08/Step-1-1.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2011/08/Step-1-1-300x207.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Pick your desired folder location and click &lt;strong&gt;Ok.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Next, make sure &lt;strong&gt;Internet Application&lt;/strong&gt; is selected and Razor is the View engine.&lt;br /&gt;
&lt;a href=&quot;https://anderly.com/wp-content/uploads/2011/08/Step-1-2.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2011/08/Step-1-2-300x270.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;In this case, we chosen to create a unit test project automatically for testing purposes.&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;OK&lt;/strong&gt; to create your project.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Creating your database (SqlCompact4)&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Before we do anything else, we are going to create a SqlCompact4 database rather than using SQLExpress which is the default for new projects.&lt;/li&gt;
&lt;li&gt;To do so, right-click the App_Data directory and select &lt;strong&gt;Add &amp;gt; New Item.&lt;br /&gt;
&lt;a href=&quot;https://anderly.com/wp-content/uploads/2011/08/Step-2-1.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2011/08/Step-2-1-300x278.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;In the next dialog, select &lt;strong&gt;SQL Server Compact 4.0 Local Database,&lt;/strong&gt; use “Database.sdf” as the filename and click &lt;strong&gt;Add.&lt;br /&gt;
&lt;a href=&quot;https://anderly.com/wp-content/uploads/2011/08/Step-2-2.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2011/08/Step-2-2-300x207.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Updating Web.config connection string&lt;/h2&gt;
&lt;h2&gt;Now that our database is created, we need to update our connection string in Web.config to point to our SqlCompact4 database we just created.&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Open Web.config and locate the connection string named “Application Services”.&lt;br /&gt;
&lt;a href=&quot;https://anderly.com/wp-content/uploads/2011/08/Step-3-11.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2011/08/Step-3-11-300x218.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Next, change the “Application Services” connectionString and providerName to the following:&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;lt;add name=“ApplicationServices“ connectionString=“data source=|DataDirectory|\Database.sdf“ providerName=“System.Data.SqlServerCe.4.0“ /&amp;gt;&lt;/p&gt;
&lt;h2&gt;Installing &amp;amp; Configuring SimpleMembership&lt;/h2&gt;
&lt;p&gt;Now, that we have our application ready, SqlCompact database created and ready to go, now we can install SimpleMembership. For the sake of simplicity, I’m going to install the SimpleMembership.Mvc3.Sample package which include the sample account controller pre-wired for use with SimpleMembership.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In Visual Studio, navigate to &lt;strong&gt;Tools &amp;gt; Library Package Manager &amp;gt; Manage NuGet Packages.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Online&lt;/strong&gt; from the left-hand pane and type in SimpleMembership in the search box at the top right.&lt;/li&gt;
&lt;li&gt;Select the &lt;strong&gt;SimpleMembership.Mvc3.Sample&lt;/strong&gt; package and click &lt;strong&gt;Install.&lt;br /&gt;
&lt;a href=&quot;https://anderly.com/wp-content/uploads/2011/08/Step-4-1.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2011/08/Step-4-1-300x153.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Next, delete the existing &lt;strong&gt;Controllers/AccountController.cs&lt;/strong&gt; file that Visual Studio created for you.&lt;/li&gt;
&lt;li&gt;Rename &lt;strong&gt;Controllers/SimpleMembershipAccountController.cs&lt;/strong&gt; to &lt;strong&gt;AccountController.cs&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Open &lt;strong&gt;App_Start/SimpleMembershipMvc3.cs&lt;/strong&gt; and update it to point to the &lt;strong&gt;“ApplicationServices”&lt;/strong&gt; connection string or your appropriate connection string.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;That’s It!&lt;/h2&gt;
&lt;p&gt;You’re application is now ready to use SimpleMembership and you have a fully-functional AccountController.cs pre-wired to use the SimpleMembership API.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Enjoy!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Please post a comment if you have questions or run into issues.&lt;/p&gt;
&lt;p&gt;The code is available here: &lt;a href=&quot;https://anderly.com/wp-content/uploads/2011/08/SimpleMembership.Mvc3_.Example.zip&quot;&gt;SimpleMembership.Mvc3.Example.zip&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>Uncategorized</category></item><item><title>SimpleMembership.Mvc3 – 1.1 Published</title><link>https://anderly.com/2011/05/18/simplemembership-mvc3-1-1-published/</link><guid isPermaLink="true">https://anderly.com/2011/05/18/simplemembership-mvc3-1-1-published/</guid><description>If you’re unfamiliar with SimpleMembership.Mvc3, please see this post. Update: May 18, 2011 – Version 1.1 published to NuGet.org This includes: Minor fix to WebSecurityService to address bug reported by Phil Haack. Added assembly reference to web.config.transform to reference WebMatrix.Data. Some users have reported exceptions being thrown trying to reference that namespace. New SimpleMembershipAccountController which…</description><pubDate>Wed, 18 May 2011 18:18:48 GMT</pubDate><content:encoded>&lt;h2&gt;If you’re unfamiliar with &lt;strong&gt;SimpleMembership.Mvc3&lt;/strong&gt;, please see &lt;a href=&quot;https://anderly.com/2011/01/18/simplemembership-mvc3-nuget-package/&quot;&gt;this post&lt;/a&gt;.&lt;/h2&gt;
&lt;h4&gt;&lt;strong&gt;Update: May 18, 2011 – Version 1.1 published to NuGet.org&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;This includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Minor fix to WebSecurityService to address bug reported by Phil Haack.&lt;/li&gt;
&lt;li&gt;Added assembly reference to web.config.transform to reference WebMatrix.Data. Some users have reported exceptions being thrown trying to reference that namespace.&lt;/li&gt;
&lt;li&gt;&lt;s&gt;New SimpleMembershipAccountController which can be used as a drop-in replacement for the default AccountController in new Mvc projects. This controller uses WebSecurityService instead of the FormsAuthenticationService and MembershipService for authentication and membership.&lt;/s&gt; The SimpleMembershipAccountController has been moved to a new sample package: &lt;a href=&quot;http://nuget.org/List/Packages/SimpleMembership.Mvc3.Sample&quot;&gt;SimpleMembership.Mvc3.Sample&lt;/a&gt; It can be used as a drop-in replacement for the default AccountController in the Mvc3 Visual Studio project template. It uses the WebSecurityService from SimpleMembership.Mvc3 instead of the FormsAuthenticationService and MembershipService which come in the default project template.&lt;/li&gt;
&lt;/ul&gt;
</content:encoded><category>.NET</category><category>ASP.NET MVC</category><category>Dependency Injection</category><category>NuGet</category></item><item><title>SimpleMembership.Mvc3 NuGet Package</title><link>https://anderly.com/2011/01/18/simplemembership-mvc3-nuget-package/</link><guid isPermaLink="true">https://anderly.com/2011/01/18/simplemembership-mvc3-nuget-package/</guid><description>SimpleMembership.Mvc3 – 1.0 Enables the SimpleMembership API from WebMatrix/WebPages (i.e. WebSecurity) to be used with ASP.NET MVC3. This allows you to use the WebSecurity helper found in the WebMatrix.WebData namespace. Update: February 28, 2011 – Version 1.0 released This includes: The App_Start convention from David Ebbo’s post. An updated dependency on WebActivator 1.3.2 or greater…</description><pubDate>Tue, 18 Jan 2011 17:39:19 GMT</pubDate><content:encoded>&lt;h2&gt;SimpleMembership.Mvc3 – 1.0&lt;/h2&gt;
&lt;p&gt;Enables the SimpleMembership API from WebMatrix/WebPages (i.e. WebSecurity) to be used with ASP.NET MVC3. This allows you to use the WebSecurity helper found in the WebMatrix.WebData namespace.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;Update: February 28, 2011 – Version 1.0 released&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;This includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The App_Start convention from David Ebbo’s &lt;a href=&quot;http://blog.davidebbo.com/2011/02/appstart-folder-convention-for-nuget.html&quot;&gt;post&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;An updated dependency on WebActivator 1.3.2 or greater (This allows us to use the new PostApplicationStartMethod in WebActivator which allows us to remove the need to modify global.asax.cs).&lt;/li&gt;
&lt;li&gt;Removed need to modify global.asax.cs&lt;/li&gt;
&lt;li&gt;Now, the call to WebSecurity.InitializeDatabaseConnection() is in the new Post App Startup method called Initialize() inside App_Start/SimpleMembershipMvc3.cs. This is where you’ll need to specify your connection string and user table.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Features&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Includes a web activator and web.config transforms that enable the SimpleMembershipProvider&lt;/li&gt;
&lt;li&gt;Includes an abstraction of the WebSecurity helper (IWebSecurityService) and an implementation (WebSecurityService) to enable use with DI/IoC frameworks such as NInject, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Usage&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2011/01/SimpleMembershipMvc3.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2011/01/SimpleMembershipMvc3.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Modify the Initialize() method in App_Start/SimpleMembershipMvc3.cs to point to your connection string and user table.&lt;/li&gt;
&lt;li&gt;That’s It!&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Using the IWebSecurityService abstraction&lt;/h2&gt;
&lt;p&gt;This package includes an abstraction of the WebSecurity interface (Services/IWebSecurityService) as well as an implementation of this interface (Services/WebSecurityService). This is useful for scenarios like using WebSecurity with Ninject or another IoC/DI framework to avoid hard references to WebSecurity and improve testability. To use this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;First, make sure you register WebSecurityService as an IWebSecurityService with your IoC container.&lt;/li&gt;
&lt;li&gt;Next, remove the call to WebSecurity.InitializeDatabaseConnection from the Initialize() method in App_Start/SimpleMembershipMvc3.cs&lt;/li&gt;
&lt;li&gt;Finally, uncomment the following lines and modify the call to InitializeDatabaseConnection() to point to your connection string and user table:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;var webSecurityService = DependencyResolver.Current.GetService&amp;lt;IWebSecurityService&amp;gt;();

webSecurityService.InitializeDatabaseConnection(connectionStringName: &quot;Default&quot;, userTableName: &quot;Users&quot;, userIdColumn: &quot;ID&quot;, userNameColumn: &quot;Username&quot;, autoCreateTables: true);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Currently, the package includes the actual WebMatrix.WebData.dll assembly. I’m looking into changing the package to instead use powershell to add the reference to the project if it already exists on the user machine.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
&lt;p&gt;Adam&lt;/p&gt;
</content:encoded><category>.NET</category><category>ASP.NET MVC</category><category>Dependency Injection</category><category>NuGet</category></item><item><title>ASP.NET MVC, Dependency Injection and The Bliss of Truly Decoupled Applications</title><link>https://anderly.com/2010/11/09/asp-net-mvc-dependency-injection-and-the-bliss-of-truly-decoupled-applications/</link><guid isPermaLink="true">https://anderly.com/2010/11/09/asp-net-mvc-dependency-injection-and-the-bliss-of-truly-decoupled-applications/</guid><description>In traditional software and web applications application layering is one of the tenets of good application design and architecture. It stems from the separation of concerns principle in computer science which is the process of separating applications and programs into distinct features that overlap in functionality as little as possible. Hence, the single responsibility principle…</description><pubDate>Tue, 09 Nov 2010 22:05:00 GMT</pubDate><content:encoded>&lt;p&gt;In traditional software and web applications application layering is one of the tenets of good application design and architecture. It stems from the &lt;a href=&quot;http://en.wikipedia.org/wiki/Separation_of_concerns&quot;&gt;separation of concerns&lt;/a&gt; principle in computer science which is the process of separating applications and programs into distinct features that overlap in functionality as little as possible. Hence, the &lt;a href=&quot;http://en.wikipedia.org/wiki/Single_responsibility_principle&quot;&gt;single responsibility principle&lt;/a&gt; and &lt;a href=&quot;http://en.wikipedia.org/wiki/DRY&quot;&gt;DRY&lt;/a&gt; concepts in software engineering and object-oriented programming.&lt;/p&gt;
&lt;p&gt;Typically, in layered applications, a given application layer should only communicate with and depend on the layer directly below it.&lt;/p&gt;
&lt;p&gt;Take the following diagram for example, taken from the Microsoft Application Architecture Guide v2 (I added the red arrow indicators that typically represent where dependencies are):&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/11/image.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb.png&quot; alt=&quot;image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this example, the Presentation Layer would talk to and depend on the Business Layer. The Business Layer would talk to and depend on the Data Layer. The Data Layer would talk to and depend on the database.&lt;/p&gt;
&lt;p&gt;This is generally considered good application design despite there being dependencies between layers. However, traditionally, layer n-1 dependency (one layer dependency) has been the normal and accepted practice. But experience tells us that all-too-often we find dependencies on more than just one layer. In fact, we may find dependencies between multiple layers…or worse….between all layers, ending up with something like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/11/image4.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb3.png&quot; alt=&quot;image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The application may work fine. In fact, it may work perfectly. But the net effect, in the case of either diagram, is that, with each dependency, change becomes more difficult. Our apps become more difficult to maintain, more difficult to test, and more difficult to change which can result in longer development cycles, higher costs and increased risk of failure on our projects.&lt;/p&gt;
&lt;p&gt;Usually, these dependencies come in the form of concrete class names. For example:&lt;/p&gt;
&lt;p&gt;MyService service = new MyService();&lt;/p&gt;
&lt;p&gt;As &lt;a href=&quot;http://hanselman.com&quot;&gt;Scott Hanselman&lt;/a&gt; would say, “anytime you find yourself writing code like this, quit your job and go do something else.” No seriously, you should at least stop and acknowledge what this really is – a dependency on an implementation. Sure, factory classes and singletons come in handy to remove the need to new things up, but we still end up with a dependency – only now we’re dependent on the Singleton or the Factory.&lt;/p&gt;
&lt;p&gt;Ideally, we want to declare a dependency on “some thing” without saying what that “some thing” is.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;A simplified analogy&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;If you are hungry, you could ask your friend, “do you have a hamburger?” in which case you are expressing a need for an explicit implementation of something that satisfies hunger (a hamburger). If your friend has a hamburger, great! He would give it to you, you would eat it, and you wouldn’t be hungry anymore. Problem solved! But if your friend does not have a hamburger, you’d still be hungry – mainly because you were too specific in your request. Now, instead of asking for the hambuger, you could ask your friend, “do you have anything to eat?” In this case, you are expressing the “need” (food or something that satisfies hunger) vs. a concrete implementation. This way, if your friend has anything to eat he can give it to you (regardless of whether it is a hamburger or not) and you won’t go hungry. Any food would suffice.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;What’s the point?&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The point is that by being less specific in our request for food, we are more adaptable. The same is true with software. If we simply declare dependencies on contracts (interfaces), rather than implementations, our software becomes more adaptable and easier to change. Dependency Injection exists to help you do just that.&lt;/p&gt;
&lt;p&gt;The goal of &lt;a href=&quot;http://en.wikipedia.org/wiki/Dependency_Injection&quot;&gt;Dependency Injection&lt;/a&gt; (DI for short) is to separate behavior (or implementation) from dependency resolution, which is really just &lt;a href=&quot;http://en.wikipedia.org/wiki/Encapsulation_(computer_science)#Encapsulation&quot;&gt;encapsulation&lt;/a&gt; – one of the main principles of computer science and object-oriented programming. I like to think of Dependency Injection as “intra-app &lt;a href=&quot;http://en.wikipedia.org/wiki/Service-oriented_architecture&quot;&gt;SOA&lt;/a&gt;”; the end result being a highly decoupled application composed of “services” with explicit service boundaries and contracts (or service interfaces) where any given application layer has no knowledge of any other layers. It cares not the number of layers nor the implementation within each layer. Each layer simply depends on a contract and can be reasonably sure that at runtime there will be at least one implementation available to satisfy that contract. With Dependency Injection on our side, the above diagram might change to look something like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/11/image5.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb4.png&quot; alt=&quot;image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At first glance, this doesn’t look much different from the first diagram. We still have “dependencies.” However, now we are dependent on a contract, not an actual implementation. This provides enormous benefits to us as application developers because our application layers are now plug-n-play. They are hot-swappable like hard drives in a RAID configuration. We can change the implementation of a layer and as long as we implement the agreed upon interface, we can rest assured we won’t break something in another layer.&lt;/p&gt;
&lt;p&gt;Of course, we still have to unit test our new layer to make sure we don’t have any internal bugs, but as long as other layers only depend on the interface (not the implementation) we know we can reliably swap out an implementation without affecting other parts of an application or system. Ideally, each implementation of an application layer becomes a “black box” to the other layers with which it interacts.&lt;/p&gt;
&lt;p&gt;In the case of our MyService above. Instead of writing our code like: MyService service = new MyService();&lt;br /&gt;
Using Dependency Injection, we would instead write; IService service { get; set; }; as a property on our class or we would use constructor injection and have something like.&lt;/p&gt;
&lt;p&gt;public class HomeController(IService service)&lt;br /&gt;
{&lt;/p&gt;
&lt;p&gt;}&lt;/p&gt;
&lt;p&gt;As you can see, we are now expressing a dependency on a contract (an interface) rather than an implementation and we are now “wired” for a Dependency Injection/IoC framework to resolve these dependencies for us without explicitly identifying them in our code.&lt;/p&gt;
&lt;p&gt;You might say, “that’s all fine and good, but how do I make sure that my application is only dependent on contracts/interfaces?” More importantly, for existing applications that might not have been written this way, how do I find all the application dependencies and extract them into interfaces in order to move to a DI-friendly application architecture.&lt;/p&gt;
&lt;p&gt;This is where being a .NET developer in this day and age makes your life much easier. Thanks to some new features in Visual Studio 2010, you can now answer those questions fairly easily. If you have one of the higher level VS2010 SKUs (Premium and Ultimate), you have the ability to create Application Architecture Layer diagrams. While you may have known that, you may not be aware that you can also validate an application against a layer diagram and have Visual Studio generate the dependencies between your layers so that you can see the dependencies between layers.&lt;/p&gt;
&lt;p&gt;Using this feature, not only can you say, “my application should look like this” by creating an application layer diagram, but with the validation feature, you can ask the question, “does my application look like this?”&lt;/p&gt;
&lt;p&gt;To get started with this feature, let’s take the following ASP.NET MVC project that I’ve setup as an example for this post. (I’ve circled the areas of immediate interest)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/11/MvcAutofacSolution.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/11/MvcAutofacSolution.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can see, I have actually organized my solution folders to mimic my application layering. We have a Repository/Data Access layer, we have a Services layer and we have a Presentation/UI layer. You’ll also notice that we have a Contracts project (or layer) which contains our interfaces.&lt;/p&gt;
&lt;p&gt;So our dependencies go something like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Site (our ASP.NET MVC app) depends on an IUserService.&lt;/li&gt;
&lt;li&gt;Our Services, depend on an IUserRepository and IUser.&lt;/li&gt;
&lt;li&gt;Our Repositories depend on the IUser contract since that is the contract they return from their operations.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are no dependencies between layers. They only depend on interfaces in the Contracts project.&lt;/p&gt;
&lt;p&gt;You may have also noticed that there are four different “repository” projects and three different “services” projects. This is where the plug-n-play concept I discussed above comes in to play. ASP.NET MVC 2 comes with great support for Dependency Injection (which MVC 3 builds upon) which allows you to plug-in your DI/IoC framework of choice for all your DI needs. In my case, I’m using &lt;a href=&quot;https://github.com/autofac/Autofac&quot;&gt;Autofac&lt;/a&gt;. ASP.NET MVC provides an extensibility point that allows you to say, “anytime my application needs something to satisfy a contract/interface, here’s where to find it.” That “where to find it” part is where an DI/IoC framework plugs-in to satisfy the dependencies of your application without having to declare explicit dependencies between your application layers and/or components.&lt;/p&gt;
&lt;p&gt;Frameworks such as &lt;a href=&quot;https://github.com/autofac/Autofac&quot;&gt;Autofac&lt;/a&gt;, &lt;a href=&quot;http://ninject.org/&quot;&gt;Ninject&lt;/a&gt;, &lt;a href=&quot;http://www.castleproject.org/container/&quot;&gt;Castle Windsor&lt;/a&gt;, &lt;a href=&quot;http://structuremap.net/structuremap/index.html&quot;&gt;StructureMap&lt;/a&gt; and &lt;a href=&quot;http://unity.codeplex.com/&quot;&gt;Unity&lt;/a&gt;, all have some concept of a “registry” which is basically an Interface-to-Implementation mapping or dictionary. With our MyService example above, we would be able to register our implementation MyService as the service that satisfies all dependencies on IService. Then, any time the application needs an implementation of IService, it will ask the DI container to provide one from its registry.&lt;/p&gt;
&lt;p&gt;I won’t go into the details of how these dependencies get registered with or resolved by the DI/IoC frameworks. I’ll leave that for you to read about on your own or to explorer by digging through the attached sample code.&lt;/p&gt;
&lt;p&gt;Instead, we’ll jump right into the benefits that using Dependency Injection provide.&lt;/p&gt;
&lt;p&gt;So, in the diagram, we happen to have four different implementations of a DataAccessLayer.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;DatabaseRepository – persists data to a SQL database&lt;/li&gt;
&lt;li&gt;FakeRepository – fakes the peristence to an underlying data store (ideal for UnitTesting )&lt;/li&gt;
&lt;li&gt;MongoDbRepository – persists data to a MongoDb database&lt;/li&gt;
&lt;li&gt;XmlRepository – persists data to an Xml file&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All four Repository projects implement the IUserRepository contract/interface that our Services layer depends on. This allows us to reliably swap out one for another without affecting any code in the services layer at all. So, it would be trivial to add another repository that persisted data to Oracle, SQL Azure, Amazon SimpleDB, Microsoft Access, Excel, a flat-file, what have you – just so long as the repository implements the IUserRepository interface, we’re good.&lt;/p&gt;
&lt;p&gt;Likewise, we have three different implementations of our Services layer.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;CachingService – retrieves data from an IUserRepository and caches the results&lt;/li&gt;
&lt;li&gt;FakeUserService – a services that fakes retrieving data from an IUserRepository (again, ideal for unit testing)&lt;/li&gt;
&lt;li&gt;UserService – same as the caching service (just without caching)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These services all implement the IUserService contract/interface that our presentation layer (UI) depends on.&lt;/p&gt;
&lt;p&gt;Now, on to creating an application architecture and validating these stated dependencies.&lt;/p&gt;
&lt;p&gt;From the Architecture menu in Visual Studio, you select New Diagram.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb64.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb64_thumb.png&quot; alt=&quot;image_thumb[64]&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the dialog box that opens, select Layer Diagram and give it an appropriate name.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb65.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb65_thumb.png&quot; alt=&quot;image_thumb[65]&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You should end up with a blank architecture diagram that looks like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb66_thumb.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb66_thumb_thumb.png&quot; alt=&quot;image_thumb[66]_thumb&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, using either the Toolbox or by right-clicking, we can begin adding layers to your diagram. After adding our application layers, our diagram should look like the following:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb67_thumb.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb67_thumb_thumb.png&quot; alt=&quot;image_thumb[67]_thumb&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, to validate our architecture (and dependencies), we first need to tell Visual Studio, what code/projects are in what layers. We start by dragging our projects (or solution folders) into the associated application layer. For example, in my sample solution, I would drag the entire DataAccessLayer solution folder into the Data Access layer on the diagram:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb68_thumb.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb68_thumb_thumb.png&quot; alt=&quot;image_thumb[68]_thumb&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here’s what we should end up with when we’re done:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb69_thumb.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb69_thumb_thumb.png&quot; alt=&quot;image_thumb[69]_thumb&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It looks very similar to when we started, but now we have a small indicator in the upper-right-hand corner which tells us how many projects are associated with each layer.&lt;/p&gt;
&lt;p&gt;Now for the magic!&lt;/p&gt;
&lt;p&gt;Simply, right-click anywhere in the white space on the application layer diagram and click &lt;strong&gt;Generate Dependencies&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;If what I told you above about how my application is architected is true, then you should get an updated diagram that looks like the following:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb70_thumb.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/11/image_thumb70_thumb_thumb.png&quot; alt=&quot;image_thumb[70]_thumb&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Ah, now isn’t that diagram a breath of fresh air? In this diagram, Visual Studio is telling us there there are absolutely NO dependencies between the layers of our application! Rather, all application layers depend only on the Contracts project which is simply a collection of interfaces. This is the epitome of encapsulation and tells us that our application layers are decoupled from one another and can be swapped out for other implementations without risk to the rest of our application.&lt;/p&gt;
&lt;p&gt;This is ideal for &lt;a href=&quot;http://en.wikipedia.org/wiki/Test-driven_development&quot;&gt;TDD&lt;/a&gt; scenarios and allows for simultaneous development on different application layers if we have already ironed out our contracts/interfaces. This means more parallel development can occur which can potentially reduce project timelines. And of course, with TDD on our side, we can reliably test individual layers and sign-off on them knowing that they are not dependent or affected by other layers/components whatsoever. End-result: higher-quality software developed in a shorter amount of time.&lt;/p&gt;
&lt;p&gt;Now, if your application doesn’t look like this and looks more like the second picture with dependencies between every layer, don’t worry! Visual Studio can also help you find those dependencies so that you can factor out the concrete references into interfaces/contracts.&lt;/p&gt;
&lt;p&gt;First, start by removing the dependencies from your diagram that you don’t want to have in your app – do this by rick-clicking on the dependency arrow and selecting &lt;strong&gt;Delete&lt;/strong&gt;. Next, after you have removed all the unwanted dependencies, simply right-click anywhere in the whitespace of the diagram and select &lt;strong&gt;Validate Architecture&lt;/strong&gt;. Visual Studio will proceed to build your projects and determine if your application actually validates against your stated (desired) architecture. If it does not, the violations will show up in the Error list window and you can start going through these dependencies and replacing the concrete implementations with contracts/interfaces. Additionally, application architects can use this functionality in conjunction with TFS to prevent code check-ins that violate an application architecture diagram.&lt;/p&gt;
&lt;p&gt;With Visual Studio 2010, ASP.NET MVC 2 &amp;amp; 3 and the rich support for Dependency Injection, you can begin extracting interfaces from your concrete classes to remove the hard-dependencies in your apps, increase the maintainability of your apps. These features aren’t limited to MVC either. Many DI/IoC frameworks also work with ASP.NET WebForms as well as Windows Forms, WPF, and Silverlight. With these tools in your toolbox you too can begin enjoying the bliss that is a truly decoupled application that is easy to maintain, easy to test, easy to change and easy to replace when the next technology comes along!&lt;/p&gt;
&lt;p&gt;Download the sample code: &lt;a href=&quot;http://ander.ly/1hBds&quot;&gt;MvcDI.zip&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For more reading on ASP.NET MVC and Dependency Injection I suggest you check out the following blogs:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://weblogs.asp.net/scottgu/&quot;&gt;http://weblogs.asp.net/scottgu/&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://hanselman.com&quot;&gt;http://hanselman.com&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://haacked.com&quot;&gt;http://haacked.com&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://bradwilson.typepad.com/&quot;&gt;http://bradwilson.typepad.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Happy Injecting!&lt;/p&gt;
</content:encoded><category>.NET</category><category>ASP.NET MVC</category><category>Dependency Injection</category></item><item><title>Recreating the MobileMe Gallery in Silverlight – Part 1 *Updated*</title><link>https://anderly.com/2010/07/01/recreating-the-mobileme-gallery-in-silverlight-part-1-updated/</link><guid isPermaLink="true">https://anderly.com/2010/07/01/recreating-the-mobileme-gallery-in-silverlight-part-1-updated/</guid><description>Originally, in Part 1 of my soon-to-be multi-part series on recreating the MobileMe Gallery in Silverlight I used a separate WCF project (under .NET 3.5) to create my Gallery Service to serve as a proxy between my Silverlight client and the Apple MobileMe service that provides MobileMe Gallery data in JSON format. Since then, I…</description><pubDate>Thu, 01 Jul 2010 15:49:12 GMT</pubDate><content:encoded>&lt;p&gt;Originally, in &lt;a href=&quot;https://anderly.com/2009/10/21/recreating-the-mobileme-gallery-in-silverlight-3-part-1/&quot;&gt;Part 1&lt;/a&gt; of my soon-to-be multi-part series on recreating the MobileMe Gallery in Silverlight I used a separate WCF project (under .NET 3.5) to create my Gallery Service to serve as a proxy between my Silverlight client and the Apple MobileMe service that provides MobileMe Gallery data in JSON format.&lt;/p&gt;
&lt;p&gt;Since then, I have upgraded the project to Silverlight 4 and .NET 4 and have decided to move the service code into the Web project that hosts the Silverlight application. More importantly, I have changed the service to use the new config-free RESTful model available in WCF 4.&lt;/p&gt;
&lt;p&gt;You can download the latest source from CodePlex here: &lt;a href=&quot;http://silverlightmobileme.codeplex.com/SourceControl/list/changesets&quot;&gt;http://silverlightmobileme.codeplex.com/SourceControl/list/changesets&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, our web project looks like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/07/Part1.png&quot;&gt;&lt;/a&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/07/Part1.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/07/Part1.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now, our service code is as simple as one file – GalleryService.cs which is as follows:&lt;br /&gt;
(Notice no .svc file needed anymore thanks to the WebServiceHostFactory in WCF 4)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;using System;
using System.Configuration;
using System.IO;
using System.Net;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;

namespace Gallery.Web.Services
{
	[ServiceContract(Namespace = &quot;urn:silverlightmobileme.codeplex.com&quot;)]
	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
	[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
	public class GalleryService
	{
		string galleryUrlFormat = ConfigurationManager.AppSettings[&quot;GalleryUrlFormat&quot;];
		string albumUrlFormat = ConfigurationManager.AppSettings[&quot;AlbumUrlFormat&quot;];

		[WebGet(UriTemplate = &quot;/{username}&quot;,
				ResponseFormat = WebMessageFormat.Json,
				BodyStyle = WebMessageBodyStyle.Bare)]
		[OperationContract]
		public Stream GetGallery(string username)
		{
			// TODO: add exception-handling using WebFaultExceptions and HttpStatusCode enumeration
			var webClient = new WebClient();
			string photocastUrl = string.Format(galleryUrlFormat, username);
			return webClient.OpenRead(photocastUrl);
		}

		[WebGet(UriTemplate = &quot;/{username}/{id}&quot;,
				ResponseFormat = WebMessageFormat.Json,
				BodyStyle = WebMessageBodyStyle.Bare)]
		[OperationContract]
		public Stream GetAlbum(string username, string id)
		{
			var webClient = new WebClient();
			string albumUrl = string.Format(albumUrlFormat, username, id);
			return webClient.OpenRead(albumUrl);
		}

	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The magic of WCF 4 config-free RESTful services is handled in Global.asax.cs&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;using System.Web;
using System.ServiceModel.Activation;
using System.Web.Routing;
using Gallery.Web.Services;

namespace Gallery.Web
{
	public class Global : HttpApplication
	{
		public static void RegisterRoutes(RouteCollection routes)
		{
			//routes.Add(&quot;GalleryService&quot;, new Route(
			//    &quot;GalleryService&quot;,
			//    new CustomRouteHandler(&quot;~/Services/GalleryService.svc&quot;)
			//));
			routes.Add(&quot;Default&quot;, new Route(
				&quot;{username}&quot;,
				new CustomRouteHandler(&quot;~/Default.aspx&quot;)
			));
			RouteTable.Routes.Add(new ServiceRoute(&quot;GalleryService&quot;, new WebServiceHostFactory(), typeof(GalleryService)));
			RouteTable.Routes.Add(new ServiceRoute(&quot;ConfigService&quot;, new WebServiceHostFactory(), typeof(ConfigService)));
		}

		protected void Application_Start()
		{
			RegisterRoutes(RouteTable.Routes);
		}
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here, after registering our main route for the gallery, we simply add two more routes (of type &lt;strong&gt;ServiceRoute&lt;/strong&gt;), passing it the path we want to map to our services, then the ServiceHostFactory (which handles the config-free RESTful WCF), followed by the type of the service.&lt;/p&gt;
&lt;p&gt;That’s it!&lt;/p&gt;
&lt;p&gt;Now our service has nice RESTful service endpoints and there is no special WCF configuration needed and it just works.&lt;/p&gt;
&lt;p&gt;Try out the new config-free RESTful service here: &lt;a href=&quot;http://gallery.restazured.com/GalleryService/help&quot;&gt;http://gallery.restazured.com/GalleryService/emily_parker&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With WCF 4 config-free RESTful services, we also get handy helper pages for our service consumers to help them understand how to call our services and what type of response to expect.&lt;/p&gt;
&lt;p&gt;Try it out here:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://gallery.restazured.com/GalleryService/help&quot;&gt;http://gallery.restazured.com/GalleryService/help&lt;br /&gt;
&lt;/a&gt;&lt;a href=&quot;http://gallery.restazured.com/ConfigService/help&quot;&gt;http://gallery.restazured.com/ConfigService/help&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you’ll see, this displays what operations are available and even provides sample responses. Now that’s RESTful!&lt;/p&gt;
&lt;p&gt;Stay tuned for Part 2 where we’ll cover the details of the Silverlight project (now Silverlight 4) where we’ll be using &lt;a href=&quot;http://mef.codeplex.com/&quot;&gt;MEF&lt;/a&gt;, &lt;a href=&quot;http://en.wikipedia.org/wiki/Model_View_ViewModel&quot;&gt;MVVM&lt;/a&gt; and our config-free RESTful WCF services.&lt;/p&gt;
</content:encoded><category>.NET</category><category>REST</category><category>Silverlight</category></item><item><title>Create your own branded url-shortener in under 10 minutes using ASP.NET MVC 2</title><link>https://anderly.com/2010/06/10/create-your-own-branded-url-shortener-in-under-10-minutes-using-asp-net-mv2/</link><guid isPermaLink="true">https://anderly.com/2010/06/10/create-your-own-branded-url-shortener-in-under-10-minutes-using-asp-net-mv2/</guid><description>These days, URL shortener services like bit.ly are a dime a dozen. However, the latest craze are branded, shortened URLs like amzn.to or nyti.ms. You’ve probably seen URLs like these floating around Twitter, Facebook, etc. Why not have your very own in under 10 minutes?</description><pubDate>Thu, 10 Jun 2010 07:41:13 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; bit.ly now allows custom domains without having to pay. Additionally, there are services like &lt;a href=&quot;http://droplr.com/&quot;&gt;Droplr&lt;/a&gt;, &lt;a href=&quot;http://getcloudapp.com&quot;&gt;CloudApp&lt;/a&gt; and &lt;a href=&quot;https://jumpshare.com/&quot;&gt;JumpShare&lt;/a&gt;. Currently, I use Droplr for my personal short links and file sharing. and we use CloudApp for &lt;a href=&quot;http://ssms.us&quot;&gt;my company&lt;/a&gt; short links and file sharing. This article mainly discusses how you could have achieved this in the past before bit.ly made branded short domains available and before these other services existed.&lt;/p&gt;
&lt;h4&gt;Overview&lt;/h4&gt;
&lt;p&gt;These days, URL shortener services like &lt;a href=&quot;http://bit.ly&quot;&gt;bit.ly&lt;/a&gt; are a dime a dozen. However, the latest craze are branded, shortened URLs like &lt;a href=&quot;http://amzn.to&quot;&gt;amzn.to&lt;/a&gt; instead of &lt;a href=&quot;http://amazon.com&quot;&gt;amazon.com&lt;/a&gt;, &lt;a href=&quot;http://nyti.ms&quot;&gt;nyti.ms&lt;/a&gt; instead of &lt;a href=&quot;http://nytimes.com&quot;&gt;nytimes.com&lt;/a&gt;, &lt;a href=&quot;http://tcrn.ch&quot;&gt;tcrn.ch&lt;/a&gt; instead of &lt;a href=&quot;http://techcrunch.com&quot;&gt;techcrunch.com&lt;/a&gt;, &lt;a href=&quot;http://huff.to&quot;&gt;huff.to&lt;/a&gt; instead of &lt;a href=&quot;http://huffingtonpost.com&quot;&gt;huffingtonpost.com&lt;/a&gt;. You’ve probably seen URLs like these floating around Twitter, Facebook, IM and even email. These abbreviated domains offer the same benefits of a short URL provided by a service like bit.ly (ideal for use on Twitter, etc.) without sacrificing the branded experience and marketing that is achieved by using a “full-size” URL. They are the “compact car” of URLs and they are your friend!&lt;/p&gt;
&lt;p&gt;Hence the reason for new services like &lt;a href=&quot;http://bitly.pro/&quot;&gt;bitly.Pro&lt;/a&gt;. In case your unfamiliar, bitly.Pro is a new service offered by &lt;a href=&quot;http://bit.ly&quot;&gt;bit.ly&lt;/a&gt; that allows companies and individuals to brand their shortened URLs using their own abbreviated domains. &lt;strong&gt;Amazon.com&lt;/strong&gt; already uses &lt;a href=&quot;http://amzn.to&quot;&gt;http://amzn.to&lt;/a&gt;. &lt;strong&gt;The New York Times&lt;/strong&gt; uses &lt;a href=&quot;http://nyti.ms&quot;&gt;http://nyti.ms&lt;/a&gt;. Many other companies are using bitly.Pro as well. You may already have your very own abbreviated domain that you’d like to use to brand your shortened urls. If not, &lt;a href=&quot;http://godaddy.com&quot;&gt;go get one&lt;/a&gt;. So, like me, you figure you’ll head on over to &lt;a href=&quot;http://bitly.pro/signup&quot;&gt;http://bitly.pro/signup&lt;/a&gt; to sign up for the free beta only to find out that the beta is closed to new users at this time. (&lt;strong&gt;Update:&lt;/strong&gt; bitly.Pro beta has re-opened and you can signup here: &lt;a href=&quot;http://bit.ly/a/pro_request&quot;&gt;http://bit.ly/a/pro_request&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;But wait…before you begin cursing bit.ly about their closed beta, allow me to present a quick solution that still allows you to brand your shortened links and track traffic to your branded service. It won’t give you the analytics regarding how your content is begin distributed across Twitter, Facebook, etc. (although you could build that in fairly easily), but for someone who just wants a simple branded url shortener solution, it will fit the bill.&lt;/p&gt;
&lt;p&gt;So, without further ado, here’s the simple ASP.NET MVC-based solution that provides a simple bitly.Pro-like solution of your very own. Best of all, you can get it going in under 10 minutes. Of course, you could build the same solution entirely with javascript and an html page, but where’s the fun in that?&lt;/p&gt;
&lt;h4&gt;Getting Started&lt;/h4&gt;
&lt;p&gt;The easiest way to get started is to head over to &lt;a href=&quot;http://www.asp.net/&quot;&gt;http://www.asp.net/&lt;/a&gt; and use the Web Platform Installer to install Visual Web Developer 2010 and ASP.NET MVC 2.&lt;/p&gt;
&lt;p&gt;Once you’ve got these installed, fire up VS2010 and add a new “ASP.NET MVC2 Empty Web Application.”&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/06/Step1.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/06/Step1.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You should end up with something that looks like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/06/Step1-2.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/06/Step1-2.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;The Controller&lt;/h4&gt;
&lt;p&gt;The first thing we want to do is setup a controller to handle our requests, so right-click the Controllers directory in the Solution Explorer and select Add &amp;gt; Controller.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/06/Step2.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/06/Step2.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We’ll name ours “HomeController” and, since we won’t be doing anything with an actual model, we’ll leave the box unchecked that prompts us to create actions methods for Create, Update and Delete scenarios.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2010/06/Step2-2.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2010/06/Step2-2.png&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Our HomeController is going to be very simple and will look like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;using System.Web.Mvc;

namespace bitlyProSimple.Controllers
{
	[HandleError]
	public class HomeController : Controller
	{
		public ActionResult Index(string linkid)
		{
			Response.StatusCode = 302;
			Response.RedirectLocation = (string.IsNullOrWhiteSpace(linkid)
								 ? &quot;http://anderly.com&quot;
								 : string.Format(&quot;http://bit.ly/{0}&quot;, linkid));
			return new ContentResult();
		}

	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Our controller is going to accept a string (the linkid) and then contstruct a 302 redirect to bit.ly to finish the job. This allows us to simply use the bit.ly analytics when you have a bit.ly account.&lt;/p&gt;
&lt;p&gt;As you can see, we are using bit.ly, but you could very well use any other URL shortener service. Essentially, what we’ll be doing is mapping requests that match the format &lt;code&gt;http://[yourdomain]/[linkid]&lt;/code&gt; to our HomeController which will accept the linkid as a parameter and then prepare to forward our request to bit.ly. So in my case, my abbreviated domain is http://ander.ly. So, I’ll be mapping any requests that match the &lt;code&gt;http://ander.ly/[linkid]&lt;/code&gt; format to be forwarded to &lt;code&gt;http://bit.ly/[linkid]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In case there isn’t a link id, we will simply redirect to the blog home page.&lt;/p&gt;
&lt;h4&gt;&lt;strong&gt;Wrapping Up&lt;/strong&gt;&lt;/h4&gt;
&lt;p&gt;Last but not least, we need to head on over to Global.asax.cs to setup our Routes and we’ll be done.&lt;/p&gt;
&lt;p&gt;Open up Global.asax.cs and replace the default route of:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{controller}/{action}/{id}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;with&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{linkid}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That’s it!&lt;/p&gt;
&lt;p&gt;Fire up the solution and test it out for yourself. Don’t forget to bookmark the location of this post: &lt;a href=&quot;http://ander.ly/13UVK&quot;&gt;http://ander.ly/13UVK&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now any requests that come in that match the format &lt;code&gt;http://ander.ly/[linkid]&lt;/code&gt; will be sent to our HomeController which will extract the linkid and construct a new bit.ly URL of the same format and do a simple redirect for the user.&lt;/p&gt;
&lt;p&gt;With this solution, we can simply use the existing bit.ly URL shortener service without having to roll our own and we can simply replace bit.ly in any shortened URLs with our very own branded abbreviated domain.&lt;/p&gt;
&lt;p&gt;Now you too can start branding the links you share.&lt;/p&gt;
&lt;p&gt;Let the shameless self-promotion begin!&lt;/p&gt;
&lt;h4&gt;Source Code&lt;/h4&gt;
&lt;p&gt;&lt;a href=&quot;http://ander.ly/16pfL&quot;&gt;bitlyProSimple.zip&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>.NET</category><category>ASP.NET MVC</category><category>REST</category></item><item><title>Silverlight MobileMe Gallery now on CodePlex!</title><link>https://anderly.com/2009/11/24/silverlight-mobileme-gallery-now-on-codeplex/</link><guid isPermaLink="true">https://anderly.com/2009/11/24/silverlight-mobileme-gallery-now-on-codeplex/</guid><description>I have published the initial source for my project “Recreating the MobileMe Gallery in Silverlight 3” on CodePlex. You can now access the Alpha release of the code here: http://silverlightmobileme.codeplex.com/ I will be updating I have updated the working example (http://gallery.restazured.com/emily_parker) as well to reflect the latest version on CodePlex. Please leave your comments and…</description><pubDate>Tue, 24 Nov 2009 23:49:44 GMT</pubDate><content:encoded>&lt;p&gt;I have published the initial source for my project “&lt;a href=&quot;https://anderly.com/2009/07/23/recreating-the-mobileme-gallery-in-silverlight-3/&quot;&gt;Recreating the MobileMe Gallery in Silverlight 3&lt;/a&gt;” on &lt;a href=&quot;http://silverlightmobileme.codeplex.com/&quot;&gt;CodePlex&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can now access the Alpha release of the code here: &lt;a href=&quot;http://silverlightmobileme.codeplex.com/&quot;&gt;http://silverlightmobileme.codeplex.com/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I will be updating I have updated the working example (&lt;a href=&quot;http://gallery.restazured.com/emily_parker&quot;&gt;http://gallery.restazured.com/emily_parker&lt;/a&gt;) as well to reflect the latest version on CodePlex.&lt;/p&gt;
&lt;p&gt;Please leave your comments and let me know if you have any questions…or if you would like to be a contributor to the project.&lt;/p&gt;
&lt;p&gt;Enjoy!&lt;/p&gt;
</content:encoded><category>.NET</category><category>Silverlight</category></item><item><title>Recreating the MobileMe Gallery in Silverlight 3 – Part 1</title><link>https://anderly.com/2009/10/21/recreating-the-mobileme-gallery-in-silverlight-3-part-1/</link><guid isPermaLink="true">https://anderly.com/2009/10/21/recreating-the-mobileme-gallery-in-silverlight-3-part-1/</guid><description>In my introductory post I detailed the features needed to successfully recreate the MobileMe Gallery in Silverlight 3. While a bit late, this is Part 1 of a multi-part series where I will detail out step-by-step the process of Recreating the MobileMe Gallery in Silverlight 3. The Tools I will assume you already know what…</description><pubDate>Wed, 21 Oct 2009 07:15:53 GMT</pubDate><content:encoded>&lt;p&gt;In my &lt;a href=&quot;https://anderly.com/2009/07/23/recreating-the-mobileme-gallery-in-silverlight-3/&quot;&gt;introductory post&lt;/a&gt; I detailed the features needed to successfully recreate the MobileMe Gallery in Silverlight 3. While a bit late, this is Part 1 of a multi-part series where I will detail out step-by-step the process of Recreating the MobileMe Gallery in Silverlight 3.&lt;/p&gt;
&lt;h2&gt;The Tools&lt;/h2&gt;
&lt;p&gt;I will assume you already know what tools are required to do Silverlight development. If not, go here: &lt;a href=&quot;http://timheuer.com/blog/articles/silverlight-get-started-part-1-hello-world.aspx&quot;&gt;http://timheuer.com/blog/articles/silverlight-get-started-part-1-hello-world.aspx&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For this post, you will also need a tool such as &lt;a href=&quot;http://www.fiddler2.com/fiddler2/&quot;&gt;Fiddler&lt;/a&gt; or &lt;a href=&quot;http://projects.nikhilk.net/WebDevHelper&quot;&gt;Web Development Helper&lt;/a&gt; in order to do some HTTP tracing.&lt;/p&gt;
&lt;h2&gt;Getting Started&lt;/h2&gt;
&lt;p&gt;For this post we are going to focus on the initial plumbing required to retrieve the data from the MobileMe Gallery. The first thing we’ll need is the underlying data (album definitions, etc.) stored on the MobileMe site so that we can populate our Silverlight Gallery. To do so, we’ll need to see what the Apple MobileMe Gallery does under the covers.&lt;/p&gt;
&lt;p&gt;So, if you head over to the &lt;a href=&quot;http://gallery.me.com/emily_parker&quot;&gt;MobileMe Sample Gallery&lt;/a&gt; you should see the following:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2009/10/SampleMobileMeGallery.PNG&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2009/10/SampleMobileMeGallery-300x228.PNG&quot; alt=&quot;Click Here for a Larger View&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Click Here for a Larger View&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In order to find out if the underlying album data is accessible, I’m going to use the Web Development Helper IE Add-In to do some HTTP Tracing on the Apple MobileMe Gallery. After firing up Web Development Helper and turning on HTTP logging (HTTP &amp;gt; Enable HTTP Logging), I can then refresh the browser and should see a long list of HTTP requests in the console like so:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2009/10/WebDevHelper.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2009/10/WebDevHelper-300x228.png&quot; alt=&quot;Web Dev Helper&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Click Here for a Larger View&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;If you scroll up in the list, you should find the entry highlighted above. This is the main request we are concerned with. Double-clicking on this request and then selecting the “Reponse Content” tab at the bottom provides more details.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2009/10/HttpLogViewer.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2009/10/HttpLogViewer-300x258.png&quot; alt=&quot;Http Log Viewer&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Click Here for a Larger View&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;There you have it! A good ‘ol fashion HTTP GET request returning JSON. A quick glance over this data shows you that this JSON response contains the gallery details we’re after. So far, so good.&lt;/p&gt;
&lt;h2&gt;Getting the Data&lt;/h2&gt;
&lt;p&gt;Now we know where to get the data, but how do we get it? You may say just use the WebClient class in Silverlight to do an HTTP GET request. However, Silverlight requires &lt;a href=&quot;http://timheuer.com/blog/archive/0001/01/01/silverlight-cross-domain-policy-file-snippet-intellisense.aspx&quot;&gt;client access policy files&lt;/a&gt; for cross-domain HTTP requests in order to provide a security mechanism to service authors to specify who can and cannot access their services. There are some public web services that already have these files in place for Flash, but Silverlight requires its own flavor. Additionally, the Apple MobileMe Gallery doesn’t have one. Therefore, we need our own service (WCF service that-is) that will serve as a proxy between the Apple MobileMe Gallery service and our Silverlight MobileMe Gallery client. In short, we’ll call our WCF service (that we’ll author) and our service will call the Apple MobileMe Gallery service. This is a common workaround as the Silverlight client performs the check for the client access policy file while WCF doesn’t do any checks because it’s a server technology.&lt;/p&gt;
&lt;h2&gt;Writing our Service&lt;/h2&gt;
&lt;p&gt;We’ll start off by creating an empty Visual Studio Solution called &lt;strong&gt;Gallery&lt;/strong&gt;. Then, we’ll add a new “WCF Service Application” project to the solution – giving it the name &lt;strong&gt;Gallery.Service&lt;/strong&gt;. Here is the structure of the service project after being built out.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2009/10/ServiceProjectStructure.png&quot; alt=&quot;Service Project Structure&quot; title=&quot;Service Project Structure&quot; /&gt;&lt;/p&gt;
&lt;p&gt;IGallery.cs is our service contract that will define the signatures for the methods we’ll need to call to retrieve gallery and album details. It looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2009/10/IGallery.png&quot; alt=&quot;IGallery&quot; title=&quot;IGallery&quot; /&gt;&lt;/p&gt;
&lt;p&gt;IPolicyProvider.cs is our policy provider contract that will define the signature for the method that will return the Silverlight client access policy file. It looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2009/10/IPolicyProvider.png&quot; alt=&quot;IPolicyProvider&quot; title=&quot;IPolicyProvider&quot; /&gt;&lt;/p&gt;
&lt;p&gt;As you’ll notice, both of these interfaces are using the &lt;strong&gt;WebGet&lt;/strong&gt; attribute to map specific UriTemplates to these service methods. For instance, in IPolicyProvider, we are saying if an HTTP GET request comes in to our root service folder followed by “/clientaccesspolicy.xml,” then that means run this method. We do this because anytime a Silverlight client makes any cross-domain request, it first makes a request to “clientaccesspolicy.xml” to see if it has rights to access the service.&lt;/p&gt;
&lt;p&gt;Finally, our implementation of Gallery.svc.cs looks like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2009/10/Gallery.svc.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2009/10/Gallery.svc-300x233.png&quot; alt=&quot;Gallery.svc&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Click Here for a Larger View&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Here, you’ll notice that our GetGallery and GetAlbum methods are simply using WebClient to call the gallery service and album service using url formats defined in Web.config. These are:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://anderly.com/wp-content/uploads/2009/10/WebConfigSettings.png&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2009/10/WebConfigSettings-300x10.png&quot; alt=&quot;WebConfigSettings&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Click Here for a Larger View&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You’ll notice that the first entry (PhotocastUrlFormat) is the same format as the HTTP request we observed using Web Development Helper. And we simply, leave a curly-brace placeholder for the MobileMe username which we’ll substitute at run-time.&lt;/p&gt;
&lt;p&gt;Minus WCF configuration settings which are included in the source, we now have a working service which will forward calls to the Apple MobileMe service to retrieve gallery and album details. This service is currently available at &lt;a href=&quot;http://igallery.restazured.com/GalleryService.svc&quot;&gt;http://igallery.restazured.com/GalleryService.svc&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Feel free to wire up your WCF client of choice (Silverlight, WPF, etc.) add a service reference and try calling one of the methods passing your own MobileMe username or the sample “emily_parker”. You can even see the client policy provider in action here: &lt;a href=&quot;http://igallery.restazured.com/clientaccesspolicy.xml&quot;&gt;http://igallery.restazured.com/clientaccesspolicy.xml&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;Now, we have a WCF service setup to forward our requests for MobileMe Gallery and Album details to the Apple MobileMe Service. In Part 2, we’ll start creating the Silverlight project to call our WCF service and start building the home page to look like: &lt;a href=&quot;http://gallery.me.com/emily_parker&quot;&gt;http://gallery.me.com/emily_parker&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the meantime, checkout the working example (using Silverlight 3) here: &lt;a href=&quot;http://gallery.restazured.com/emily_parker&quot;&gt;http://gallery.restazured.com/emily_parker&lt;/a&gt;&lt;/p&gt;
</content:encoded><category>Silverlight</category></item><item><title>Silverlight Midpoint Rounding Solution</title><link>https://anderly.com/2009/08/08/silverlight-midpoint-rounding-solution/</link><guid isPermaLink="true">https://anderly.com/2009/08/08/silverlight-midpoint-rounding-solution/</guid><description>As a follow up to my previous Shakespearean-titled post on rounding, I decided to provide a quick follow up to provide a solution for midpoint rounding in Silverlight. Based on some traffic that I’ve been getting it looks like people are searching for a rounding solution in Silverlight since the Silverlight core framework lacks the…</description><pubDate>Sat, 08 Aug 2009 07:20:40 GMT</pubDate><content:encoded>&lt;p&gt;As a follow up to my previous Shakespearean-titled post on rounding, I decided to provide a quick follow up to provide a solution for midpoint rounding in Silverlight. Based on some traffic that I’ve been getting it looks like people are searching for a rounding solution in Silverlight since the Silverlight core framework lacks the traditional Math.Round() overloads we get with the full .NET framework that allow specifying the desired midpoint rounding behavior.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Remember, Silverlight contains a pared-down version of the .NET framework.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So, here is a simple solution to take what we learned in the previous post and develop our own MathExt helper class that provides static Round methods similar to the Math.Round() methods that allow us to specify the desired midpoint rounding behavior. Using this you can now control midpoint rounding behavior in Silverlight.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public enum MidpointRounding
{
	ToEven,
	AwayFromZero
}

public static class MathExt
{
	public static decimal Round(decimal d, MidpointRounding mode)
	{
		return MathExt.Round(d, 0, mode);
	}

	/// &amp;lt;summary&amp;gt;
	/// Rounds using arithmetic (5 rounds up) symmetrical (up is away from zero) rounding
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&quot;d&quot;&amp;gt;A Decimal number to be rounded.&amp;lt;/param&amp;gt;
	/// &amp;lt;param name=&quot;decimals&quot;&amp;gt;The number of significant fractional digits (precision) in the return value.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;The number nearest d with precision equal to decimals. If d is halfway between two numbers, then the nearest whole number away from zero is returned.&amp;lt;/returns&amp;gt;
	public static decimal Round(decimal d, int decimals, MidpointRounding mode)
	{
		if (mode == MidpointRounding.ToEven)
		{
			return decimal.Round(d, decimals);
		}
		else
		{
			decimal factor = Convert.ToDecimal(Math.Pow(10, decimals));
			int sign = Math.Sign(d);
			return Decimal.Truncate(d * factor + 0.5m * sign) / factor;
		}
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or if you prefer an extension-method approach:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public enum MidpointRounding
{
	ToEven,
	AwayFromZero
}

public static class DecimalExtensions
{
	public static decimal Round(this decimal d, MidpointRounding mode)
	{
		return d.Round(0, mode);
	}

	/// &amp;lt;summary&amp;gt;
	/// Rounds using arithmetic (5 rounds up) symmetrical (up is away from zero) rounding
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&quot;d&quot;&amp;gt;A Decimal number to be rounded.&amp;lt;/param&amp;gt;
	/// &amp;lt;param name=&quot;decimals&quot;&amp;gt;The number of significant fractional digits (precision) in the return value.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;The number nearest d with precision equal to decimals. If d is halfway between two numbers, then the nearest whole number away from zero is returned.&amp;lt;/returns&amp;gt;
	public static decimal Round(this decimal d, int decimals, MidpointRounding mode)
	{
		if (mode == MidpointRounding.ToEven)
		{
			return decimal.Round(d, decimals);
		}
		else
		{
			decimal factor = Convert.ToDecimal(Math.Pow(10, decimals));
			int sign = Math.Sign(d);
			return Decimal.Truncate(d * factor + 0.5m * sign) / factor;
		}
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Remember, the non-extension-method version could easily be used in any legacy .NET projects that still may be on 1.0 or 1.1 to give us the ability to control midpoint rounding behavior which didn’t arrive in the framework until .NET 2.0.&lt;/p&gt;
&lt;p&gt;Once again, Happy Rounding!&lt;/p&gt;
</content:encoded><category>.NET</category><category>Silverlight</category></item><item><title>To round ‘up’, or to round ‘down’: that is the question</title><link>https://anderly.com/2009/07/28/to-round-up-or-to-round-down-that-is-the-question/</link><guid isPermaLink="true">https://anderly.com/2009/07/28/to-round-up-or-to-round-down-that-is-the-question/</guid><description>In troubleshooting a rounding discrepancy a couple of years ago in a software component, I discovered what may be a lesser known fact – the Microsoft programming languages (VBScript, VBA, VB6, VB.NET, C#, etc.) implement what is commonly referred to as “banker’s rounding” or “rounding to the nearest” – which follows the IEEE Standard 754…</description><pubDate>Tue, 28 Jul 2009 18:16:23 GMT</pubDate><content:encoded>&lt;p&gt;In troubleshooting a rounding discrepancy a couple of years ago in a software component, I discovered what may be a lesser known fact – the Microsoft programming languages (VBScript, VBA, VB6, VB.NET, C#, etc.) implement what is commonly referred to as “banker’s rounding” or “rounding to the nearest” – which follows the IEEE Standard 754, section 4. My reason for posting about this is that, in some cases, this can yield unexpected results.&lt;/p&gt;
&lt;p&gt;As we all know traditional arithmetic rounding (the kind we all learned in grade school) says .5 always rounds up. However, the IEEE Standard 754, section 4 does not implement this form of symmetrical arithmetic rounding.&lt;/p&gt;
&lt;p&gt;Here’s the explanation:&lt;/p&gt;
&lt;p&gt;Given the range 0 – 1&lt;/p&gt;
&lt;p&gt;[.1 .2 .3 .4] – always rounds down&lt;/p&gt;
&lt;p&gt;[.6 .7 .8 .9] – always rounds up&lt;/p&gt;
&lt;p&gt;However, .5 is the midpoint between 0 and 1 and always rounding .5 in the same direction results in a bias that grows with the more numbers you add together.&lt;/p&gt;
&lt;p&gt;So, the IEEE Standard says that one way to minimize the bias is with “banker’s rounding” which is as follows:&lt;/p&gt;
&lt;p&gt;Banker’s rounding rounds .5 up sometimes…and down sometimes. I know it sounds inconsistent, but the convention is to round to the nearest even number, so that both 1.5 and 2.5 round to 2, and 3.5 and 4.5 both round to 4. Banker’s rounding is symmetric.&lt;/p&gt;
&lt;p&gt;Here are a few sample results using the IEEE Standard (banker’s rounding):&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Rounded to 2 Decimal Places&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0.1250&lt;/td&gt;
&lt;td&gt;0.12 (Rounds down when the number to the left of the 5 is even)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.1350&lt;/td&gt;
&lt;td&gt;0.14 (Rounds up when the number to the left of the 5 is odd)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.1251&lt;/td&gt;
&lt;td&gt;0.13 (Rounds up because the 1 to the right of the 5 since it is not exactly the midpoint between .12 and .13)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.125000001&lt;/td&gt;
&lt;td&gt;0.13 (Rounds up for the same reason as the one above)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;You may already be aware of this seemingly odd behavior, but many of you may be surprised by this result (as I was).&lt;/p&gt;
&lt;p&gt;In any case, I wanted to share my findings in case you were expecting a rounding implementation different than that which is actually implemented in the products/programming languages you are using.&lt;/p&gt;
&lt;p&gt;Microsoft acknowledges that their rounding implementation is inconsistent across products (VBScript, VBA, VB6, .NET, SQL Server, EXCEL) and says that this is only done for historical reasons. Here is the link to the Microsoft KB article that details the different rounding implementations in their products and how to implement a custom rounding method based on your need: &lt;a href=&quot;http://support.microsoft.com/?kbid=196652&quot;&gt;http://support.microsoft.com/?kbid=196652&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here’s the breakdown of the rounding implementations for Microsoft Products:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Product&lt;/th&gt;
&lt;th&gt;Implementation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;VBScript, VBA, VB 6.0&lt;/td&gt;
&lt;td&gt;Banker’s Rounding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Excel Worksheet&lt;/td&gt;
&lt;td&gt;Symmetric Arithmetic Rounding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SQL Server&lt;/td&gt;
&lt;td&gt;Either Symmetric Arithmetic Rounding or Symmetric Round Down (Fix) depending on arguments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET 1.0, 1.1&lt;/td&gt;
&lt;td&gt;Banker’s Rounding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET 2.0 (or greater)&lt;/td&gt;
&lt;td&gt;Banker’s Rounding but provides additional overloads to the Math.Round() method for specifying desired midpoint rounding behavior.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;So, the good news is that if you are using SQL Server or Excel rounding, you are fine – you’re gonna get good ‘ol traditional arithmetic rounding (.5 always rounds up).&lt;/p&gt;
&lt;p&gt;Also of interest, is that the Java Math library (including JavaScript) implements &lt;strong&gt;Asymmetric Arithmetic Rounding&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The key difference between this and &lt;strong&gt;Symmetric Arithmetic Rounding&lt;/strong&gt; (the kind we learned in grade school) is as follows:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Symmetric Arithmetic Rounding&lt;/strong&gt; always rounds up, where “up” is defined as “away from zero.”&lt;/p&gt;
&lt;p&gt;So, 0.1250 rounds to 0.13 and -0.1250 rounds to -0.13.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Asymmetric Arithmetic Rounding&lt;/strong&gt; always rounds up, where “up” is defined as “heading towards positive infinity.”&lt;/p&gt;
&lt;p&gt;So, 0.1250 rounds to 0.13 and -0.1250 rounds to -0.12 (i.e. in a positive direction).&lt;/p&gt;
&lt;p&gt;As for my case, I wanted Symmetric Arithmetic Rounding and followed the instructions in the KB article above for implementing my own custom Round method to achieve this result.&lt;/p&gt;
&lt;p&gt;Here is the final implementation:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
/// Implements alternate rounding methods, in contrast to Decimal.Round()
/// and Math.Round(), which implement banker&apos;s rounding (5 rounds to even).
/// See http://support.microsoft.com/?kbid=196652 for other methods.
/// &amp;lt;/summary&amp;gt;

public static class MathExt

{

	/// &amp;lt;summary&amp;gt;
	/// Rounds using arithmetic (5 rounds up) symmetrical (up is away from zero) rounding
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&quot;d&quot;&amp;gt;d: A System.Decimal number to be rounded.&amp;lt;/param&amp;gt;
	/// &amp;lt;param name=&quot;decimals&quot;&amp;gt;The number of significant fractional digits (precision) in the return value.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;The number nearest d with precision equal to decimals. If d is halfway between two numbers, then the nearest whole number away from zero is returned.&amp;lt;/returns&amp;gt;
	public static decimal Round(decimal d, int decimals)
	{
		decimal factor = Convert.ToDecimal(Math.Pow(10, decimals));
		int sign = Math.Sign(d);
		return Decimal.Truncate(d * factor + 0.5m * sign) / factor;
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I would encourage you to review any rounding code in your apps and verify that the rounding implementation is the one you expected.&lt;/p&gt;
&lt;p&gt;Happy Rounding!&lt;/p&gt;
</content:encoded><category>.NET</category></item><item><title>Recreating the MobileMe Gallery in Silverlight 3</title><link>https://anderly.com/2009/07/23/recreating-the-mobileme-gallery-in-silverlight-3/</link><guid isPermaLink="true">https://anderly.com/2009/07/23/recreating-the-mobileme-gallery-in-silverlight-3/</guid><description>Background: Even though I am an avid fan of many Microsoft products (especially their developer tools), Apple has just done certain things “right” for the home user where it seems Microsoft has struggled or been late to the table. As you may have read on my About Me page, I use Macs at home. They…</description><pubDate>Thu, 23 Jul 2009 06:48:10 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Background:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Even though I am an avid fan of many Microsoft products (especially their developer tools), Apple has just done certain things “right” for the home user where it seems Microsoft has struggled or been late to the table. As you may have read on my &lt;a href=&quot;https://anderly.com/about/&quot;&gt;About Me&lt;/a&gt; page, I use Macs at home. They have their own set of issues, but for most of the “home stuff” I need a computer for (photos, movies, music) they do the job and they do it well.&lt;/p&gt;
&lt;p&gt;One of my favorite tools is iPhoto (Aperture too) and the one-click publishing to &lt;a href=&quot;http://www.apple.com/mobileme/features/gallery.html&quot;&gt;MobileMe Gallery&lt;/a&gt; – Apple’s web-based photo/movie gallery tool that creates good looking, easy-to-use, web-based galleries that I use to share photos and movies with friends and family. Take a look for yourself and visit the &lt;a href=&quot;http://gallery.me.com/emily_parker&quot;&gt;MobileMe sample gallery&lt;/a&gt; for the ficticious user “Emily Parker.”&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://gallery.me.com/emily_parker&quot;&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2009/07/mobileme1.jpg&quot; alt=&quot;Sample MobileMe Gallery&quot; title=&quot;Sample MobileMe Gallery&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So for the most part, the features here meet my needs with one exception – movies require the Apple QuickTime plug-in to view them. Well, you may say, ‘no big deal’ and you’re right…unless you’re one of my many family members who is still on Windows 2000 (or earlier) and can’t install the latest version of QuickTime because it requires Windows XP. So, needless to say, a fair amount of people are unable to view any of the movies that I publish to MobileMe Gallery. So, I end up having to also publish them to YouTube as well (which is a kind of a hassle). Not to mention that they don’t get the same focused user experience of my photos and movies in one nice and neat presentation and not a bunch of other junk detracting from the experience. I know, I know, my family members should upgrade, but the simple fact of the matter is that many of them are happy with their computers and they’re not going to upgrade just so they can view my measly ol’ MobileMe Gallery.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So, now for the solution. I attended a Guerilla.NET event back in March (put on by &lt;a href=&quot;http://www.develop.com&quot;&gt;DevelopMentor&lt;/a&gt;) and while at the class I got up to speed on Silverlight 2 as well what features were coming in Silverlight 3. Voila! Silverlight 3 was going to support additional media formats including MPEG-4, which is the format used by iTunes and MobileMe Gallery. So, you see where I’m going. My solution would be to use the features of Silverlight 3 to create a solution that would allow my family to view the MPEG-4 format movies stored on MobileMe Gallery using the Silverlight 3 plug-in (once it became available). I knew it would be sometime before it came out of beta and I knew it would take me awhile to develop, so I knew I had some time.&lt;/p&gt;
&lt;p&gt;But remember, I didn’t want to sacrifice the clean, simple, focused &lt;a href=&quot;http://en.wikipedia.org/wiki/User_experience_design&quot;&gt;UX&lt;/a&gt; of MobileMe Gallery by simply giving my family a silverlight media player as an alternate location to view movies. Plus, there are already Silverlight media players that would handle the job once Silverlight 3 was available. I wanted my family to have the full, beautiful MobileMe Gallery experience in all its glory. So, I decided I would recreate the MobileMe Gallery using Silverlight. I figured it would be a good learning experiment since I hadn’t played with Silverlight much before the class.&lt;/p&gt;
&lt;p&gt;So, this is the introductory post of a multi-part series where I will detail out step-by-step the process of Recreating the MobileMe Gallery in Silverlight 3. I hope you’ll follow along as I go down to meticulous detail to ensure my Silverlight Gallery looks exactly like Apple’s MobileMe Gallery.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key Features and Success Criteria:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Play MPEG-4 (.m4v) files using Silverlight without the need for QuickTime&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2. Photo Album and Movie “Scrubbing”&lt;/strong&gt; (if you view the sample above, you’ll see what I mean when you mouse over an album or movie)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3. Full featured photo album with all the features (and views) of the one built-in to MobileMe Gallery&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4. Utilize the photos/movies already stored on MobileMe Gallery&lt;/strong&gt; (no separate upload or storage required…we’ll do this by tapping into the existing APIs and RSS/JSON feeds that MobileMe uses itself by using a little Fiddler detective work)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5. 100% Silverlight implementation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The goal in one sentence is by the time we finish we should have an exact replica, feature-for-feature match of the MobileMe Gallery using Silverlight 3 (see below for a preview).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://anderly.com/wp-content/uploads/2009/07/mobileme_silverlight1.jpg&quot; alt=&quot;MobileMe Gallery (using Silverlight 3)&quot; title=&quot;MobileMe Gallery (using Silverlight 3)&quot; /&gt;&lt;/p&gt;
&lt;p&gt;As for legal disclaimer, I should note that Apple, the Apple logo, MobileMe, the MobileMe logo, and MobileMe Gallery are registered trademarks of Apple.&lt;/p&gt;
&lt;p&gt;Also, I am a multi-Mac owner, multi-iPhone owner, paying member of the iPhone developer program and MobileMe subscriber, so Apple don’t sweat this too much. I’m still a big fan, but needed a good project to develop my Silverlight skills and figured recreating the beautiful MobileMe Gallery would be an excellent challenge.&lt;/p&gt;
&lt;p&gt;Here’s the breakdown:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://anderly.com/2009/10/21/recreating-the-mobileme-gallery-in-silverlight-3-part-1/&quot;&gt;Part 1: Getting Started&lt;/a&gt; – WCF and the initial plumbing required to retrieve the data from the MobileMe Gallery&lt;/li&gt;
&lt;li&gt;Part 2: The Silverlight Project (Coming Soon) – creating the Silverlight project to call our WCF service and start building the home page&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please check back for updates as I’ll continue to update this post with the links to new segments as I complete them.&lt;/p&gt;
</content:encoded><category>Silverlight</category></item></channel></rss>