Generate QR Barcode in ASP.Net MVC

I had a task of creating a QR barcode and displaying it on a web-page from ASP.Net MVC system. There are a lot of free web-services for generating a qr-codes for you, ( like http://qrcode.kaywa.com/ ) But this time I did not want to use a service for various reasons. I had to get the barcode generated on my server. (Just accept it as default!)

I have found many .Net libraries that generate a qr-barcodes, but for some reason I did like QrCode.Net. Probably because it is hosted on codeplex and I keep my open-source projects there as well.

I have downloaded their Dll file, added it as a reference to my MVC project:

In my MVC project I have added a new action that returned a FileStremResult:

using Gma.QrCodeNet.Encoding;
using Gma.QrCodeNet.Encoding.Windows.Controls;

public virtual FileResult BarcodeImage(String barcodeText)
{
    // generating a barcode here. Code is taken from QrCode.Net library
    QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.H);
    QrCode qrCode = new QrCode();
    qrEncoder.TryEncode(barcodeText, out qrCode);
    Renderer renderer = new Renderer(5, Brushes.Black, Brushes.White);

    // write to file if required for auditing
    //renderer.CreateImageFile(qrCode.Matrix, String.Format(@"d:\tmp\{0}.png", barcodeText), ImageFormat.Png);

    Stream memoryStream = new MemoryStream();
    renderer.WriteToStream(qrCode.Matrix, memoryStream, ImageFormat.Png);

    // very important to reset memory stream to a starting position, otherwise you would get 0 bytes returned
    memoryStream.Position = 0;

    var resultStream = new FileStreamResult(memoryStream, "image/png");
    resultStream.FileDownloadName = String.Format("{0}.png", barcodeText);

    return resultStream;
}

UPDATE 23 Dec 2013: Since this article was written, the API of QrCode.Net has changed slightly and the code above does no longer compile. So see the new code:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Web.Mvc;
using Gma.QrCodeNet.Encoding;
using Gma.QrCodeNet.Encoding.Windows.Render;

namespace SampleBarCodeMvc.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult BarcodeImage(String barcodeText)
        {
            // generating a barcode here. Code is taken from QrCode.Net library
            QrEncoder qrEncoder = new QrEncoder(ErrorCorrectionLevel.H);
            QrCode qrCode = new QrCode();
            qrEncoder.TryEncode(barcodeText, out qrCode);
            GraphicsRenderer renderer = new GraphicsRenderer(new FixedModuleSize(4, QuietZoneModules.Four), Brushes.Black, Brushes.White);

            Stream memoryStream = new MemoryStream();
            renderer.WriteToStream(qrCode.Matrix, ImageFormat.Png, memoryStream);

            // very important to reset memory stream to a starting position, otherwise you would get 0 bytes returned
            memoryStream.Position = 0;

            var resultStream = new FileStreamResult(memoryStream, "image/png");
            resultStream.FileDownloadName = String.Format("{0}.png", barcodeText);

            return resultStream;
        }
    }
}

Then in one of the views I place this image tag:

  <img src="/Controller/BarcodeImage?barcodeText=Hello"/>

Where Controller is a name of your controller where you placed the action. And that will give you an image with a barcode and word “Hello” encoded in it.

I have quickly created a sample solution in Visual Studio 2013 (you should be able to open that in VS2012):
SampleBarCodeMvc – this is to show a working example.

Enjoy!

Update: QrCode.Net is now available via nuget package and can be installed either via Nuget inside of your Visual Studio or in VS-console: Install-Package QrCode.Net

Disable unobtrusive validation on per-element basis in ASP.Net MVC

Sometimes you just don’t want a validation on your form elements, but the framework just adds the validation automatically, cause it is too clever. To disable the validation on one element, pass html parameter data_val=false to your controller and JavaScript will ignore the that field. Example:

@Html.DropDownList("documentId", new SelectList(ViewBag.MetaTags, "Value", "Text"), new {data_val=false})

Convert Due Date to human readable format

Sometimes you need to show date in a “Due in X-days” format, not just a date. This will convert date to a string with granularity: Today, tomorrow, yesterday, days, weeks, months.

public static class HumanTime
{
    public static string DueDate(DateTime dueDate) {
        return DueDate(dueDate, DateTime.Now);
    }

    public static string DueDate(DateTime dueDate, DateTime dateNow) {
        DateTime nowDate = dateNow;

        TimeSpan ts = nowDate - dueDate;

        if (dueDate.Date == DateTime.Today)
        {
            return "due today";
        }

        if (dueDate.Date == DateTime.Now.AddDays(1).Date)
        {
            return "due tomorrow";
        }

        if (dueDate.Date == DateTime.Now.AddDays(-1).Date)
        {
            return "was due yesterday";
        }


        int totalDays = (int)Math.Round(ts.TotalDays);
        if (Math.Abs(totalDays) &lt; 7)
        {
            return DueStringFormat(totalDays, "day");
        }

        int weeks = (int)Math.Round( ts.TotalDays / 7 );
        if (Math.Abs(weeks) &lt; 5 && Math.Abs(totalDays)&lt;30 )
        {
            return DueStringFormat(weeks, "week");
        }

        int months = (int)Math.Round( ts.TotalDays / 30 );
        return DueStringFormat(months, "month");
    }


    public static string DueStringFormat(int count, string unit)
    {
        string format = "{0} {1}";
        if (count &lt; 0)
        {
            format = "due in {0} {1}";
        } 
        else
        {
            format = "{0} {1} overdue";
        }

        return String.Format(format, Math.Abs(count), unit.Quantify(count));
    }


