{"id":27,"date":"2017-04-28T08:45:00","date_gmt":"2017-04-28T15:45:00","guid":{"rendered":"\/lisa\/post\/2017\/04\/28\/In-praise-of-offering-multiple-APIs-QRCodes-for-SSRS-and-more.aspx"},"modified":"2021-11-24T11:21:43","modified_gmt":"2021-11-24T19:21:43","slug":"in-praise-of-offering-multiple-apis-qrcodes-for-ssrs-and-more","status":"publish","type":"post","link":"https:\/\/spacefold.com\/lisa\/2017\/04\/28\/in-praise-of-offering-multiple-apis-qrcodes-for-ssrs-and-more\/","title":{"rendered":"In praise of offering multiple APIs: QRCodes for SSRS and more"},"content":{"rendered":"<p>The need for bar codes never seems to go away &#8212; it just morphs.<\/p>\n<p>In <a title=\"Bar chart trick re-examined\" href=\"\/lisa\/2008\/06\/22\/Walkthrough-A-bar-chart-trick-examined-and-a-charting-alternative-offered\/\" target=\"_blank\" rel=\"noopener\">a 2008 post<\/a>, I talked about different ways to render a chart yourself, if the native types offered weren&#8217;t what you wanted. But I&nbsp; concluded that it might be better not to let the report do the rendering, when you have an external alternative. <\/p>\n<p>This is especially true when it comes to bar code images. Some bar codes can be expressed using custom fonts, which means the RDL can do all the work and it&#8217;s no sweat for you.&nbsp; But, in QRCode&#8217;s case, I don&#8217;t even think it&#8217;s even possible for the RDL to render the image natively no matter what you do.<\/p>\n<p>I have QRCode requirements on a number of fronts right now. I found a number of ways to get a QRCode in a report on the web &#8212; <a title=\"QRCode + SSRS methods\" href=\"http:\/\/lmgtfy.com?q=qrcode+ssrs\">you will too<\/a> &#8212; but most of them seemed over-complicated, used an outside service, etc.<\/p>\n<p>Others suggested the Google Chart API, which of course I have also suggested, in <a title=\"duh, use Google Chart API\" href=\"\/lisa\/2008\/06\/22\/Walkthrough-A-bar-chart-trick-examined-and-a-charting-alternative-offered\/\">the same 2008 post<\/a>, as the obvious, head-slapping alternative to complicating your life with a DIY approach. For bar codes, though, you&#8217;re stuck with using <a title=\"Google Chart Infographics\" href=\"https:\/\/developers.google.com\/chart\/infographics\/\" target=\"_blank\" rel=\"noopener\">Google Chart&#8217;s Infographics<\/a> &#8212; QRCodes are <a title=\"Google Infographics QRCodes\" href=\"https:\/\/developers.google.com\/chart\/infographics\/docs\/qr_codes\">here<\/a>&nbsp; &#8212; which, as you&#8217;ll see, is a deprecated API.&nbsp; Some people, including my employer, object to taking that chance.<\/p>\n<p>Other posted suggestions led the way to open source, free libraries to use for this purpose.<\/p>\n<ul>\n<li><a title=\"QRCode.JS\" href=\"\/\/davidshimjs.github.io\/qrcodejs\/\" target=\"_blank\" rel=\"noopener\">One<\/a> is client side javascript library, and I suppose you could do a hack to get this to work directly into a report, but after looking at whether a div or an iframe would be respected <a title=\"interpreting HTML tags in an RDL\" href=\"https:\/\/docs.microsoft.com\/en-us\/sql\/reporting-services\/report-design\/add-html-into-a-report-report-builder-and-ssrs\" target=\"_parent\" rel=\"noopener\">when SSRS interprets HTML tags<\/a>, which they aren&#8217;t, I didn&#8217;t want to think further about this.&nbsp;<\/li>\n<li><a title=\"QRCode.NET\" href=\"https:\/\/qrcodenet.codeplex.com\/\" target=\"_blank\" rel=\"noopener\">The other<\/a> is a little .NET project, which you can use as a DLL.&nbsp;<\/li>\n<\/ul>\n<p>Now the question becomes:&nbsp; how do we expose the library we choose to use?<\/p>\n<p>While we can register custom DLLs for use by ReportServer, in my current environment that gets a bit messy. I didn&#8217;t relish explaining how to reference the DLL and write the embedded code functions to our various report authors.<\/p>\n<p>After thinking it over, I decided the best path would be a little external web app, which a report could call to get a QRCode as an external image, just as it would have done when using the Google Chart API.<\/p>\n<p>The advantage here, besides simplicity of the reference call in the RDL, is that other applications in our environment, which also might need a QRCode, could call the same web app to get one.&nbsp; My new functionality wouldn&#8217;t be restricted to reports.<\/p>\n<p>With this potential advantage in mind, I decided that the web app could expose multiple APIs, with at least one tuned for use by RDLs.<\/p>\n<h2>&nbsp;<\/h2>\n<h2>1 &#8211; Return a web page using the javascript functionality, <br \/>containing only a QRCode.&nbsp;<\/h2>\n<p>&nbsp;<\/p>\n<p>This method is suitable for any application (usually but not always web based) that <strong>can<\/strong> embed an iframe.&nbsp;<\/p>\n<p>The API is basically<\/p>\n<div class=\"code\">http:\/\/&lt;WebApp&gt;\/&lt;MyURL&gt;?id=[the value you want encoded in the QRCode goes here]<\/div>\n<p>&#8230;and your ASPX page body looks just like this:<\/p>\n<div class=\"code\">&lt;body onload=&#8221;makeCode() ;&#8221;&gt; <br \/> &nbsp;&nbsp; &lt;div id=&#8221;qrcode&#8221; style=&#8221;width:100px; height:100px;&#8221;&gt; <br \/>&nbsp;&nbsp; &lt;\/div&gt; <br \/>&lt;\/body&gt;<\/div>\n<p>The header of your ASPX page uses the appropriate script references, as specified by the camples that come with the library, plus a slightly-adapted function for makeCode(), which grabs the value to encode from the incoming request:<\/p>\n<div class=\"code\">&lt;script type=&#8221;text\/javascript&#8221; src=&#8221;.\/scripts\/jquery.min.js&#8221;&gt;&lt;\/script&gt;<br \/>&lt;script type=&#8221;text\/javascript&#8221; src=&#8221;.\/scripts\/qrcode.js&#8221;&gt;&lt;\/script&gt;<br \/>&lt;script type=&#8221;text\/javascript&#8221;&gt;<br \/>&nbsp;&nbsp;&nbsp; function makeCode() {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var elText = &#8220;&lt;%= Request.QueryString(&#8220;id&#8221;) %&gt;&#8221;;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var qrcode = new QRCode(document.getElementById(&#8220;qrcode&#8221;), {<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; width: 100,<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; height: 100<br \/>&nbsp; &nbsp; &nbsp; &nbsp; });<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qrcode.makeCode(elText);<br \/>&nbsp;&nbsp;&nbsp; }<br \/>&lt;\/script&gt;<\/div>\n<p>&#8230; since this is a client-side approach, of course there&#8217;s no additional code-behind code in this ASPX page, just the embedded reference to the Request.QueryString in the javascript function above.&nbsp;&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<h2>2 &#8211; Return an image instead of a page, using the same API as above.<\/p>\n<\/h2>\n<p>Here&#8217;s what that would look like, if it isn&#8217;t obvious:<\/p>\n<div class=\"code\">http:\/\/&lt;WebApp&gt;\/&lt;MySecondURL&gt;?id=[the value you want encoded in the QRCode goes here]<\/div>\n<p>This second web page uses server-side functionality.&nbsp; It can be used the same way as the first one, but works even if you just want to get an image returned (you don&#8217;t want to use an iframe, js is not available, etc).&nbsp; In my case, I chose to return PNGs, but you could make this configurable using a second parameter on the URL.<\/p>\n<p>None of the samples I saw for returning an image from an ASPX rather than a page exactly worked for me, so I&#8217;ll show you the code I used here.&nbsp; Notice that I&#8217;m using the value encoded as the name of the PNG returned.&nbsp; This may not always be practical, and it might make more sense to use a static name:<\/p>\n<div class=\"code\">&nbsp;&nbsp;&nbsp; &#8216; Gma.QrCodeNet.Encoding is referenced in the project.<\/p>\n<p> &nbsp;&nbsp;&nbsp; Protected Sub Page_Load(ByVal sender As Object, _<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ByVal e As System.EventArgs) Handles Me.Load<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim id As String = Request.QueryString(&#8220;id&#8221;)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If String.IsNullOrEmpty(id) Then<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id = &#8220;test&#8221;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End If<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim tempBMP As Bitmap = GenerateQRCode(id)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Clear()<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Buffer = False<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.AddHeader(&#8220;Content-Disposition&#8221;, _<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String.Format(&#8220;inline; filename=&#8221; &amp; Chr(34) &amp; _<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;{0}.png&#8221; &amp; Chr(34), id))<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.ContentType = &#8220;image\/png&#8221;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tempBMP.Save(Response.OutputStream, _<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Drawing.Imaging.ImageFormat.Png)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tempBMP.Dispose()<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Close()<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.End()<\/div>\n<div class=\"code\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tempBMP = Nothing<br \/>&nbsp;&nbsp;&nbsp; End Sub<\/div>\n<p>The GenerateQRCode function invoked above is basically taken from samples that come with the library, in my case.&nbsp; If you were generating a different type of image or using a different library your version would be different but, for the record and for completeness, here&#8217;s my version of the function.&nbsp; There is no other code in this web page.<\/p>\n<div class=\"code\">&nbsp;&nbsp;&nbsp; Private Function GenerateQRCode(val As String) As Bitmap<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim Encoder As _ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; New Gma.QrCodeNet.Encoding.QrEncoder( _<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Gma.QrCodeNet.Encoding.ErrorCorrectionLevel.L)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim Code As Gma.QrCodeNet.Encoding.QrCode = Encoder.Encode(val)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim TempBMP As New Bitmap(Code.Matrix.Width, Code.Matrix.Height)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For X As Integer = 0 To Code.Matrix.Width &#8211; 1<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; For Y As Integer = 0 To Code.Matrix.Height &#8211; 1<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If Code.Matrix.InternalArray(X, Y) Then<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TempBMP.SetPixel(X, Y, Color.Black)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Else<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TempBMP.SetPixel(X, Y, Color.White)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End If<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Next<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Next<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return TempBMP<br \/>&nbsp;&nbsp;&nbsp; End Function<\/div>\n<h2>&nbsp;<\/h2>\n<h2>3 &#8211; Return an image using a custom http handler.&nbsp;<\/h2>\n<p>&nbsp;<\/p>\n<p>This API is both performant and perfectly suited for use in SSRS.&nbsp; I&#8217;d never written a custom handler before, so I followed <a title=\"writing an ASPX custom HTTP handler\" href=\"http:\/\/www.jigar.net\/articles\/viewhtmlcontent3\/\" target=\"_blank\" rel=\"noopener\">the directions here<\/a> and simplified my life by allowing the handler to work for &#8220;http:\/\/&lt;WebApp&gt;\/*.PNG&#8221;.&nbsp; Now an API simply uses an image object with an external URL.<\/p>\n<p>By default, the image you get encodes the value of the filename you use for the PNG (filename stem only, I discard the path and the PNG extension).<\/p>\n<p>However, this is a RESTful interface, and it&#8217;s really easy to provide more intelligence for particular needs.&nbsp; For example, you could register your handler to *.IMAGE, and then parse the path for the type of image to return (with a suitable default, if none is given by the request, of course).&nbsp; <\/p>\n<p>In our case, we wanted inventory labels with QRCodes that would link directly to a <a title=\"jira ticketing system \" href=\"https:\/\/www.atlassian.com\/software\/jira\" target=\"_blank\" rel=\"noopener\">jira<\/a> item in a specific project for each physical item bearing such a label.&nbsp;<\/p>\n<p>Rather than force the client (in this case, an RDL that is formatted to print our inventory labels) to bear the burden of fashioning the full jira URL, we could easily put that intelligence into the handler.&nbsp;<\/p>\n<p>Here&#8217;s my entire handler, which as you can see is very similar to the webform approach above but requires a different method (in my testing) to successfully write the response:<\/p>\n<div class=\"code\">Imports System.Web<br \/>Imports System.Drawing<br \/>Imports System.IO<br \/>Imports Microsoft.VisualBasic<\/p>\n<p>&#8216; again, project references Gma.QrCodeNet.Encoding<\/p>\n<p>Public Class QRCodeHandler<br \/>&nbsp;&nbsp;&nbsp; Implements IHttpHandler<\/p>\n<p>&nbsp;&nbsp;&nbsp; Public ReadOnly Property IsReusable() As Boolean <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Implements IHttpHandler.IsReusable<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Get<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return True<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End Get<br \/>&nbsp;&nbsp;&nbsp; End Property<\/p>\n<p>&nbsp;&nbsp;&nbsp; Public Sub ProcessRequest(ByVal context As HttpContext) <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Implements IHttpHandler.ProcessRequest<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim req As String = context.Request.Path<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim prefix As String =&nbsp; _ <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IIf(req.ToLower().Contains(&#8220;jira&#8221;), My.Settings.JiraURLPrefix, &#8220;&#8221;)<\/p>\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim id As String =&nbsp; _<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.IO.Path.GetFileNameWithoutExtension(req)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If String.IsNullOrEmpty(id) Then<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; id = &#8220;test&#8221;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End If<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim tempBMP As Bitmap = GenerateQRCode(prefix &amp; id)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim buffer As Byte() = GetBytesForImage(tempBMP)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.Response.Clear()<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.Response.ContentType = &#8220;image\/png&#8221;<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.Response.OutputStream.Write(buffer, 0, buffer.Length)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; context.Response.End()<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buffer = Nothing<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tempBMP = Nothing<br \/>&nbsp;&nbsp;&nbsp; End Sub<\/div>\n<div class=\"code\">&nbsp;&nbsp;&nbsp; Private Function GenerateQRCode(val As String) As Bitmap<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8216; insert same function as the WebForm class above<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return TempBMP<br \/>&nbsp;&nbsp;&nbsp; End Function<\/p>\n<p>&nbsp;&nbsp;&nbsp; Private Function GetBytesForImage(tmpBMP As Bitmap) As Byte()<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim outStream As New System.IO.MemoryStream()<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmpBMP.Save(outStream, _<\/div>\n<div class=\"code\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Drawing.Imaging.ImageFormat.Png)<br \/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return outStream.ToArray()<br \/>&nbsp;&nbsp;&nbsp; End Function<\/p>\n<p>End Class<\/p><\/div>\n<p>&#8230; and, as you can see, it would be easy to special-case or adapt this code for other needs besides creating a jira URL, using path components.<\/p>\n<p>For a handler, you&#8217;ll also need to register the handler in your web.config and\/or with IIS.&nbsp; How you do this depends on exactly how you&#8217;ve set up IIS and your web site, and I&#8217;m really a novice at this, so either read the docs and <a title=\"writing an ASPX custom HTTP handler\" href=\"http:\/\/www.jigar.net\/articles\/viewhtmlcontent3\/\" target=\"_blank\" rel=\"noopener\">the directions here<\/a> or whatever other source is suitable for your web app, or as a last resort, you can drop me a line and I&#8217;ll try to help you muddle through.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The need for bar codes never seems to go away &#8212; it just morphs. In a 2008 post, I talked about different ways to render a chart yourself, if the native types offered weren&#8217;t what you wanted. But I&nbsp; concluded that it might be better not to let the report do the rendering, when you<a class=\"more-link\" href=\"https:\/\/spacefold.com\/lisa\/2017\/04\/28\/in-praise-of-offering-multiple-apis-qrcodes-for-ssrs-and-more\/\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,5],"tags":[],"class_list":["post-27","post","type-post","status-publish","format-standard","hentry","category-asp-net","category-reporting"],"_links":{"self":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts\/27","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/comments?post=27"}],"version-history":[{"count":1,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts\/27\/revisions"}],"predecessor-version":[{"id":496,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/posts\/27\/revisions\/496"}],"wp:attachment":[{"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/media?parent=27"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/categories?post=27"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/spacefold.com\/lisa\/wp-json\/wp\/v2\/tags?post=27"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}