Tuples in C# 7

While I had originally written about my lack of appreciation for Tuples in .Net 4, the new Tuple feature that has been introduced with C# 7 is really something else.

Having programmed in functional languages like F#, a good Tuple implementation is something I’ve come to appreciate.

Here are the reasons the new Tuple is better than the old one.

Field names

Tuple fields now have names which makes reasoning about the code a whole lot easier.

Compare this:

var oldTuple = 
    Tuple.Create(1, "test", 1.0);

var b = oldTuple.Item1 == 2 ? oldTuple.Item2.ToLower() 
                            : "";            

With this:

(int rebate, string itemName, double price) newTuple
    = (1, "test", 1.0);

var a = newTuple.rebate == 2 ? newTuple.itemName.ToLower() 
                             : "";

Gone are the Item1 and Item2 fields.

Better syntax support

As you can see in the previous example Tuples can be manipulated using the parentheses syntax. There is no need to use the Tuple type’s Create method.

Here’s an example of the new syntax being used to define a Tuple return type for a method.

public (string first, string second) ReturnTuple()
{
    return ("an", "example");
}

 

Deconstruction support

Deconstruction is another feature that F# and some functional programmers (or Rust programmers for that matter) are probably familiar with and that you can now use with Tuples.

Here is an example:

public class FromHellsHeart
{
    public bool GrapplingWithThee { get; set; }
    public bool StabingAtThee { get; set; }
    public bool SpitingAtThee { get; set; }

    public void Deconstruct(out bool grappling, 
                            out bool stabbing,
                            out bool spitting)
    {
        grappling = GrapplingWithThee;
        stabbing = StabingAtThee;
        spitting = SpitingAtThee;
    }
} 

[TestMethod]
public void TupleTest()
{
    var mobyDick = new FromHellsHeart
    {
        GrapplingWithThee = true,
        StabingAtThee = true,
        SpitingAtThee = true,
    };

    (bool g, bool st, bool sp) = mobyDick;
    Assert.IsTrue(g && st && sp);
}   

 

By deconstructing the mobyDick Tuple we have essentially extracted it’s elements into three local variables.

Conclusion

All these new features bring Tuples in line with languages like F# which is a good thing.

Tuples are a great way to prevent having to write one off classes, to easily refactor methods that would need to pass around anonymous types or to replace the older less efficient Tuple.

 

New Sniptaculous version

I’ve just updated Snipatculous, my Visual Studio snippets collection to version 1.01. I’m using it daily at this point and I really like how fast it can make certain scenarios.

For example, ifany will expand to :

if ($value$ != null && $value$.Any())
{
    // cursor ends here instead of comment
    // after value has been replaced
}

The main issue is the installation which consists of a file copy in Visual Studio’s snippet directory. I’ll have to investigate if I could make a Visual Studio Extension that would facilitate the installation procedure and make it seem less barbaric.

SonarLint Visual Studio Extension / C# Linter

I’m currently working on a legacy code base that’s not a shining example of clean code and best practices.

I try to improve the code as I work, a careful balancing act where I do my best not to impact productivity by spending too much time on refactoring and reformatting.

To help me with this task I decided to look into linters. Note that I’m not using ReSharper which would help with code quality, but that’s another story.

I tried StyleCop, but with the default settings I just wasn’t impressed. Many rules are in my opinion needlessly restrictive. It also seemed to simply dump more than a thousand warnings in the error window.

I tried SonarLint next and I must say I was thoroughly impressed. Though the errors are also sent to the error window they are also shown inline in the file. The parsing by SonarLint was fast and running the Visual Studio extension only had a very small impact on performance even while working with a solution containing thousands of files and hundreds of thousands of lines of codes.

While I haven’t run ReSharper in years, performance was one of the two reasons I stopped using it. On large solutions like the one I’m currently working with, it would slow everything down to a crawl, even when disabling solution-wide analysis.

SonarLint isn’t exactly what I was expecting it to be. I thought it would be more for style guidelines but it has instead given me deeper insights. I’m specifically referring to my last two examples.

Things like needlessly nested if statements:

if (FirstProperty == false) 
{
    if (NeedlesslyDeeplyScoped == true)
    { }
}

Using a Count() instead of an Any:

if (files.Count(f => f.IsDeleted) > 0)
// to
if (files.Any(f => f.IsDeleted))

