Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Friday, June 26, 2015

Building an Interactive SVG Pie Chart with Asp.Net MVC Razor and C#

In one of my recent web development projects I set out to redesign a basic pie chart. The previous implementation was generated by a javascript framework that did more than it was used for, and lacked some of the flexibility that we wanted. So for the rewrite I decided to simplify the code, and take an opportunity to learn more about SVG graphics.

Bear in mind as you read this that it's all still pretty "fresh" ...the code probably can (and should) be refactored. But this should serve as a good basic introduction. There are a number of good tutorials on the web for generating SVG pie charts. This post focuses on my implementation using Asp.Net MVC, C#, and Razor. WHat you'll see below is the combination of various bits of knowledge gathered from around the web and a fair amount of tinkering and troubleshooting. I think the final result looks pretty nice, so I figured it was worth sharing.

Why SVG? Because it's a vector-based image, it can scale up or down and never get pixellated, and looks good on any screen from desktop to mobile. The image data itself is very minimal, and because it can be written inline with your HTML, it doesn't require extra HTTP calls. The SVG code itself is pretty simple as well, so I don't need to rely on more intensive server-side image generation code. There are plenty of reasons why SVG is cool, but those are just a few that come to mind right now. SVG is pretty widely supported now across all major browsers except IE8, which at least for my current project I don't need to worry about.

I started out by writing a basic C# class to hold all the relevant information needed for a simple pie chart:

Having this dedicated PieChart class allows me to generate pie charts throughout my application in a consistent way. In my MVC controller, I can build a view model for the page, and include a PieChart object. Then, in my Razor view, I can add a simple call to "DisplayFor" to generate the inline SVG, using a shared display template.

The bulk of the code lives in the shared razor template in Views/Shared/DisplayTemplates/PieChart.cshtml

To keep everything fairly self-contained, I decided to include the SVG-specific C# code right in the Razor file. While this may not adhere very well to separation of concerns, it certainly helps with manageability and making it easier to follow/understand. A fair tradeoff if you ask me. Here's the entire Razor file. I'll explain each section below:


@functions

Normally I don't put complex functions in my razor views, so I didn't know the "@functions" block existed until now. For this application it was the perfect container for some simple trigonometric calculations.

PieSlicePathDesc

In SVG, we can use the path element to define complex shapes. In this case, we'll need to generate multiple "pie slices". This function does the math to calculate the x/y coordinates of each point, and outputs the path description in SVG's language. Basically the path description boils down to these instructions:

  • Start drawing at the center of our pie chart
  • Move to a point on the outside of the circle
  • Draw an arc with a given radius until we reach the next x/y coordinate
  • Draw a line back to the starting point to complete the shape

With all this logic defined here, we can easily call it in the razor markup later.

startAngle

For my pie chart, I want the first slice to start at the top of the circle. Here I set the starting angle.

svg

With most of the code out of the way, we can start generating the actual SVG tags. For a great reference to all the SVG tags and attributes, check out MDN's SVG Element Reference. The viewBox attribute defines the limits of the image using the SVG's internal coordinate system. I sized this image to have a padding around the outside equal to 10% of the radius. This comes in handy later for our hover effect.

style

Here in the SVG I embedded some CSS styling to apply a consistent style to all the pie slices, mainly to give them all a white outline.

@foreach loop

Using Razor, we can easily enumerate over the collection of PieChartSlice objects and generate the SVG paths.

g (Group) element

This is a basic SVG element to group together other SVG elements together. This allows us to combine the pie slice, as well as a tooltip and some hover animation elements.

title element

In SVG, the title element acts much like the title attribute in HTML. In most browsers this text will appear as a tooltip when the mouse hovers over it. I could have used other elements to write the text on the image, but I decided to keep it hidden to keep the image clean and uncluttered. If the user hovers over the pie slice, they can see the label, the value, and the percentage. The text is also available to screen readers and other web accessibility tools.

circle or path

In the event that our pie chart's data set only contains one item, we only need to draw a full circle, not a slice.  If we are generating multiple slices, the SVG path is used, and calls the PieSlicePathDesc method we defined earlier.

Hover animations with animateTransform

To add a little interactivity, I wanted to add a hover effect to each pie slice, where the slice would expand outward while hovering over it. To do this I added some animateTransform elements to the group containing the pie slice. There is one animation that expands from the center by 5% on mouseover, and another animation that shrinks back down on mouseout.

Finished!

My final implementation was a bit more complex. I added some code for generating the pie slice colors and some other changes specific to my project, but this should give you a basic idea of how it works.

To see the final result, below is some actual inline SVG generated by this code:

Thinking: 0:38:39 (39.3%) Writing Code: 0:34:16 (34.9%) Researching: 0:11:33 (11.8%) Refactoring: 0:09:52 (10%) Getting Distracted: 0:03:54 (4%)

