Solving development problems  |  About this blog

The easiest way to generate a QR Code for software developers

So you want to simply generate a QR Code image without diving into the technical specifics? This blog post contains a few simple examples. Just copy-paste where you need it.

Idea is to build a URL, make an HTTP request and download the QR Code image. Result is the following image:

your content goes here

HTTP Request

URL looks like http://www.esponce.com/api/v3/generate?content={content}&format={format} where {content} is URL encoded content to be embedded in QR and {format} is output image format. Available formats are png, jpg, bmp, tif, xaml, svg, eps, txt, html, zip (containing all listed formats)

List of other parameters like color and size can be found here.

C# Sample

This code can be used in .NET 2.0 including ASP.NET and WPF or Silverlight for web or WP7

using System;
using System.IO;
using System.Web;
using System.Net;

public class Program
{
  public static void Main(string[] args)
  {
    //Generate a QR Code and save it to file "sample.png"
    Generate("your content goes here", "png", "sample.png");
  }

  public static void Generate(string content, string format, string path)
  {
    string encoded = HttpUtility.UrlEncode(content);
    Uri uri = new Uri("http://www.esponce.com/api/v3/generate?content=" + encoded + "&format=" + format);
    WebClient client = new WebClient();
    client.DownloadFile(uri, path);
  }
}

Java Sample

This code can be used in a classic Java application or web applet or Android application

import java.io.*;
import java.net.*;

public class qrcode
{
  public static void main(String args[])
  {
    //Generate a QR Code image and save it to file "sample.png"
    generate("your content goes here", "png", "sample.png");
  }

  public static void generate(String content, String format, String path)
  {
    try
    {
      String encoded = URLEncoder.encode(content, "UTF-8");
      String url = "http://www.esponce.com/api/v3/generate?content=" + encoded + "&format=" + format;
      BufferedInputStream ins = new BufferedInputStream(new URL(url).openStream());
      FileOutputStream fos = new FileOutputStream(path);
      BufferedOutputStream bos = new BufferedOutputStream(fos, 1024);

      int size = 0;
      byte data[] = new byte[1024];
      while ((size = ins.read(data, 0, 1024)) > 0)
      {
        bos.write(data, 0, size);
      }

      bos.close();
      fos.close();
      ins.close();
    }
    catch (Exception e)
    {
    }
  }
}

Python Sample

Using Python 2.7

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import urllib
import httplib

def generate(content, format = "png"):
    query = urllib.urlencode({ "content": content, "format": format })
    con = httplib.HTTPConnection("www.esponce.com")
    con.request("GET", "/api/v3/generate?" + query)
    response = con.getresponse()
    image = response.read()
    con.close()
    return image

image = generate("your content goes here")
file = open("sample.png", "wb")
file.write(image)
file.close()

JavaScript Sample

JavaScript in combination with HTML

<img id="qrcode" src="" alt="QR Code" />
<script type="text/javascript">
    function generate(content)
    {
        var url = "http://www.esponce.com/api/v3/generate?content=" + encodeURI(content) + "&format=png";
        var img = document.getElementById("qrcode");
        img.src = url;
    }
    generate("your content goes here");
</script>

PHP Sample

<img src="<?php echo generate("your content goes here"); ?>" alt="QR Code" />

<?php
function generate($content, $format = "png")
{
    $encoded = urlencode($content);
    $url = "http://www.esponce.com/api/v3/generate?content=$encoded&format=$format";
    return $url;
}
?>

There is more

Download all samples with make script here.

Other QR Code related methods like decoding (reverse process of generating) and tracking scans can be found at esponce.com.

Visual Source Safe Analyze and Repair tool problems

This is the solution if you got this error message when trying to do Analyze and Repair some VSS database using does prompt command:
C:\>”C:\Program Files (x86)\Microsoft Visual SourceSafe\analyze.exe” -F -V3 -D “\\my_server\my_vss_database\data

Error was:

Database analysis in progress File ../data/status.dat is already open Cannot rebuild the database while Visual SourceSafe is being run. Make sure all users have exited SourceSafe and try again.

Solution

Make sure there are no users connected to the VSS database (running ssexp, ssadmin, etc), that users cannot connect to the database using the web service (they connect only for short times, so it’s hard to see them listed as logged in with ssadmin), and that VSS LAN Service is stopped (use net stop ssservice), as it may keep a connection open to the database.

Set IIS binding manually (add and remove IIS binding)

We had an issue that we need to add or remove IIS 7 or IIS 7.5 additional bindings on one web application and we wanted to do this from one of our ASP.NET MVC applications.