To foreach statements that can run on null variables:

List<Foo> myCollection = null;

if (IsWeatherRainy) 
{
    myCollection = new List<Foo>();
    // add stuff
}

// myColllection null on at least one execution path
foreach (var item in myCollection)

Or overlapping method signatures with optional parameters that can’t be used:

// This method's signature overlaps the second one
// and the default parameter value can't be used
public File GetFile(bool firstParam, 
                    bool secondParam = false)
{
    return new File();
}

public TestFile GetFile(bool firstParam)
{
    return new TestFile();
}

This last one having been found three times in a single file.

SonarLint is available on the Visual Studio marketplace. It’s free and open source with a repository on GitHub. It’s created by a company that also sells a similar product (though geared towards CI / Build servers) but I haven’t found any downsides to using the free Visual Studio Extension.

By the way, I haven’t been asked to write this by the company that makes SonarLint.

Integrating DropzoneJS into an ASP.NET MVC site

Dropzone allows you to easily handle file upload via drag and drop.

Here is a simple tutorial on how to integrate DropzoneJS into an existing ASP.NET MVC application. The instructions on the dropzone page are easy to follow but I include here a version tailored for ASP.NET MVC.

First off, there is a NuGet package but I prefer not to use it so that I can include only the necessary files and choose where those files are located.

The first step is to obtain the JavaScript file and include it into your /Scripts folder.

dropzone1

Optionally you can also download and use the CSS file. Put this one in your /Content folder.

dropzone2

Once these files are in place, it’s time to create some bundles. In App_Start/BundleConfig.cs add the following bundles:

bundles.Add(new ScriptBundle("~/bundles/dropzone")
            .Include("~/Scripts/dropzone.js"));

bundles.Add(new StyleBundle("~/Content/dropzone-css")
            .Include("~/Content/dropzone.css"));

On the page you want to use dropzone on, add calls to the Styles and Scripts render methods and also a form element with the dropzone class. The class name is how dropzone locates the control so it can make the appropriate modifications.

Remember that you can’t nest form elements so if your page already contains another form your will need to make sure they aren’t nested.

Here is how our page.cshtml:

@Styles.Render("~/Content/dropzone-css")

<div class="jumbotron">
    <h1>dropzone test</h1>
</div>

<div class="row">
    @using (Html.BeginForm("FileUpload", "Home", 
                           FormMethod.Post,
                           new
                           {
                               @class = "dropzone",
                               id = "dropzone-form",
                           }))
    {
        <div class="fallback">
            <input name="file" type="file" multiple />
        </div>
    }
</div>

@section scripts {
    @Scripts.Render("~/bundles/dropzone")

    <script type="text/javascript">
        Dropzone.options.dropzoneForm = {
            paramName: "file",
            maxFilesize: 20,
            maxFiles: 4,
            acceptedFiles: "image/*",
            dictMaxFilesExceeded: "Custom max files msg",
        };
    </script>
}

The form contains an optional fallback element for clients who don’t support JavaScript. Also note in the scripts section, custom configuration options are declared.

You may notice I have set a maxFilesize. This value is in MB. It is necessary to change the maxRequestLength attribute in your web.config file to a value at least as big as maxFilesize, otherwise IIS will reject files under the maxFilesize limit.

Here is how to change your maxRequestLength:

<system.web>
    <compilation debug="true" targetFramework="4.5.2" />
    <!--maxRequestLength increased to 20 MB-->
    <httpRuntime targetFramework="4.5.2" 
                 maxRequestLength="20480" />
</system.web>

After we have updated our web.config we can now move on to the controller.

[HttpPost]
public ActionResult FileUpload(HttpPostedFileBase file)
{
    try
    {
        var memStream = new MemoryStream();
        file.InputStream.CopyTo(memStream);

        byte[] fileData = memStream.ToArray();

        //save file to database using fictitious repository
        var repo = new FictitiousRepository();
        repo.SaveFile(file.FileName, fileData);
    }
    catch (Exception exception)
    {
        return Json(new { success = false, 
                          response = exception.Message });
    }

    return Json(new { success = true, 
                      response = "File uploaded." });
}

When uploading multiple files at the same time, this method will get called as many times as there are files.

If you want to handle the returned JSON, you need to handle events from dropzone, in this case the complete event.

Here is how the page looks after having uploaded two pictures:

dropzone3