    /// Adds "s" suffix to a word if there are more than one thing involved.
    public static string Quantify(this String singular, int count)
    {
        int abs = Math.Abs(count);
        if (abs > 1)
            return singular+"s";
        else 
            return singular;
    }
}

Enums and Display attribute

Enums are handy. But they do not allow you have easy Text description on them.
How about using DisplayAttribuite on enum values and have that text in a drop-down? Easy!

/// <summary>
/// Creates a SelectList from Enum, taking Description values from Enum fields
/// Taken from here: http://stackoverflow.com/a/3705387/809357
/// </summary>
public static SelectList ToSelectListWithDisplayName<T>(this T enumeration, string selected = "")
{
    var source = Enum.GetValues(typeof(T));

    var items = new Dictionary<object, string>();

    var displayAttributeType = typeof(DisplayAttribute);

    foreach (var value in source)
    {
        FieldInfo field = value.GetType().GetField(value.ToString());

                    if (field == null) continue;

        DisplayAttribute attrs = (DisplayAttribute)field.GetCustomAttributes(displayAttributeType, false).FirstOrDefault();
        if (attrs != null)
        {
            items.Add((int)value, attrs.GetName());
        }else   // in case Description attribute is not available, we fall back to the default name
        {
            items.Add((int)value, value.ToString());
        }
    }
    return new SelectList(items, "Key", "Value", selected);
}

Also you can get just on Display Name for one Enum Value:

public static string GetDisplayName(this Enum value)
{
    FieldInfo field = value.GetType().GetField(value.ToString());

    if (field == null)
        return String.Empty;

    object[] attribs = field.GetCustomAttributes(typeof(DisplayAttribute), true);
    if(attribs.Length > 0)
    {
        return ((DisplayAttribute)attribs[0]).GetName();
    }
    return value.ToString();
}

Creating custom Html Helper in MVC3

Creating custom attribute is pretty simple really, just follow the example. You need to return MvcHtmlString – that is string with your html to be displayed on a page – this will not be escaped.

public static MvcHtmlString DisplayWithNameFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper,Expression<Func<TModel, TProperty>> expression)
{
    ModelMetadata metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
    if (metaData.Model == null)
    {
        return MvcHtmlString.Create(String.Empty);
    }

    string html = "<div class=\"display-label\">";
    html += htmlHelper.LabelFor(expression).ToString();
    html += "</div><div class=\"display-field\">";
    html += htmlHelper.DisplayFor(expression).ToString();
    html += "</div>";

    return MvcHtmlString.Create(html);
}

MVC Recipies: On Page Action Return to the previous page

Whenever you need a page to return to the previous page when you get an form submit or some other action, this can be used:

Have a base controller that is inherited by all your controllers. That is always a good idea – you can easily add things that work site-wide.
In you base controller have a OnActionExecuting overriden – here we are going to store the previous page.
Something like this:

public abstract partial class MyController : Controller
{

public ActionResult RedirectToPrevious(String defaultAction, String defaultController)
{
  if (Session == null || Session["PrevUrl"] == null)
  {
      return RedirectToAction(defaultAction, defaultController);
  }

  String url = ((Uri)Session["PrevUrl"]).PathAndQuery;

  if (Request.Url != null && Request.Url.PathAndQuery != url)
  {
      return Redirect(url);
  }

  return RedirectToAction(defaultAction, defaultController);
}


protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var httpContext = filterContext.HttpContext;

    if (httpContext.Request.RequestType == "GET"
        && !httpContext.Request.IsAjaxRequest()
        && filterContext.IsChildAction == false)    // do no overwrite if we do child action.
    {
        // stop overwriting previous page if we just reload the current page.
        if (Session["CurUrl"] != null 
            && ((Uri)Session["CurUrl"]).Equals(httpContext.Request.Url) ) 
            return;

        Session["PrevUrl"] = Session["CurUrl"] ?? httpContext.Request.Url;
        Session["CurUrl"] = httpContext.Request.Url;
    }
}
}

Now, as I figured, it is not the best idea for redirecting everything by default. For validation purposes you would like not to redirect

Then you can reference Session[“PrevUrl”] in controllers, but there is a better way of doing it – create attribute!

public class RedirectToPreviousPageAttribute : ActionFilterAttribute
{
///

/// Place [RedirectToPreviousPage] attribute on Controller action
/// and when you do submit of form, this functionality will kick in.
/// We check if Session has Previous URL set and force to redirect
/// to whatever it says.
/// If no Session variable is set, just do what it is supposed to do in the first place.
///

/// public override void OnResultExecuted(ResultExecutedContext filterContext)
{
var httpContext = filterContext.HttpContext;

    if (httpContext.Session == null || httpContext.Session["PrevUrl"] == null)
    {
        base.OnResultExecuted(filterContext);
        return;
    }

    String url = ((Uri)httpContext.Session["PrevUrl"]).PathAndQuery;

    if (httpContext.Request.Url != null && httpContext.Request.Url.PathAndQuery != url)
    {
        httpContext.Response.Redirect(url);
    }


    base.OnResultExecuted(filterContext);

}

}

And now, wherever you are put this attribute on a controller action (or entire controller), it will redirect to the previous page:

[HttpPost]
public virtual ActionResult Edit(Model model)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

    _repository.InsertOrUpdate(model);
    _repository.Save();

    return RedirectToPrevious("Index", "Controller");
}

VoilĂ ! Good to go!