It is possible so you need to use IIS system program appcmd.exe (you can find it in C:\Windows\System32\inetsrv\ (we suggest you to put this into your PATH variable)

Adding additional bindings

You want to add your-subdomain.your-domain.com binding to your IIS 7 app named your-domain.com

C:\Windows\System32\inetsrv\appcmd set site /site.name: your-domain.com /+bindings.[protocol='http',bindingInformation='*:80:your-subdomain.your-domain.com']

Removing existing bindings

You want to remove your-subdomain.your-domain.com binding from your IIS 7 app named your-domain.com (please notice - sign in front of bindings word)

C:\Windows\System32\inetsrv\appcmd set site /site.name: your-domain.com /-bindings.[protocol='http',bindingInformation='*:80:your-subdomain.your-domain.com']

And that’s it but if you want to run it from ASP.NET you could try to use Process and ProcessInfo classes to run DOS command but there are some permissions problems (we didn’t investigated much).

Other (alternative way that we tried is directly from the code)
You will need to reference this DLL: c:\Windows\System32\inetsrv\Microsoft.Web.Administration.dll

using (ServerManager serverManager = new ServerManager())
{
  if (serverManager.Sites == null)
    throw new SimpleException("There are no IIS applications!");

  var esponceApp = serverManager.Sites.FirstOrDefault(
x => x.Name == Settings.IISAppName);
  if (esponceApp != null)
  {
    BindingCollection bindingCollection = esponceApp.Bindings;
    Binding binding = bindingCollection.CreateElement("binding");
    binding["protocol"] = "http";
    binding["bindingInformation"] =
string.Format(@"{0}:{1}:{2}", "*", "80", this.DomainName);

    //Remove this binding if already exists.
    int oldBindingIndex = -1;
    int bindingIndex = -1;
    foreach (Binding currentBinding in esponceApp.Bindings)
    {
      if (currentBinding.BindingInformation ==
binding["bindingInformation"].ToString())
      {
        bindingIndex = esponceApp.Bindings.IndexOf(currentBinding);
      }
      if (!string.IsNullOrEmpty(oldDomainName) &&
      currentBinding.BindingInformation ==
string.Format(@"{0}:{1}:{2}", "*", "80", oldDomainName))
      {
        oldBindingIndex = esponceApp.Bindings.IndexOf(currentBinding);
      }
    }
    if (bindingIndex != -1)
    {
      esponceApp.Bindings.RemoveAt(bindingIndex);
    }
    if (oldBindingIndex != bindingIndex && oldBindingIndex != -1)
    {
      esponceApp.Bindings.RemoveAt(oldBindingIndex);
    }

    //Add this bindings
    bindingCollection.Add(binding);
    serverManager.CommitChanges();
  }
}
}
catch
{
throw new SimpleException("Could not add binding into IIS application!");
}

Important!
Set identity of your app’s Application Domain from Advanced Settings > Process Model > Identity > Change “ApplicationPoolIdentity” to “Local System”

Investigate also security implications if you are not running this in Intranet….

Increasing maximum request length for WCF REST Web Service with ASP .NET 4.0

Recently we have extended a web service with method for uploading user’s profile image. So far the service was working fine with less amount of data, i.e. name, address and description. First image upload test with the new method resulted with 400 Bad Request. Breakpoints were set in WCF method but debugger did not stop there, not even entered the method.

Default configuration

WCF service had been configured for REST using default webHttpBinding configuration in web.config

<configuration>
  ...
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="ApiBehavior" />
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="Avivo.Web.Services.ApiServiceBehavior">
         <serviceMetadata httpGetEnabled="true" />
         <serviceDebug includeExceptionDetailInFaults="false" />
         <serviceTimeouts transactionTimeout="00:05:00" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <services>
      <!-- API v1.0 -->
      <service behaviorConfiguration="Avivo.Web.Services.ApiServiceBehavior"
name="Avivo.Web.Services.ApiService">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:1234/api/v1" />
          </baseAddresses>
        </host>
        <endpoint address="" binding="webHttpBinding"
contract="Avivo.Web.Services.IApiService" behaviorConfiguration="ApiBehavior" />
      </service>
    </services>

    <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true">
      <baseAddressPrefixFilters>
        <add prefix="http://localhost:1234/api/v1"/>
      </baseAddressPrefixFilters>
    </serviceHostingEnvironment>

  </system.serviceModel>
  ...
</configuration>

Identifying the problem

Images can be quite large (few MB), especially when comparing with text size (few KB). At first it was assumed the web service call has exceeded maximum request length limit. To confirm the assumption we analyzed WCF traffic using SvcTraceViewer.

Enabling WCF tracing in web.config

<configuration>
  ...
  <!-- Use SvcTraceViewer for debugging WCF services -->
  <system.diagnostics>
    <trace autoflush="true" />
    <sources>
      <source name="System.ServiceModel" switchValue="Information,
ActivityTracing" propagateActivity="true">
        <listeners>
          <add name="sdt" type="System.Diagnostics.XmlWriterTraceListener"
initializeData="d:\temp\wcf-trace.svclog" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>
  ...
</configuration>

When the tracing is set each request to web service will write entry to d:\temp\wcf-trace.svclog in this case. The report file can be opened with SvcTraceViewer found in %ProgramFiles%\Microsoft SDKs\Windows, e.g. “c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\SvcTraceViewer.exe”

Entries in SvcTraceViewer marked with red represents errors. The problematic request was logged with error message:

The maximum message size quota for incoming messages (65536) has been exceeded. To increase the quota, use the MaxReceivedMessageSize property on the appropriate binding element.