Wednesday, September 24, 2014

Sql query performance monitoring with EF6 through interception

Lately I've been building a web application against a database that I don't have full control over which is used by a variety of other internal applications. If something were to affect the performance of my app (such as a slow database query) I'd like to know before my users start to complain. To that end, I've built out some very basic always-on production monitoring/instrumentation. For example, I set up a Http Module to monitor response times on all Http requests, and log the ones that fall outside of a given threshold.

I've been using NLog, through the Common.Logging interface to handle this sort of thing. I have NLog configured to email me a log dump whenever an error or warning occurs. If I can just log a warning when a sql query takes too long, the rest of the process (logging, emailing, etc) is taken care of.

When I first started looking into it, I was looking at the new DbContext.Database.Log property in Entity Framework 6. I could set it to any action that takes a string, intercept the messages, and parse out the occasional log message that contained the query execution time. This was admittedly a bit messy, but it worked.

I did a little more research and discovered what I really needed... database interception. In particular, this article laid out a simple example of database interception code. However it didn't show any way to actually measure query execution time. I decided to figure out how the EF logger was doing it. After looking at some stack traces and poking around in JustDecompile, I found the System.Data.Entity.Infrastructure.Interception.DatabaseLogFormatter class. This is the class that actually generates the messages sent through the Database.Log action. It works as a database interceptor, and just implements a simple timer that starts and stops with each SQL command that passes through it. Armed with this information, I had enough to build up a proper sql monitoring class for EF6 that logs slow queries and also sql errors:

Tuesday, July 1, 2014

Getting Started with LESS CSS in your ASP.Net MVC project

Today one of my coworkers asked me for more information on a CSS preprocessor I had mentioned in one of our weekly meetings. I've been using LESS CSS lately for one of my projects and enjoying it. It simplifies the CSS I have to write, and the language is easy to follow as most of the syntax reads like standard CSS code.

Getting Started with LESS

Here’s the official LESS website that will walk you through how it works:
They have some good documentation and examples to get you started.

This was originally designed to “compile” the CSS in the user's web browser. I prefer to do this before it gets to the client. This offloads some of the work from the client browser, and ensures your CSS will always be generated the same way every time regardless of the client's browser capabilities. This also prevents the chance of making the page “blink” as it converts the LESS to CSS. This is especially applicable to me as my current web application project is running on a "thin client" machine which runs an older browser on a limited processor.

So how do we get from a LESS file to usable CSS? There are a couple ways to generate your CSS from LESS files…

Getting to CSS

The easiest way to get started would be to use the popular Visual Studio extension Web Essentials:
It provides great LESS support in Visual Studio (and lots of other handy features). Every time you save a LESS file, it automatically generates an accompanying CSS file in your project, which you can then reference in your page.

Too many files?

Personally I don’t like managing all the extra CSS files in my project. Part of me worries that my CSS won't always be "in sync" with my LESS file, either from some unseen bug or more likely a mistake I may make. I prefer to let the server automatically generate my CSS on the fly, and cache the generated result. This gets a bit more complex and requires some other packages, but I feel it's worth it.

First, I love the LESS preview function in Web Essentials, but as I mentioned I don't want the CSS files generated. This is easy to disable under Visual Studio's Tools > Options menu. Under Web Essentials > Less, disable "Compile files on save."

I use a NuGet package called dotLess (a .net based LESS compiler):
It handles all requests for .less files and returns the compiled CSS. This way I can put a reference on my page for a .LESS file and the server will return the compiled CSS automatically. The only drawback is that it isn't quite up to date with the LESS spec, so I've run into a few issues with some of the more complicated aspects of the LESS language. Thus far I've been able to work around them so I'm willing the accept the trade off for the convenience it provides.

Bundling & Minification

Generated CSS is great, but it's even better if we can bundle and minify everything to improve the page load time and the overall user experience.

For bundling & minification with dotLess, I use this package:
This gives me a “LessBundle” class that will let me bundle & minify multiple CSS & LESS files. For example, my BundleConfig.cs file in my MVC project has this entry in it:

bundles.Add(new LessBundle("~/Content/styles")
    .Include("~/Content/normalize.css")
    .Include("~/Content/less/Site.less")
);
Now, I can just include a reference to the bundle in my view:
@Styles.Render("~/Content/styles")
In debug mode I get a style tag for each file. The request for the less file will be handled by dotLess
<link href="/Content/normalize.css" rel="stylesheet"></link>
<link href="/Content/less/Site.less" rel="stylesheet"></link>
In Release mode, bundling and minification become enabled, and everything in the LESS Bundle is compiled with dotLess and minified into a single stylesheet link:
<link href="/Content/styles?v=OVSsAe9M_HQdBtQlL5-p9IRWblY32n6g5U4FaGEiUCE1" rel="stylesheet"></link>
More LESS Links: