Flush Async Output Events

The System.Diagnostics.Process class provides the options to retrieve all output from an external process after it has completed, or to retrieve events containing the output as the execution occurs. The option to receive asynchronous output events is useful in scenarios where you need to provide user feedback or log the output when timeouts occur.

When receiving asynchronous output events, you must ensure that the external process has completed when you want to make sure that you get all the output. Continue reading Flush Async Output Events

Structured Logging with Serilog and ELK

ThoughtWorks recently released their Technology Radar report for January 2015 and structured logging was among the techniques that they strongly suggested that the industry adopt. I’ve actually had some exposure to structured logging over the past year and have been very happy with the results. So, I thought I would share my experience. Continue reading Structured Logging with Serilog and ELK

Force Bundling Optimizations

Use the following code in the BundleConfig.cs of your ASP.NET MVC application to force bundling and minification.

// BundleConfig::RegisterBundles
BundleTable.EnableOptimizations = true;

Why?

Why would you do this? Sometimes bundling and minification causes problems, such as in AngularJS. You will want to find these problems before publishing, so just enable this line every once in a while to make sure everything still works as expected with the optimizations.

Read Open File in C#

This post is a summary of this StackOverflow answer by Cheeso.

To read a file that is currently open (or may be open later) in another process, you must specify a FileShare option. The FileShare flag indicates the modes that other processes are allowed to open the file in.

using (Stream s = System.IO.File.Open(fullFilePath, 
          FileMode.Open, 
          FileAccess.Read,       // I want to open this file for reading only.
          FileShare.ReadWrite))  // Other processes may specify 
                                 // FileAccess of read or write.
{
}

Reference

Email Addresses as User Names in ASP.NET Identity

It’s common for web applications to use email addresses instead of user names to distinguish users. However, if you are using ASP.NET Identity, you have probably noticed that it has UserName built into the IUser interface. Since Identity assumes that this is the distinguishing field for the user, it’s not crazy to think that it might be a good place to drop the email address. In order to have Identity allow an email address in this field, you will need to write a custom IIdentityValidator.

/// <summary>
/// A replacement for the <see cref="UserValidator"/> which requires that an email 
/// address be used for the <see cref="IUser.UserName"/> field.
/// </summary>
/// <typeparam name="TUser">Must be a type derived from <see cref="Microsoft.AspNet.Identity.IUser"/>.</typeparam>
/// <remarks>
/// This validator check the <see cref="IUser.UserName"/> property against the simple email regex provided at
/// http://www.regular-expressions.info/email.html. If a <see cref="UserManager"/> is provided in the constructor,
/// it will also ensure that the email address is not already being used by another account in the manager.
/// 
/// To use this validator, just set <see cref="UserManager.UserValidator"/> to a new instance of this class.
/// </remarks>
public class CustomUserValidator<TUser> : IIdentityValidator<TUser>
    where TUser : class, Microsoft.AspNet.Identity.IUser
{
    private static readonly Regex EmailRegex = new Regex(@"^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
    private readonly UserManager<TUser> _manager;

    public CustomUserValidator()
    {
    }

    public CustomUserValidator(UserManager<TUser> manager)
    {
        _manager = manager;
    }

    public async Task<IdentityResult> ValidateAsync(TUser item)
    {
        var errors = new List<string>();
        if (!EmailRegex.IsMatch(item.UserName))
            errors.Add("Enter a valid email address.");

        if (_manager != null)
        {
            var otherAccount = await _manager.FindByNameAsync(item.UserName);
            if (otherAccount != null && otherAccount.Id != item.Id)
                errors.Add("Select a different email address. An account has already been created with this email address.");
        }

        return errors.Any()
            ? IdentityResult.Failed(errors.ToArray())
            : IdentityResult.Success;
    }
}

UPDATE 03/28/2014: As John Holliday points out, Identity 2.0 requires that the TUser be a reference type, so where TUser : Microsoft.AspNet.Identity.IUser was updated to where TUser : class, Microsoft.AspNet.Identity.IUser. Thanks John!

This validator ensures that the UserName field is set to an email address. It also optionally ensures that the email address is not being used by another account.

UPDATE 11/17/2013: I just found out that ValidateAsync is called at times other than when creating a new user, such as when adding external logins with UserManager.AddLoginAsync. This caused errors to occur with the original code because it thought it found duplicates. The fix this, && otherAccount.Id != item.Id has been added when checking for duplicates.

In order to use this validator, just set your UserManager.UserValidator to a new instance of it.

[Authorize]
public class AccountController : Controller
{
    public AccountController()
        : this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
    {
        UserManager.UserValidator = new CustomUserValidator<ApplicationUser>(UserManager);
    }