Identifying that assumption was right and the upload request exceeded default 65 KB limit.

Increasing request limit quota

Customizing webHttpBinding in web.config and referencing with bindingConfiguration in endpoint element

<configuration>
        ...
  <system.serviceModel>
        ...
    <bindings>
      <!-- Customizations for REST service -->
      <webHttpBinding>
        <!-- Limits set to 10 MB (specified value in bytes) -->
        <binding name="ApiQuotaBinding" maxReceivedMessageSize="10485760"
maxBufferPoolSize="10485760" maxBufferSize="10485760" closeTimeout="00:03:00"
openTimeout="00:03:00" receiveTimeout="00:10:00" sendTimeout="00:03:00">
          <readerQuotas maxDepth="32" maxStringContentLength="10485760"
maxArrayLength="10485760" maxBytesPerRead="10485760" />
          <security mode="None" />
        </binding>
      </webHttpBinding>
    </bindings>

    <services>
      <!-- API v1.0 -->
      <service behaviorConfiguration="Avivo.Web.Services.ApiServiceBehavior"
name="Avivo.Web.Services.ApiService">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:1234/api/v1" />
          </baseAddresses>
        </host>
        <!-- Added attribute 'bindingConfiguration' -->
        <endpoint address="" bindingConfiguration="ApiQuotaBinding" binding="webHttpBinding"
contract="Avivo.Web.Services.IApiService" behaviorConfiguration="ApiBehavior" />
      </service>
    </services>

  </system.serviceModel>
  ...
</configuration>

Additionally httpRuntime limits must also be set because web service is running in ASP .NET compatibilty mode. Note that maxRequestLength has value in kilobytes.

<configuration>
  ...
  <system.web>
    <httpRuntime maxRequestLength="10240" />
  </system.web>
  ...
</configuration>

Testing

Finding the solution was not straightforward, it took some time searching the web and reading documentation. Finally after figuring out the described config in this post we solved the problem with success.

October 26th, 2011

Adding stored JavaScript procedures to MongoDB using Windows Batch script

MongoDB can use stored procedures similar to MSSQL. To make a MongoDB procedure create a new file, name it like DoSomething.js, write a function and attach it to database.

Guide through example

Lets say we have a log of website visitors stored in visitors collection inside myweb database. Each visitors record contains date and time of a visit. Now we want to create monthly statistics – how many users visits website per month.

visitors collection looks like:

> use myweb
> db.visitors.findOne()
{
  "_id": ObjectId("4e0cb7e7da3ea11d18d841e7"),
  "timestamp": "Thu Jun 30 2011 19:52:39 GMT+0200 (Central Europe Daylight Time)"
}

Most reusable way to get data is to create a stored procedure GetVisitsPerMonth() and call it on demand. Create a file GetVisitsPerMonth.js and copy-paste the following code inside. Note that file name is named by procedure.

function ()
{
	var result = db.visitors.group(
	{
		keyf: function(doc)
		{
			return { //NOTE: Bracket must be in this line!!!
				month: doc.timestamp.getMonth(),
				year: doc.timestamp.getFullYear()
			};
		},
		initial: {count:0},
		reduce: function(doc, prev) { prev.count++ }
	});

	return result;
}

How to attach one procedure

Stored procedure can be manually attached like this:

db = connect("localhost:27017/myweb");
db.system.js.save({"_id":"GetVisitsPerMonth", "value": function() { ... });

How to attach multiple procedures

Large sets of procedures should be well organized in files so you can quickly find a procedure and fix it if necessary. To insert or update all procedures at once use a simple batch script.

Create a new file, name it install.bat and copy-paste the following code inside:

@echo off

:parameters
set DBCON=localhost:27017/myweb
set MONGO=c:\mongodb\bin\mongo.exe
set SCRIPT=script.js

:startup
if not exist %MONGO% goto error
if not "%1"=="" goto add

rem Append connection string
echo Adding connection string...
echo db = connect("%DBCON%"); > %SCRIPT%
echo. >> %SCRIPT%

rem Append scripts
call %0 GetVisitsPerMonth
rem call %0 DoSomething
rem other procedures go here

goto install
rem goto end

:add
echo Adding script %1...
echo db.system.js.save({"_id":"%1", "value": >> %SCRIPT%
type %1.js >> %SCRIPT%
echo }); >> %SCRIPT%
echo. >> %SCRIPT%
goto end

:install
echo Running script...
%MONGO% %SCRIPT%
goto end

:error
echo Check if mongo is installed:
echo %MONGO%

:end

Edit parameters according to your needs: path to mongo.exe, database name, and list of procedures.
Simply run the script and it is done.

Testing a stored procedure

Log into mongo console:

> use myweb
> db.eval("GetVisitsPerMonth()")
[
  {
    "month": 5,
    "year": 2011,
    "count": 28233,
  },
  {
    "month": 6,
    "year": 2011,
    "count": 48026,
  },
  {
    "month": 7,
    "year": 2011,
    "count": 92754,
  }
]

October 7th, 2011