Help
RSS
API
Feed
Maltego
Contact
Domain > blog.zerosharp.com
×
More information on this domain is in
AlienVault OTX
Is this malicious?
Yes
No
DNS Resolutions
Date
IP Address
2014-09-23
23.235.46.133
(
ClassC
)
2016-07-15
151.101.48.133
(
ClassC
)
2024-10-06
185.199.111.153
(
ClassC
)
Port 80
HTTP/1.1 200 OKConnection: keep-aliveContent-Length: 99369Server: GitHub.comContent-Type: text/html; charsetutf-8Last-Modified: Sun, 04 Nov 2018 21:09:23 GMTAccess-Control-Allow-Origin: *ETag: 5bdf6003-18429expires: Sun, 06 Oct 2024 01:28:48 GMTCache-Control: max-age600x-proxy-cache: MISSX-GitHub-Request-Id: B014:3FD743:21A535C:22ABE37:6701E577Accept-Ranges: bytesAge: 0Date: Sun, 06 Oct 2024 01:18:48 GMTVia: 1.1 varnishX-Served-By: cache-bfi-kbfi7400049-BFIX-Cache: MISSX-Cache-Hits: 0X-Timer: S1728177529.631149,VS0,VE99Vary: Accept-EncodingX-Fastly-Request-ID: 8a7b064c97e20d7bfa548be5433a9c7575cec9a1 !DOCTYPE html>!--if IEMobile 7 >html classno-js iem7>!endif-->!--if lt IE 9>html classno-js lte-ie8>!endif-->!--if (gt IE 8)|(gt IEMobile 7)|!(IEMobile)|!(IE)>!-->html classno-js langen>!--!endif-->head> meta charsetutf-8> title>ZeroSharp/title> meta nameauthor contentRobert Anderson> meta namedescription contentTomorrow could be an exciting moment in the history of maths. Sir Michael Atiyah is presenting a proof of the Riemann Hypothesis at the Heidelberg …> !-- http://t.co/dKP3o1e --> meta nameHandheldFriendly contentTrue> meta nameMobileOptimized content320> meta nameviewport contentwidthdevice-width, initial-scale1> link relcanonical hrefhttp://ZeroSharp.github.com/> link href/favicon.png relicon> link href/stylesheets/screen.css mediascreen, projection relstylesheet typetext/css> script src/javascripts/modernizr-2.0.js>/script> script src/javascripts/ender.js>/script> script src/javascripts/octopress.js typetext/javascript>/script> link hrefhttp://feeds.feedburner.com/zerosharp relalternate titleZeroSharp typeapplication/atom+xml> !--Fonts from Googles Web font directory at http://google.com/webfonts -->link hrefhttp://fonts.googleapis.com/css?familyPT+Serif:regular,italic,bold,bolditalic relstylesheet typetext/css>link hrefhttp://fonts.googleapis.com/css?familyPT+Sans:regular,italic,bold,bolditalic relstylesheet typetext/css> !-- ra+> -->link hrefhttp://fonts.googleapis.com/css?familyUbuntu:500 relstylesheet typetext/css>link hrefhttp://fonts.googleapis.com/css?familyOpen+Sans relstylesheet typetext/css>link hrefhttp://fonts.googleapis.com/css?familyInconsolata relstylesheet typetext/css>link href/stylesheets/custom/data-table.css mediascreen, projection relstylesheet typetext/css>!-- /ra+> --> script typetext/javascript> var _gaq _gaq || ; _gaq.push(_setAccount, UA-30564687-1); _gaq.push(_trackPageview); (function() { var ga document.createElement(script); ga.type text/javascript; ga.async true; ga.src (https: document.location.protocol ? https://ssl : http://www) + .google-analytics.com/ga.js; var s document.getElementsByTagName(script)0; s.parentNode.insertBefore(ga, s); })(); /script>/head>body classcollapse-sidebar sidebar-footer > header rolebanner>hgroup> !--h1>a href/>ZeroSharp/a>/h1>--> a hrefhttp://www.zerosharp.com/>h1>ZeroSharp/h1>/a> h2>Robert Andersons ones and zeros/h2> /hgroup>/header> nav rolenavigation> form actionhttp://google.com/search methodget> fieldset rolesearch> input typehidden nameq valuesite:ZeroSharp.github.com /> input classsearch typetext nameq results0 placeholderSearch/> /fieldset>/form>ul classmain-navigation> li>a href/>Blog/a>/li> li>a href/blog/archives>Archives/a>/li> li>a href/about/>About/a>/li> li>a href/license/>License/a>/li> /ul>ul classsubscription> li>a relme hrefhttps://plus.google.com/112685056596124127572?relauthor> img src/images/asides/googleplus.png width24 height24 altRob on Google+> /a>/li> li>a relme hrefhttp://twitter.com/8ctopus> img src/images/asides/twitter.png width24 height24 altRob on Twitter /> /a>/li> !--li>a relme hrefhttp://stackoverflow.com/users/1077279/shamp00> img src/images/asides/stackoverflow.png width24 height24 altRob on StackOverflow /> /a>/li> li>a relme hrefhttps://github.com/zerosharp> img src/images/asides/github.png width24 height24 altRob on GitHub /> /a>/li> li>a relme hrefhttp://www.linkedin.com/profile/view?id926740 class googleplus-hidden > img src/images/asides/linkedin.png width24 height24 altRob on LinkedIn /> /a>/li> li>a relme hrefhttp://springpad.com/#!/shamp00 class googleplus-hidden > img src/images/asides/springpad.png width24 height24 altRob on SpringPad /> /a>/li> li>a relme hrefhttp://pinterest.com/shamp00 class googleplus-hidden > img src/images/asides/pinterest.png width24 height24 altRob on Pinterest /> /a>/li> li>a relme hrefhttp://www.last.fm/user/nosredna class googleplus-hidden > img src/images/asides/lastfm.png width24 height24 altRob on Last.fm /> /a>/li>--> li>a hrefhttp://feeds.feedburner.com/zerosharp> img src/images/asides/rss.png relsubscribe-rss width24 height24 altRSS Feed /> /a>/li>/ul>/nav> div idmain> div idcontent> div classblog-index> article> header> h1 classentry-title>a href/has-the-riemann-hypothesis-been-proved/>Has the Riemann Hypothesis Been Proved?/a>/h1> p classmeta> time datetime2018-09-23T08:35:00+01:00 pubdate data-updatedtrue>Sep 23span>rd/span>, 2018/time> | a href/has-the-riemann-hypothesis-been-proved/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>img classright src/images/blog/has-the-riemann-hypothesis-been-proved-michael-atiyah.jpg titleBy Tugsataydin CC BY-SA 4.0 from Wikimedia Commons >Tomorrow could be an exciting moment in the history of maths. a hrefhttps://en.wikipedia.org/wiki/Michael_Atiyah>Sir Michael Atiyah/a> is presenting a proof of the Riemann Hypothesis at the Heidelberg Laureate Forum which will be available on a hrefhttps://www.youtube.com/user/LaureateForum>their youtube channel/a>. There is a good angle by Ken Regan on the a hrefhttps://rjlipton.wordpress.com/2018/09/21/the-specter-of-simpler-proofs/>Gödel’s Lost Letter blog/a>./p>p>The Riemann Hypothesis is one of the most important unsolved problems in mathematics and the subject of one of my favourite books about maths: a hrefhttps://www.amazon.com/Prime-Obsession-Bernhard-Greatest-Mathematics/dp/0452285259>Prime Obsession/a>./p>p>A few years ago in Paris, I had the pleasure of seeing a href/an-afternoon-with-two-fields-medallists>Sir Michael speak/a>. He spoke so cheerfully about life and mathematics. There is a great interview with him on the a hrefhttps://www.youtube.com/playlist?listPLVV0r6CmEsFzjttuP9WTFDzu0oAOJBM_3>Web of Stories/a> YouTube channel./p>/div> /article> article> header> h1 classentry-title>a href/my-essential-web-applications/>My Essential Web Applications and iPhone Apps/a>/h1> p classmeta> time datetime2018-09-18T09:27:00+01:00 pubdate data-updatedtrue>Sep 18span>th/span>, 2018/time> | a href/my-essential-web-applications/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>This is part three of a series of posts about the software and tools I find invaluable. See a href/essential-applications>Part 1: essential applications/a> and a href/my-essential-visual-studio-tools-and-extensions>Part 2: Visual Studio tools/a>. In this post I’m covering the online applications and iPhone apps I find indispensible./p>h2>a hrefhttps://www.google.com/gmail/>Gmail/a>/h2>p>Does the job./p>h2>a hrefhttps://www.lastpass.com/>Lastpass/a>/h2>p>Everyone needs a password manager./p>h2>a hrefhttps://www.pinboard.in>Pinboard/a> (and the a hrefhttps://pinswiftapp.com/>PinSwift/a> iPhone app)/h2>p>The best bookmark tracking tool. Simple, fast, powerful. The best mobile app for it is a hrefhttps://pinswiftapp.com/>PinSwift/a>./p>h2>a hrefhttps://bear.app/>Bear/a>/h2>p>A very pretty MarkDown editor for Mac and iPhone. I use a hrefhttps://bear.app/>Bear/a> for all my notes./p>h2>a hrefhttps://www.google.com/drive/download/>Google Drive File Stream/a>/h2>p>Since I use a hrefhttps://gsuite.google.com/>GSuite/a>, it makes sense to try to put everything there. Google Drive has improved enormously since they moved to a file streaming approach./p>h2>a hrefhttps://mail.google.com/tasks/canvas>Google Tasks/a> (and the a hrefgotasksapp.com/>GoTasks/a> app)/h2>p>I need simple task manager with support for multiple lists, hierarchies and available everywhere. Google Tasks is often overlooked in this regard. Check out the a hrefhttps://mail.google.com/tasks/canvas>Google Tasks canvas/a>. There is also a fantastic free iPhone app for it a hrefhttp://gotasksapp.com/>GoTasks/a>./p>h2>a hrefhttps://feedly.com/>Feedly/a>/h2>p>a hrefhttps://feedly.com/>Feedly/a> is the best RSS news feed reader, in my opinion. I keep up with a few development blogs, a few science blogs and the blogs of my friends. The mobile app is great too./p>h2>a hrefhttps://www.xero.com/>Xero/a>/h2>p>I’ve been using a hrefhttps://www.xero.com/>Xero/a> for eight years now. Business accounting software done right./p>h2>a hrefhttps://www.amazon.com/kindle-dbs/fd/kcp>Kindle/a>/h2>p>I like real books but don’t always lug them about with me, so often I buy both the hard copy and the kindle version (there shoudl be some sort of clever discount for this…). The Kindle app is where I spend my time when I have no connectivity (the London tube, airplanes, etc.)/p>h2>a hrefhttps://chess.com>Chess.com/a> and a hrefhttps://lichess.com>Lichess.com/a>/h2>p>I waste hours playing online blitz chess. I’ve even written a couple of Chrome extensions: a hrefhttps://chrome.google.com/webstore/detail/lichess-print-friendly-pd/goijhimgdjppmhmjkaglhggoapkgobfg>Pretty print your games/a> and a hrefhttps://chrome.google.com/webstore/detail/chesscom-v3-analysis/bhjlkimpkkgkmfjlcfngmakenalgleap>Analyse any chess.com game with lichess/a>./p>p>Chess is a mascohistic, character-building pastime. Progress is elusive. You play a couple of good games and you think you’re improving and then you get thrashed repeatedly by a 10 year old./p>/div> /article> article> header> h1 classentry-title>a href/my-essential-visual-studio-tools-and-extensions/>My Essential Visual Studio Tools and Extensions/a>/h1> p classmeta> time datetime2018-09-10T15:45:00+01:00 pubdate data-updatedtrue>Sep 10span>th/span>, 2018/time> | a href/my-essential-visual-studio-tools-and-extensions/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>This is part two of a series of posts about the software and tools I find invaluable. See a href/essential-applications>part 1/a> and a href/my-essential-web-applications>part 3/a>./p>h2>CodeRush/h2>p>I’ve been using DevExpress a hrefhttps://www.devexpress.com/products/coderush/>CodeRush/a> since 2005. Check out a hrefhttps://youtu.be/v5-MVSoqCnU>this video tutorial/a> for a lightening tour of a lot of the features, and look at the DevExpress youtube channel for a hrefhttps://www.youtube.com/playlist?listPL8h4jt35t1wgawacCN9wmxq1EN36CNUGk>a load of other tutorials/a>./p>h2>NCrunch/h2>p>a hrefhttps://www.ncrunch.net/>NCrunch/a> provides continuous testing for Visual Studio. When I make any change to my code which breaks a unit test, the NCrunch risk status goes red a few seconds later, even without recompiling. I get immediate feedback for any breaking change, so long as I have a test for it. Not only does it encourages me and my team to write good tests, but it allows us to make new changes andrefactor with confidence./p>p>img src/images/blog/ncrunch-progress-bar.png>/p>h2>Redgate .NET Reflector Developer Bundle/h2>p>When the going gets tough, the a hrefhttps://www.red-gate.com/products/dotnet-development/ants-performance-profiler/index>ANTS Performance Profiler/a> and a hrefhttps://www.red-gate.com/products/dotnet-development/ants-memory-profiler/index>ANTS Memory Profiler/a> have helped me find some of the hardest bugs I’ve come across./p>p>Also, while there are several good .NET decompilers, many of them free, I got used to a hrefhttps://www.red-gate.com/products/dotnet-development/reflector/index>.NET Reflector/a> which comes part of this bundle./p>h2>T4/h2>p>I use code generation to automatically generate templates for unit tests for validation rules and a hrefhttps://docs.microsoft.com/en-us/visualstudio/modeling/code-generation-and-t4-text-templates?viewvs-2017>T4/a> and the a hrefhttps://marketplace.visualstudio.com/items?itemNameOlegVSych.T4ToolboxforVisualStudio2017>T4 Toolbox/a> fit the bill nicely./p>p>For a more advanced use case, see my post about automatically a href/making-xaf-reports-even-better-part-1/>converting DevExpress v1 report scripts/a> to check for compilation errors and allow for unit testing of report scripts./p>h2>AWS Toolkit/h2>p>I always install the a hrefhttps://aws.amazon.com/visualstudio/>Amazon Web Services Toolkit/a> to make it easy to spin up test servers in the Amazon cloud./p>h2>Next up/h2>p>My a href/my-essential-web-applications>essential web applications and iPhone apps/a>./p>/div> /article> article> header> h1 classentry-title>a href/essential-applications/>My Essential Applications/a>/h1> p classmeta> time datetime2018-09-07T15:23:00+01:00 pubdate data-updatedtrue>Sep 7span>th/span>, 2018/time> | a href/essential-applications/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>This is the first in a series of posts where I list the applications that I use and enjoy the most. See a href(/my-essential-visual-studio-tools-and-extensions>part 2/a>) and a href/my-essential-web-applications>part 3/a>./p>p>A bit of preamble, my most powerful machine is a Windows-only desktop with lots of RAM and an SSD drive. I use it almost exclusively for development./p>p>I also have a Macbook Pro which is configured to dual-boot Windows and MacOS. The Windows machine is more or less a mirror of my main development machine. The Mac is where I do all my document editing, Word, blogging, etc. I also use it for my occasional forays in to iPhone development or other non-Windows experiments./p>p>When I upgrade my development machine, I reconfigure the previous system for Linux, currently Ubuntu./p>h2>Chocolatey/h2>p>In Windows, a hrefChocolatey%20-%20The%20package%20manager%20for%20Windows>Chocolatey/a> is a very convenient way to install programs. Just go:/p>pre>code>C:> choco install nodejs/code>/pre>h2>Boxstarter/h2>p>Even better, create a powershell script with all the applications you want to install and run it with a hrefhttps://boxstarter.org/>boxstarter/a>. Repeatable and reboot-resilient environment installations using chocolatey under the hood. For several years now, I have maintained a script for installing my entire development environment (and the build server) from scratch. Works whether it’s a physical or a virtual machine./p>h2>BeyondCompare/h2>p>a hrefhttps://www.scootersoftware.com/>BeyondCompare/a> is the best file-comparison tool I’ve found. Cross-platform too, I have it installed on my Mac as well./p>h2>Synergy/h2>p>a hrefhttps://symless.com/synergy>Synergy/a> allows me to share one mouse and keyboard across all my machines. It works just like dual monitors, except when the mouse moves onto the next screen, you’ve actually changed computer. I don’t have multiple monitors any more, I just switch the input on my giant a hrefhttps://www.dell.com/en-us/shop/dell-ultrasharp-34-curved-monitor-u3417w/apd/210-aiyz/monitors-monitor-accessories>curved 34” Dell monitor/a> via a keyboard shortcut./p>h2>7Zip/h2>p>Nothing to say./p>h2>VS Code/h2>p>First class support for .NET and C#, Typescript in particular, but a hrefhttps://code.visualstudio.com/>VS Code/a> is also extremely good with Javascript, Powershell, Python, Markdown, etc. Multiple cursor support. Cross-platform. Extensions. I’m writing this blog post in VS Code./p>h2>Visual Studio/h2>p>My daily workhorse. I’ve spent more screen time here than anywhere./p>h2>Zotero/h2>p>Keep track of academic papers. Download them for offline reading. Handle citations and bibliographies effortlessly from within Word. a hrefhttps://www.zotero.org/>Zotero/a>./p>h2>Next up/h2>p>More on Visual Studio in the a href/my-essential-visual-studio-tools-and-extensions>next post/a> where I go through my essential extensions and tools./p>/div> /article> article> header> h1 classentry-title>a href/macbook-and-the-mysterious-sleep/>Macbook and the Mysterious Sleep/a>/h1> p classmeta> time datetime2017-08-23T16:46:00+01:00 pubdate data-updatedtrue>Aug 23span>rd/span>, 2017/time> | a href/macbook-and-the-mysterious-sleep/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>I finally worked out why my Macbook was randomly sleeping./p>p>strong>TL;DR/strong> - a href#anchor-tldr>Skip to the end/a>./p>h2>Clues/h2>p>It only seemed to happen when I was working while sitting up on the bed with the computer on my lap. It seemed to be related to the position of the computer or possibly the lid. The computer would sleep. I’d wake it and login again. Continue. Sometimes it would happen once. Sometimes three times in ten minutes. Annoying. I assumed some hardware defect./p>h2>Pajamas/h2>p>Then over several days I cracked it. I realised it never happened when I was wearing pajamas. Very strange./p>h2>Reflections/h2>p>I started thinking about what normally triggers sleep mode. Closing the lid. How does a Macbook know the lid is closed. There’s not really a clasp or anything so it must be a magnet. Perhaps it’s getting confused by my belt buckle or something. My phone?/p>p>No, my phone em>case/em>! The flip-case of my phone has a magnet to keep the flap closed. In my jeans pocket it’s near enough to make the laptop think the lid has been closed. Duh./p>h2>a nameanchor-tldr>/a>TL;DR/h2>p>Take your mobile phone out of your pocket!/p>/div> /article> article> header> h1 classentry-title>a href/improvements-to-serverless-php-support/>Improvements to Serverless PHP Support/a>/h1> p classmeta> time datetime2017-03-02T11:37:00+00:00 pubdate data-updatedtrue>Mar 2span>nd/span>, 2017/time> | a href/improvements-to-serverless-php-support/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>I was inspired by two events to jump back into serverless framework./p>p>img classleft src/images/blog/serverless-php-improvements-001.jpeg width200 titleServerless London Meetup >/p>p>Firstly, I attended the second a hrefhttps://www.meetup.com/Serverless-London/>London serverless meetup/a> yesterday evening which was excellent and showed just how much enthusiasm there is for serverless architectures. Check out their new logo on the left. It was significant that each of the three speakers announced that they are actively hiring serverless developers./p>p>Secondly, a hrefhttps://github.com/Stolz>Stolz/a> has contributed improvements to my sample project for integrating PHP into the serverless framework. It’s the purpose of this blog post to cover the changes./p>p>The trick to getting AWS lambda to support PHP is to bundle in a PHP binary so that nodejs can call it with code>child_process.spawn()/code>. In a href/the-serverless-framework-and-php/>my first implementation/a>, I used an Ubuntu docker base image to compile and produce the php binary. Unfortunately, this is not identical to the container that AWS Lambda uses and so sometimes the logs would contain errors such as:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>/pre>/td>td classcode>pre>code classsh>span classline>START RequestId: 728dcddf-feaa-11e6-8346-2125e1c055d7 Version: span classnv>$LATEST/span>/span>span classline>2017-03-01 18:11:10.455 span classo>(/span>+00:00span classo>)/span> 728dcddf-feaa-11e6-8346-2125e1c055d7 stderr: ./php: /usr/lib64/libcurl.so.4: no version information available span classo>(/span>required by ./phpspan classo>)/span>/span>span classline>/span>span classline>END RequestId: 728dcddf-feaa-11e6-8346-2125e1c055d7/span>span classline>REPORT RequestId: 728dcddf-feaa-11e6-8346-2125e1c055d7 Duration: 6000.08 ms Billed Duration: 6000 ms Memory Size: 1024 MB Max Memory Used: 23 MB /span>/code>/pre>/td>/tr>/table>/div>/figure>p>In my experience, these errors were often not fatal, but the correct approach is to build the php binary from a base image which is closer to the one lambda uses. So instead of my docker file starting with code>FROM ubuntu/code>, it now starts with code>FROM amazonlinux/code>. Also, with this image, I can use code>yum/code> to install other dependencies like code>libpng-devel/code>. So the new docker build script for producing the php binary looks like this:/p>figure classcode>figcaption>span>dockerfile.buildphp/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>span classline-number>16/span>span classline-number>17/span>span classline-number>18/span>span classline-number>19/span>span classline-number>20/span>span classline-number>21/span>span classline-number>22/span>span classline-number>23/span>span classline-number>24/span>span classline-number>25/span>span classline-number>26/span>span classline-number>27/span>span classline-number>28/span>span classline-number>29/span>span classline-number>30/span>span classline-number>31/span>span classline-number>32/span>span classline-number>33/span>span classline-number>34/span>span classline-number>35/span>span classline-number>36/span>span classline-number>37/span>span classline-number>38/span>span classline-number>39/span>span classline-number>40/span>span classline-number>41/span>span classline-number>42/span>/pre>/td>td classcode>pre>code classsh>span classline>span classc># Compile PHP with static linked dependencies/span>/span>span classline>span classc># to create a single running binary/span>/span>span classline>/span>span classline>FROM amazonlinux/span>span classline>/span>span classline>ARG PHP_VERSION/span>span classline>/span>span classline>RUN yum install span classse>\/span>/span>span classline> autoconf span classse>\/span>/span>span classline> automake span classse>\/span>/span>span classline> libtool span classse>\/span>/span>span classline> bison span classse>\/span>/span>span classline> re2c span classse>\/span>/span>span classline> libxml2-devel span classse>\/span>/span>span classline> openssl-devel span classse>\/span>/span>span classline> libpng-devel span classse>\/span>/span>span classline> libjpeg-devel span classse>\/span>/span>span classline> curl-devel -y/span>span classline>/span>span classline>RUN curl -sL https://github.com/php/php-src/archive/span classnv>$PHP_VERSION/span>.tar.gz | tar -zxv/span>span classline>/span>span classline>WORKDIR /php-src-span classnv>$PHP_VERSION/span>/span>span classline>/span>span classline>RUN ./buildconf --force/span>span classline>/span>span classline>RUN ./configure span classse>\/span>/span>span classline> --enable-staticspan classo>/span>yes span classse>\/span>/span>span classline> --enable-sharedspan classo>/span>no span classse>\/span>/span>span classline> --disable-all span classse>\/span>/span>span classline> --enable-json span classse>\/span>/span>span classline> --enable-libxml span classse>\/span>/span>span classline> --enable-mbstring span classse>\/span>/span>span classline> --enable-phar span classse>\/span>/span>span classline> --enable-soap span classse>\/span>/span>span classline> --enable-xml span classse>\/span>/span>span classline> --with-curl span classse>\/span>/span>span classline> --with-gd span classse>\/span>/span>span classline> --with-zlib span classse>\/span>/span>span classline> --with-openssl span classse>\/span>/span>span classline> --without-pear/span>span classline>/span>span classline>RUN make -j 5/span>/code>/pre>/td>/tr>/table>/div>/figure>p>If you run this with/p>pre>code>$ sh dockerfile.buildphp/code>/pre>p>It will use docker to overwrite the php binary which will get shipped when you deploy with code>sls deploy/code>. And this time, there are no more libcurl errors. All the code is a hrefhttps://github.com/ZeroSharp/serverless-php>on Github/a>./p>/div> /article> article> header> h1 classentry-title>a href/a-concrete-php-serverless-example/>A Concrete PHP Serverless Example - Export Chess Games in PDF/a>/h1> p classmeta> time datetime2016-11-29T17:37:00+00:00 pubdate data-updatedtrue>Nov 29span>th/span>, 2016/time> | a href/a-concrete-php-serverless-example/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>In a href/the-serverless-framework-and-php/>the last post/a> I built a PHP capable sample project for a hrefhttps://serverless.com/>the Serverless Framework/a>. In this post, I’ll show a concrete use of it./p>p>The service I’m building connects runs a PHP function for pretty-printing chess games from the a hrefhttp://lichess.org/>lichess online chess server/a>. a hrefhttps://github.com/clarkerubber/lichessPDFExporter>James Clarke/a> has written a PHP function to do this using a hrefhttp://www.fpdf.org/>fpdf17/a>./p>p>The lichess exporter takes the game id of any game that has been played on the lichess server and produced a PDF output. Take for example, Game 8 of the current World Championship which is a hrefhttps://en.lichess.org/COQChpzH>here/a>. When I open the resulting file, I see this:/p>p>img src/images/blog/serverless-lichess-pdf-exporter-001.png>/p>p>In this blog post I’ll describe how I turned this into a serverless service. The goal is to create:/p>ul>li>Add an endpoint which takes the game id as a parameter/li>li>Run the PHP function via an AWS lambda function/li>li>Return the result as a stream/li>/ul>h2>Prerequisites/h2>p>First check everything we need is installed./p>pre>code>$ serverless --version1.2.1$ node --versionv7.1.0/code>/pre>h2>Initial setup/h2>pre>code>$ mkdir serverless-lichess-to-pdf$ cd serverless-lichess-to-pdf$ sls install --url https://github.com/ZeroSharp/serverless-php/code>/pre>p>Next copy in the source from https://github.com/clarkerubber/lichessPDFExporter./p>p>You can check it works by running the following./p>pre>code>$ php main.php COQChpzH > COQChpzH.pdf/code>/pre>p>What’s going on here? The php binary (from the serverless-php project) is running main.php (from the lichess-pdf-exporter project) with argument code>COQChpzH/code> (which corresponds to a a hrefhttps://en.lichess.org/hsXtkVk8>chess game/a> on the lichess server. The main.php function downloads the game from the lichess API and passes it through the fpdf17 library to create a pdf stream which is written out to the code>COQChpzH.pdf/code> file./p>h2>Lessons learned/h2>p>I learned a few things while trying to get this project working. The basic plan is to modify handler.js so that it return the output of the call described above. Turns out there are quite a few gotchas along the way./p>h2>Lesson 1 - Defining a path parameter/h2>p>I want my API to look like this:/p>pre>code>http://.../serverless-lichess-to-pdf/export/{gameid}/code>/pre>p>I could not find an example in the serverless docs for getting a parameter that is passed in the URL./p>p>Turns out your code>serverless.yml/code> file should look like this:/p>figure classcode>figcaption>span>serverless.yml/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classyaml>span classline>span classl-Scalar-Plain>functions/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>exportToPdf/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>handler/span>span classp-Indicator>:/span> span classl-Scalar-Plain>handler.exportToPdf/span>/span>span classline> span classl-Scalar-Plain>events/span>span classp-Indicator>:/span>/span>span classline> span classp-Indicator>-/span> span classl-Scalar-Plain>http/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>path/span>span classp-Indicator>:/span> span classl-Scalar-Plain>export/{gameid}/span>/span>span classline> span classl-Scalar-Plain>method/span>span classp-Indicator>:/span> span classl-Scalar-Plain>get/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Then, in your handler.js you can retrieve the parameter with:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classjs>span classline>span classnx>module/span>span classp>./span>span classnx>exports/span>span classp>./span>span classnx>exportToPdf/span> span classo>/span> span classp>(/span>span classnx>event/span>span classp>,/span> span classnx>context/span>span classp>,/span> span classnx>callback/span>span classp>)/span> span classo>>/span> span classp>{/span>/span>span classline> span classkd>var/span> span classnx>gameid/span> span classo>/span> span classnx>event/span>span classp>./span>span classnx>pathParameters/span>span classp>./span>span classnx>gameid/span>span classp>;/span>/span>span classline> span classc1>// etc.../span>/span>span classline>span classp>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>/p>h2>Lesson 2 - API Gateway does not support binary data/h2>p>I was hoping I could just do something like this:/p>figure classcode>figcaption>span>handler.js/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>/pre>/td>td classcode>pre>code classjs>span classline>span classc1>// this does NOT work/span>/span>span classline>span classkr>const/span> span classnx>response/span> span classo>/span> span classp>{/span>/span>span classline> span classnx>statusCode/span>span classo>:/span> span classmi>200/span>span classp>,/span>/span>span classline> span classnx>body/span>span classo>:/span> span classnx>outputFromPhpCall/span>span classp>,/span>/span>span classline> span classnx>content/span>span classo>-/span>span classnx>type/span>span classo>:/span> span classs2>"application/pdf"/span>/span>span classline>span classp>};/span>/span>span classline>/span>span classline>span classk>return/span> span classnx>callback/span>span classp>(/span>span classkc>null/span>span classp>,/span> span classnx>response/span>span classp>);/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>At present, you cannot return a binary file. Amazon have just (November 2016) a hrefhttps://aws.amazon.com/blogs/compute/binary-support-for-api-integrations-with-amazon-api-gateway/>released support for binary types in API Gateway/a> but it’s currently a hrefhttps://github.com/serverless/serverless/issues/2797>an open issue/a> in the Serverless Framework./p>h2>Lesson 3 - You can redirect the response to an S3 bucket/h2>p>So instead of returning the binary output, I can write the output to an S3 bucket and return a 302 redirection to the S3 resource. Like this:/p>figure classcode>figcaption>span>handler.js/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>span classline-number>16/span>span classline-number>17/span>span classline-number>18/span>span classline-number>19/span>span classline-number>20/span>span classline-number>21/span>span classline-number>22/span>span classline-number>23/span>span classline-number>24/span>span classline-number>25/span>/pre>/td>td classcode>pre>code classjs>span classline>span classc1>// body contains the output from the PHP call/span>/span>span classline>span classkr>const/span> span classnx>params/span> span classo>/span> span classp>{/span>/span>span classline> span classnx>Bucket/span>span classo>:/span> span classnx>bucket/span>span classp>,/span>/span>span classline> span classnx>Key/span>span classo>:/span> span classnx>key/span>span classp>,/span>/span>span classline> span classnx>ACL/span>span classo>:/span> span classs1>'public-read-write'/span>span classp>,/span>/span>span classline> span classnx>Body/span>span classo>:/span> span classnx>body/span>span classp>,/span>/span>span classline> span classnx>ContentType/span>span classo>:/span> span classs1>'application/pdf'/span>/span>span classline>span classp>};/span>/span>span classline>/span>span classline>span classc1>// Save the pdf file to S3 /span>/span>span classline>span classnx>s3/span>span classp>./span>span classnx>putObject/span>span classp>(/span>span classnx>params/span>span classp>,/span> span classkd>function/span>span classp>(/span>span classnx>err/span>span classp>,/span> span classnx>data/span>span classp>)/span> span classp>{/span>/span>span classline>span classk>if/span> span classp>(/span>span classnx>err/span>span classp>)/span>/span>span classline>span classp>{/span>/span>span classline> span classk>return/span> span classnx>callback/span>span classp>(/span>span classk>new/span> span classnb>Error/span>span classp>(/span>span classerr>`/span>span classnx>Failed/span> span classnx>to/span> span classnx>put/span> span classnx>s3/span> span classnx>object/span>span classo>:/span> span classnx>$/span>span classp>{/span>span classnx>err/span>span classp>}/span>span classerr>`/span>span classp>));/span>/span>span classline>span classp>}/span>/span>span classline>/span>span classline>span classc1>// respond with a 302 redirect to the PDF file/span>/span>span classline>span classkr>const/span> span classnx>response/span> span classo>/span> span classp>{/span>/span>span classline> span classnx>statusCode/span>span classo>:/span> span classmi>302/span>span classp>,/span>/span>span classline> span classnx>headers/span>span classo>:/span> span classp>{/span>/span>span classline> span classnx>location/span> span classo>:/span> span classerr>`/span>span classnx>https/span>span classo>:/span>span classc1>//s3-eu-west-1.amazonaws.com/${bucket}/${key}`/span>/span>span classline> span classp>}/span>/span>span classline>span classp>};/span>/span>span classline>/span>span classline>span classk>return/span> span classnx>callback/span>span classp>(/span>span classkc>null/span>span classp>,/span> span classnx>response/span>span classp>);/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h2>Lesson 4 - You can automatically delete S3 objects after a number of days/h2>p>Each S3 bucket has optional a hrefhttps://docs.aws.amazon.com/AmazonS3/latest/dev/object-lifecycle-mgmt.html>lifecycle rules/a> where you can specify that files are automatically removed after a time period. I wanted to set this up within the code>serverless.yml/code> resources section, but the syntax for the lifecycle rules were not very obvious and I could not find any examples online. The following seems to work:/p>figure classcode>figcaption>span>serverless.yml/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>/pre>/td>td classcode>pre>code classyaml>span classline>span classl-Scalar-Plain>resources/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>Resources/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>PackageStorage/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>Type/span>span classp-Indicator>:/span> span classl-Scalar-Plain>AWS::S3::Bucket/span>/span>span classline> span classl-Scalar-Plain>Properties/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>AccessControl/span>span classp-Indicator>:/span> span classl-Scalar-Plain>PublicRead/span>/span>span classline> span classl-Scalar-Plain>BucketName/span>span classp-Indicator>:/span> span classl-Scalar-Plain>${self:custom.exportToPdfBucket}/span>/span>span classline> span classl-Scalar-Plain>LifecycleConfiguration/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>Rules/span>span classp-Indicator>:/span>/span>span classline> span classp-Indicator>-/span> span classl-Scalar-Plain>ExpirationInDays/span>span classp-Indicator>:/span> span classl-Scalar-Plain>1/span>/span>span classline> span classl-Scalar-Plain>Status/span>span classp-Indicator>:/span> span classl-Scalar-Plain>Enabled/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h2>It’s all working now/h2>p>You can check it out by visiting a hrefhttps://e7tyur4sib.execute-api.eu-west-1.amazonaws.com/dev/export/COQChpzH>this link/a>./p>p>The a hrefhttps://github.com/ZeroSharp/serverless-lichess-to-pdf>source code is on Github/a>./p>p>I also wrote a hrefhttps://chrome.google.com/webstore/detail/lichess-print-friendly-pd/goijhimgdjppmhmjkaglhggoapkgobfg>a Chrome extension/a> which injects the link into the lichess page./p>/div> /article> article> header> h1 classentry-title>a href/the-serverless-framework-and-php/>The Serverless Framework and PHP/a>/h1> p classmeta> time datetime2016-11-21T09:21:00+00:00 pubdate data-updatedtrue>Nov 21span>st/span>, 2016/time> | a href/the-serverless-framework-and-php/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>The goal of this post is to explain how to call a PHP function from within an AWS lambda using the a hrefhttps://serverless.com/>Serverless Framework/a>./p>h2>Prerequisites/h2>p>First check everything we need is installed./p>pre>code>$ serverless --version1.1.0$ node --versionv7.1.0/code>/pre>h2>Install the sample PHP function/h2>p>Install my sample em>Hello/em> function from my github repository./p>pre>code>$ sls install --url https://github.com/ZeroSharp/serverless-php/code>/pre>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classsh>span classline>Serverless: Downloading and installing span classs2>"serverless-php"/span>…/span>span classline>Serverless: Successfully installed span classs2>"serverless-php"/span>./span>/code>/pre>/td>/tr>/table>/div>/figure>h2>The code/h2>pre>code>$ cd serverless-php/code>/pre>p>Let’s have a look at the code>serverless.yml/code> file./p>figure classcode>figcaption>span>serverless.yml/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>/pre>/td>td classcode>pre>code classyaml>span classline>span classl-Scalar-Plain>service/span>span classp-Indicator>:/span> span classl-Scalar-Plain>serverless-php/span>/span>span classline>/span>span classline>span classl-Scalar-Plain>provider/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>name/span>span classp-Indicator>:/span> span classl-Scalar-Plain>aws/span>/span>span classline> span classl-Scalar-Plain>runtime/span>span classp-Indicator>:/span> span classl-Scalar-Plain>nodejs4.3/span>/span>span classline> span classc1># region: eu-west-1/span>/span>span classline>/span>span classline>span classl-Scalar-Plain>functions/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>hello/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>handler/span>span classp-Indicator>:/span> span classl-Scalar-Plain>handler.hello/span>/span>span classline> span classl-Scalar-Plain>events/span>span classp-Indicator>:/span>/span>span classline> span classp-Indicator>-/span> span classl-Scalar-Plain>http/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>path/span>span classp-Indicator>:/span> span classl-Scalar-Plain>hello/span>/span>span classline> span classl-Scalar-Plain>method/span>span classp-Indicator>:/span> span classl-Scalar-Plain>get/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Now look at the php function code>index.php/code> that we’d like our lambda to call./p>figure classcode>figcaption>span>index.php/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>/pre>/td>td classcode>pre>code classphp>span classline>span classcp><?php/span>/span>span classline>/span>span classline>span classc1># $argv will contain the event object. You can output its contents like this if you like/span>/span>span classline>span classc1>#var_export($argv, true);/span>/span>span classline>/span>span classline>span classnb>printf/span>span classp>(/span>span classs1>'Go Serverless v1.0! Your PHP function executed successfully!'/span>span classp>);/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>And the code>handler.js/code> for the hello function looks as follows. It defines a simple lambda which calls the PHP binary, logs any errors and returns the result./p>figure classcode>figcaption>span>handler.js/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>span classline-number>16/span>span classline-number>17/span>span classline-number>18/span>span classline-number>19/span>span classline-number>20/span>span classline-number>21/span>span classline-number>22/span>span classline-number>23/span>span classline-number>24/span>span classline-number>25/span>span classline-number>26/span>span classline-number>27/span>span classline-number>28/span>span classline-number>29/span>span classline-number>30/span>span classline-number>31/span>span classline-number>32/span>span classline-number>33/span>span classline-number>34/span>span classline-number>35/span>span classline-number>36/span>span classline-number>37/span>span classline-number>38/span>span classline-number>39/span>span classline-number>40/span>span classline-number>41/span>span classline-number>42/span>span classline-number>43/span>span classline-number>44/span>/pre>/td>td classcode>pre>code classjs>span classline>span classs1>'use strict'/span>span classp>;/span>/span>span classline>/span>span classline>span classkd>var/span> span classnx>child_process/span> span classo>/span> span classnx>require/span>span classp>(/span>span classs1>'child_process'/span>span classp>);/span>/span>span classline>/span>span classline>span classnx>module/span>span classp>./span>span classnx>exports/span>span classp>./span>span classnx>hello/span> span classo>/span> span classp>(/span>span classnx>event/span>span classp>,/span> span classnx>context/span>span classp>,/span> span classnx>callback/span>span classp>)/span> span classo>>/span> span classp>{/span>/span>span classline>/span>span classline> span classkd>var/span> span classnx>strToReturn/span> span classo>/span> span classs1>''/span>span classp>;/span>/span>span classline>/span>span classline> span classkd>var/span> span classnx>php/span> span classo>/span> span classs1>'./php'/span>span classp>;/span>/span>span classline>/span>span classline> span classc1>// workaround to get 'sls invoke local' to work/span>/span>span classline> span classk>if/span> span classp>(/span>span classk>typeof/span> span classnx>process/span>span classp>./span>span classnx>env/span>span classp>./span>span classnx>PWD/span> span classo>!/span> span classs2>"undefined"/span>span classp>)/span> span classp>{/span>/span>span classline> span classnx>php/span> span classo>/span> span classs1>'php'/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classkd>var/span> span classnx>proc/span> span classo>/span> span classnx>child_process/span>span classp>./span>span classnx>spawn/span>span classp>(/span>span classnx>php/span>span classp>,/span> span classp>/span> span classs2>"index.php"/span>span classp>,/span> span classnx>JSON/span>span classp>./span>span classnx>stringify/span>span classp>(/span>span classnx>event/span>span classp>),/span> span classp>{/span> span classnx>stdio/span>span classo>:/span> span classs1>'inherit'/span> span classp>}/span> span classp>);/span>/span>span classline>/span>span classline> span classnx>proc/span>span classp>./span>span classnx>stdout/span>span classp>./span>span classnx>on/span>span classp>(/span>span classs1>'data'/span>span classp>,/span> span classkd>function/span> span classp>(/span>span classnx>data/span>span classp>)/span> span classp>{/span>/span>span classline> span classkd>var/span> span classnx>dataStr/span> span classo>/span> span classnx>data/span>span classp>./span>span classnx>toString/span>span classp>()/span>/span>span classline> span classc1>// console.log('stdout: ' + dataStr);/span>/span>span classline> span classnx>strToReturn/span> span classo>+/span> span classnx>dataStr/span>/span>span classline> span classp>});/span>/span>span classline>/span>span classline> span classc1>// this ensures any error messages raised by the PHP function end up in the logs/span>/span>span classline> span classnx>proc/span>span classp>./span>span classnx>stderr/span>span classp>./span>span classnx>on/span>span classp>(/span>span classs1>'data'/span>span classp>,/span> span classkd>function/span> span classp>(/span>span classnx>data/span>span classp>)/span> span classp>{/span>/span>span classline> span classnx>console/span>span classp>./span>span classnx>log/span>span classp>(/span>span classerr>`/span>span classnx>stderr/span>span classo>:/span> span classnx>$/span>span classp>{/span>span classnx>data/span>span classp>}/span>span classerr>`/span>span classp>);/span>/span>span classline> span classp>});/span>/span>span classline>/span>span classline> span classnx>proc/span>span classp>./span>span classnx>on/span>span classp>(/span>span classs1>'close'/span>span classp>,/span> span classkd>function/span>span classp>(/span>span classnx>code/span>span classp>)/span> span classp>{/span>/span>span classline> span classk>if/span>span classp>(/span>span classnx>code/span> span classo>!/span> span classmi>0/span>span classp>)/span> span classp>{/span>/span>span classline> span classk>return/span> span classnx>callback/span>span classp>(/span>span classk>new/span> span classnb>Error/span>span classp>(/span>span classerr>`/span>span classnx>Process/span> span classnx>exited/span> span classkd>with/span> span classnx>non/span>span classo>-/span>span classnx>zero/span> span classnx>status/span> span classnx>code/span> span classnx>$/span>span classp>{/span>span classnx>code/span>span classp>}/span>span classerr>`/span>span classp>));/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classkr>const/span> span classnx>response/span> span classo>/span> span classp>{/span>/span>span classline> span classnx>statusCode/span>span classo>:/span> span classmi>200/span>span classp>,/span>/span>span classline> span classnx>body/span>span classo>:/span> span classnx>JSON/span>span classp>./span>span classnx>stringify/span>span classp>({/span>/span>span classline> span classnx>message/span>span classo>:/span> span classnx>strToReturn/span>span classp>,/span>/span>span classline> span classc1>//input: event,/span>/span>span classline> span classp>}),/span>/span>span classline> span classp>};/span>/span>span classline>/span>span classline> span classnx>callback/span>span classp>(/span>span classkc>null/span>span classp>,/span> span classnx>response/span>span classp>);/span>/span>span classline> span classp>});/span>/span>span classline>span classp>};/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Included is the PHP binary to bundle with our serverless function./p>p>(You may need to compile it yourself with different options. See below for help on how to do this.)/p>p>Check it works from your shell./p>pre>code>$ php index.php/code>/pre>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classsh>span classline>Go Serverless v1.0! Your PHP span classk>function /span>executed successfully!/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Run it locally through the Serverless Framework./p>pre>code>$ sls invoke local --function hello/code>/pre>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>/pre>/td>td classcode>pre>code classsh>span classline>Serverless: Your span classk>function /span>ran successfully./span>span classline>/span>span classline>span classo>{/span>/span>span classline> span classs2>"statusCode"/span>: 200,/span>span classline> span classs2>"body"/span>: span classs2>"{\"message\":\"Go Serverless v1.0! Your PHP function executed successfully!\"}"/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Looks good. Let’s deploy./p>pre>code>$ sls deploy/code>/pre>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>span classline-number>16/span>span classline-number>17/span>span classline-number>18/span>/pre>/td>td classcode>pre>code classsh>span classline>Serverless: Packaging service…/span>span classline>Serverless: Uploading CloudFormation file to S3…/span>span classline>Serverless: Uploading service .zip file to S3…/span>span classline>Serverless: Updating Stack…/span>span classline>Serverless: Checking Stack update progress…/span>span classline>........../span>span classline>Serverless: Stack update finished…/span>span classline>/span>span classline>Service Information/span>span classline>service: serverless-php/span>span classline>stage: dev/span>span classline>region: eu-west-1/span>span classline>api keys:/span>span classline> None/span>span classline>endpoints:/span>span classline> GET - https://c1w0hct166.execute-api.eu-west-1.amazonaws.com/dev/hello/span>span classline>functions:/span>span classline> serverless-php-dev-hello: arn:aws:lambda:eu-west-1:962613113552:function:serverless-php-dev-hello/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Run the remote function via Serverless./p>pre>code>$ sls invoke --function hello/code>/pre>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classsh>span classline>span classo>{/span>/span>span classline> span classs2>"statusCode"/span>: 200,/span>span classline> span classs2>"body"/span>: span classs2>"{\"message\":\"Go Serverless v1.0! Your PHP function executed successfully!\",\"input\":{}}"/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Visit the endpoint in your browser./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classjson>span classline>span classp>{/span>/span>span classline> span classnt>"message"/span>span classp>:/span> span classs2>"Go Serverless v1.0! Your PHP function executed successfully!"/span>/span>span classline>span classp>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Nice. It’s all working./p>h2>Rebuilding the PHP binary/h2>p>Depending on the PHP function you need to run, it may be necessary to rebuild the php binary with different flags and dependencies. You can do this best with docker./p>pre>code>$ docker --versionDocker version 1.12.3, build 6b644ec/code>/pre>p>Modify code>dockerfile.buildphp/code> as necessary./p>p>Then run:/p>pre>code>$ sh buildphp.sh/code>/pre>p>This will build a new PHP binary and copy it to the project root. You can immediately deploy for testing with:/p>pre>code>$ sls deploy/code>/pre>h2>Thanks/h2>p>Shout out to a hrefhttps://github.com/dannylinden/aws-lambda-php>Danny Linden/a> whose code got me started on this./p>/div> /article> article> header> h1 classentry-title>a href/smart-hiding-of-the-selection-boxes-in-xaf-web-applications/>Smart Hiding of the Selection Boxes in XAF Web Applications/a>/h1> p classmeta> time datetime2016-11-06T18:39:00+00:00 pubdate data-updatedtrue>Nov 6span>th/span>, 2016/time> | a href/smart-hiding-of-the-selection-boxes-in-xaf-web-applications/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>When an a hrefhttps://www.devexpress.com/products/net/application_framework/>XAF/a> list view has no selection-based actions available, the selection box still appears in the grid. Users get confused. In this post, we’ll look at a workaround./p>h2>The problem/h2>p>In the XAF MainDemo, lets make Departments read-only for the User role./p>figure classcode>figcaption>span>Updater.cs/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classc#>span classline>span classn>userRole/span>span classp>./span>span classn>AddTypePermissionsRecursively/span>span classp></span>span classn>Department/span>span classp>>(/span>span classn>SecurityOperations/span>span classp>./span>span classn>Create/span>span classp>,/span> span classn>SecurityPermissionState/span>span classp>./span>span classn>Deny/span>span classp>);/span>/span>span classline>span classn>userRole/span>span classp>./span>span classn>AddTypePermissionsRecursively/span>span classp></span>span classn>Department/span>span classp>>(/span>span classn>SecurityOperations/span>span classp>./span>span classn>Write/span>span classp>,/span> span classn>SecurityPermissionState/span>span classp>./span>span classn>Deny/span>span classp>);/span>/span>span classline>span classn>userRole/span>span classp>./span>span classn>AddTypePermissionsRecursively/span>span classp></span>span classn>Department/span>span classp>>(/span>span classn>SecurityOperations/span>span classp>./span>span classn>Delete/span>span classp>,/span> span classn>SecurityPermissionState/span>span classp>./span>span classn>Deny/span>span classp>);/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Then start the web application, login as John and navigate to the Departments list view. There is a column selection box, but it serves no purpose. There are no actions that depend on a grid selection./p>p>span classcaption-wrapper>img classcaption src/images/blog/selection-visibility-controller-001.png width height titleWithout the SelectionColumnVisibilityController>span classcaption-text>Without the SelectionColumnVisibilityController/span>/span>/p>h2>The fix/h2>p>Here is a controller which calculates whether there are any available actions which require one or more rows to be selected. If there are none, the selection box will not appear./p>p>Add the following controller to the MainDemo.Module.Web project. It hides the selection box if there are no actions which depend on a grid selection./p>figure classcode>figcaption>span>SelectionColumnVisibilityController.cs/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>span classline-number>16/span>span classline-number>17/span>span classline-number>18/span>span classline-number>19/span>span classline-number>20/span>span classline-number>21/span>span classline-number>22/span>span classline-number>23/span>span classline-number>24/span>span classline-number>25/span>span classline-number>26/span>span classline-number>27/span>span classline-number>28/span>span classline-number>29/span>span classline-number>30/span>span classline-number>31/span>span classline-number>32/span>span classline-number>33/span>span classline-number>34/span>span classline-number>35/span>span classline-number>36/span>span classline-number>37/span>span classline-number>38/span>span classline-number>39/span>span classline-number>40/span>span classline-number>41/span>span classline-number>42/span>span classline-number>43/span>span classline-number>44/span>span classline-number>45/span>span classline-number>46/span>span classline-number>47/span>span classline-number>48/span>span classline-number>49/span>span classline-number>50/span>span classline-number>51/span>span classline-number>52/span>span classline-number>53/span>span classline-number>54/span>span classline-number>55/span>span classline-number>56/span>span classline-number>57/span>span classline-number>58/span>span classline-number>59/span>span classline-number>60/span>span classline-number>61/span>span classline-number>62/span>span classline-number>63/span>span classline-number>64/span>span classline-number>65/span>span classline-number>66/span>span classline-number>67/span>span classline-number>68/span>span classline-number>69/span>span classline-number>70/span>span classline-number>71/span>span classline-number>72/span>span classline-number>73/span>span classline-number>74/span>span classline-number>75/span>span classline-number>76/span>span classline-number>77/span>span classline-number>78/span>span classline-number>79/span>span classline-number>80/span>span classline-number>81/span>span classline-number>82/span>span classline-number>83/span>span classline-number>84/span>span classline-number>85/span>span classline-number>86/span>span classline-number>87/span>span classline-number>88/span>span classline-number>89/span>span classline-number>90/span>span classline-number>91/span>span classline-number>92/span>span classline-number>93/span>span classline-number>94/span>span classline-number>95/span>span classline-number>96/span>span classline-number>97/span>span classline-number>98/span>span classline-number>99/span>span classline-number>100/span>span classline-number>101/span>span classline-number>102/span>span classline-number>103/span>span classline-number>104/span>span classline-number>105/span>span classline-number>106/span>span classline-number>107/span>span classline-number>108/span>span classline-number>109/span>span classline-number>110/span>span classline-number>111/span>span classline-number>112/span>span classline-number>113/span>span classline-number>114/span>span classline-number>115/span>span classline-number>116/span>span classline-number>117/span>span classline-number>118/span>span classline-number>119/span>span classline-number>120/span>span classline-number>121/span>span classline-number>122/span>span classline-number>123/span>span classline-number>124/span>span classline-number>125/span>span classline-number>126/span>span classline-number>127/span>span classline-number>128/span>span classline-number>129/span>span classline-number>130/span>span classline-number>131/span>span classline-number>132/span>span classline-number>133/span>span classline-number>134/span>span classline-number>135/span>span classline-number>136/span>span classline-number>137/span>span classline-number>138/span>span classline-number>139/span>span classline-number>140/span>span classline-number>141/span>/pre>/td>td classcode>pre>code classc#>span classline>span classk>using/span> span classnn>System/span>span classp>;/span>/span>span classline>span classk>using/span> span classnn>DevExpress.ExpressApp/span>span classp>;/span>/span>span classline>span classk>using/span> span classnn>DevExpress.ExpressApp.Actions/span>span classp>;/span>/span>span classline>span classk>using/span> span classnn>DevExpress.ExpressApp.Editors/span>span classp>;/span>/span>span classline>span classk>using/span> span classnn>DevExpress.ExpressApp.SystemModule/span>span classp>;/span>/span>span classline>span classk>using/span> span classnn>DevExpress.Web/span>span classp>;/span>/span>span classline>span classk>using/span> span classnn>System.Linq/span>span classp>;/span>/span>span classline>/span>span classline>span classk>namespace/span> span classnn>MainDemo.Module.Web.Controllers/span>/span>span classline>span classp>{/span>/span>span classline> span classk>public/span> span classk>class/span> span classnc>SelectionColumnVisibilityController/span> span classp>:/span> span classn>ViewController/span>/span>span classline> span classp>{/span>/span>span classline> span classk>public/span> span classnf>SelectionColumnVisibilityController/span>span classp>()/span>/span>span classline> span classp>{/span>/span>span classline> span classn>TargetViewType/span> span classp>/span> span classn>ViewType/span>span classp>./span>span classn>ListView/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>private/span> span classkt>bool/span> span classnf>IsSelectionColumnVisible/span>span classp>()/span>/span>span classline> span classp>{/span>/span>span classline> span classkt>bool/span> span classn>isSelectionColumnRequired/span> span classp>/span> span classk>false/span>span classp>;/span>/span>span classline> span classc1>// remove checkbox if there are no available actions/span>/span>span classline> span classk>foreach/span> span classp>(/span>span classn>Controller/span> span classn>controller/span> span classk>in/span> span classn>Frame/span>span classp>./span>span classn>Controllers/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(!/span>span classn>controller/span>span classp>./span>span classn>Active/span>span classp>)/span>/span>span classline> span classk>continue/span>span classp>;/span>/span>span classline>/span>span classline> span classk>if/span> span classp>(/span>span classn>controller/span>span classp>./span>span classn>Actions/span>span classp>./span>span classn>Count/span> span classp>/span> span classm>0/span>span classp>)/span>/span>span classline> span classk>continue/span>span classp>;/span>/span>span classline>/span>span classline> span classkt>bool/span> span classn>allowEdit/span> span classp>/span> span classk>true/span>span classp>;/span>/span>span classline> span classk>if/span> span classp>((/span>span classn>Frame/span> span classk>is/span> span classn>NestedFrame/span>span classp>)/span> span classp>&&/span> span classp>(((/span>span classn>NestedFrame/span>span classp>)/span>span classn>Frame/span>span classp>)./span>span classn>ViewItem/span> span classk>is/span> span classn>PropertyEditor/span>span classp>))/span>/span>span classline> span classn>allowEdit/span> span classp>/span> span classp>(/span>span classkt>bool/span>span classp>)((/span>span classn>PropertyEditor/span>span classp>)((/span>span classn>NestedFrame/span>span classp>)/span>span classn>Frame/span>span classp>)./span>span classn>ViewItem/span>span classp>)./span>span classn>AllowEdit/span>span classp>;/span>/span>span classline>/span>span classline> span classk>foreach/span> span classp>(/span>span classn>ActionBase/span> span classn>action/span> span classk>in/span> span classn>controller/span>span classp>./span>span classn>Actions/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>action/span>span classp>./span>span classn>SelectionDependencyType/span> span classp>/span> span classn>SelectionDependencyType/span>span classp>./span>span classn>RequireMultipleObjects/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>action/span>span classp>./span>span classn>Active/span> span classp>||/span> span classn>IsActionInactiveBySelectionContext/span>span classp>(/span>span classn>action/span>span classp>))/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>action/span>span classp>./span>span classn>Enabled/span> span classp>||/span> span classn>IsActionDisabledBySelectionContext/span>span classp>(/span>span classn>action/span>span classp>))/span>/span>span classline> span classp>{/span>/span>span classline> span classn>isSelectionColumnRequired/span> span classp>/span> span classk>true/span>span classp>;/span>/span>span classline> span classk>break/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>isSelectionColumnRequired/span>span classp>)/span>/span>span classline> span classk>break/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classk>return/span> span classn>isSelectionColumnRequired/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>private/span> span classkt>bool/span> span classnf>IsActionInactiveBySelectionContext/span>span classp>(/span>span classn>ActionBase/span> span classn>action/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>action/span>span classp>./span>span classn>Active/span>span classp>)/span>/span>span classline> span classk>return/span> span classk>true/span>span classp>;/span>/span>span classline> span classk>else/span>/span>span classline> span classp>{/span>/span>span classline> span classk>foreach/span> span classp>(/span>span classkt>string/span> span classn>item/span> span classk>in/span> span classn>action/span>span classp>./span>span classn>Active/span>span classp>./span>span classn>GetKeys/span>span classp>())/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>item/span> span classp>/span> span classn>ActionBase/span>span classp>./span>span classn>RequireMultipleObjectsContext/span> span classp>||/span> span classn>item/span> span classp>/span> span classn>ActionBase/span>span classp>./span>span classn>RequireSingleObjectContext/span>span classp>)/span>/span>span classline> span classk>continue/span>span classp>;/span>/span>span classline> span classk>if/span> span classp>(!/span>span classn>action/span>span classp>./span>span classn>Active/span>span classp>/span>span classn>item/span>span classp>)/span>/span>span classline> span classk>return/span> span classk>false/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classk>return/span> span classk>true/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>private/span> span classkt>bool/span> span classnf>IsActionDisabledBySelectionContext/span>span classp>(/span>span classn>ActionBase/span> span classn>action/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>action/span>span classp>./span>span classn>Enabled/span>span classp>)/span>/span>span classline> span classk>return/span> span classk>true/span>span classp>;/span>/span>span classline> span classk>else/span>/span>span classline> span classp>{/span>/span>span classline> span classk>foreach/span> span classp>(/span>span classkt>string/span> span classn>item/span> span classk>in/span> span classn>action/span>span classp>./span>span classn>Enabled/span>span classp>./span>span classn>GetKeys/span>span classp>())/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>item/span> span classp>/span> span classn>ActionBase/span>span classp>./span>span classn>RequireMultipleObjectsContext/span> span classp>||/span>/span>span classline> span classn>item/span> span classp>/span> span classn>ActionBase/span>span classp>./span>span classn>RequireSingleObjectContext/span> span classp>||/span>/span>span classline> span classn>item/span> span classp>/span> span classn>ActionsCriteriaViewController/span>span classp>./span>span classn>EnabledByCriteriaKey/span>span classp>)/span>/span>span classline> span classk>continue/span>span classp>;/span>/span>span classline> span classk>if/span> span classp>(!/span>span classn>action/span>span classp>./span>span classn>Enabled/span>span classp>/span>span classn>item/span>span classp>)/span>/span>span classline> span classk>return/span> span classk>false/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classk>return/span> span classk>true/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>protected/span> span classk>override/span> span classk>void/span> span classnf>OnViewControlsCreated/span>span classp>()/span>/span>span classline> span classp>{/span>/span>span classline> span classk>base/span>span classp>./span>span classn>OnViewControlsCreated/span>span classp>();/span>/span>span classline> span classn>ASPxGridView/span> span classn>grid/span> span classp>/span> span classp>((/span>span classn>ListView/span>span classp>)/span>span classk>this/span>span classp>./span>span classn>View/span>span classp>)./span>span classn>Editor/span>span classp>./span>span classn>Control/span> span classk>as/span> span classn>ASPxGridView/span>span classp>;/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>grid/span> span classp>!/span> span classk>null/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classn>grid/span>span classp>./span>span classn>Load/span> span classp>+/span> span classn>grid_Load/span>span classp>;/span>/span>span classline> span classn>grid/span>span classp>./span>span classn>DataBound/span> span classp>+/span> span classn>grid_DataBound/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>protected/span> span classk>override/span> span classk>void/span> span classnf>OnDeactivated/span>span classp>()/span>/span>span classline> span classp>{/span>/span>span classline> span classk>base/span>span classp>./span>span classn>OnDeactivated/span>span classp>();/span>/span>span classline> span classn>ASPxGridView/span> span classn>grid/span> span classp>/span> span classp>((/span>span classn>ListView/span>span classp>)/span>span classk>this/span>span classp>./span>span classn>View/span>span classp>)./span>span classn>Editor/span>span classp>./span>span classn>Control/span> span classk>as/span> span classn>ASPxGridView/span>span classp>;/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>grid/span> span classp>!/span> span classk>null/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classn>grid/span>span classp>./span>span classn>DataBound/span> span classp>-/span> span classn>grid_DataBound/span>span classp>;/span>/span>span classline> span classn>grid/span>span classp>./span>span classn>Load/span> span classp>-/span> span classn>grid_Load/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>void/span> span classnf>grid_Load/span>span classp>(/span>span classkt>object/span> span classn>sender/span>span classp>,/span> span classn>EventArgs/span> span classn>e/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classn>SetSelectionColumnVisibility/span>span classp>(/span>span classn>sender/span>span classp>,/span> span classn>e/span>span classp>);/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>void/span> span classnf>grid_DataBound/span>span classp>(/span>span classkt>object/span> span classn>sender/span>span classp>,/span> span classn>EventArgs/span> span classn>e/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classn>SetSelectionColumnVisibility/span>span classp>(/span>span classn>sender/span>span classp>,/span> span classn>e/span>span classp>);/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>private/span> span classk>void/span> span classnf>SetSelectionColumnVisibility/span>span classp>(/span>span classkt>object/span> span classn>sender/span>span classp>,/span> span classn>EventArgs/span> span classn>e/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classkt>bool/span> span classn>isSelectionColumnVisible/span> span classp>/span> span classn>IsSelectionColumnVisible/span>span classp>();/span>/span>span classline> span classk>if/span> span classp>(!/span>span classn>isSelectionColumnVisible/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classkt>var/span> span classn>grid/span> span classp>/span> span classp>(/span>span classn>ASPxGridView/span>span classp>)/span>span classn>sender/span>span classp>;/span>/span>span classline> span classkt>var/span> span classn>selectionBoxColumn/span> span classp>/span>/span>span classline> span classn>grid/span>span classp>./span>span classn>Columns/span>/span>span classline> span classp>./span>span classn>OfType/span>span classp></span>span classn>GridViewCommandColumn/span>span classp>>()/span>/span>span classline> span classp>./span>span classn>Where/span>span classp>(/span>span classn>x/span> span classp>>/span> span classn>x/span>span classp>./span>span classn>ShowSelectCheckbox/span>span classp>)/span>/span>span classline> span classp>./span>span classn>FirstOrDefault/span>span classp>();/span>/span>span classline>/span>span classline> span classk>if/span> span classp>(/span>span classn>selectionBoxColumn/span> span classp>!/span> span classk>null/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classn>selectionBoxColumn/span>span classp>./span>span classn>Visible/span> span classp>/span> span classk>false/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline>span classp>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Run the application again and see the difference. Now the grid looks like this. Notice, there is no longer a selection box on the row./p>p>img src/images/blog/selection-visibility-controller-002.png titleWith the SelectionColumnVisibilityController >/p>p>By the way, this is how it looks with old-style XAF web apps./p>p>span classcaption-wrapper>img classcaption src/images/blog/selection-visibility-controller-003.png width height titleWithout the SelectionColumnVisibilityController>span classcaption-text>Without the SelectionColumnVisibilityController/span>/span>/p>p>span classcaption-wrapper>img classcaption src/images/blog/selection-visibility-controller-004.png width height titleWith the SelectionColumnVisibilityController>span classcaption-text>With the SelectionColumnVisibilityController/span>/span>/p>/div> /article> article> header> h1 classentry-title>a href/sometimes-youve-just-got-to-deploy/>Sometimes You’ve Just Got to Deploy/a>/h1> p classmeta> time datetime2016-10-16T18:44:00+01:00 pubdate data-updatedtrue>Oct 16span>th/span>, 2016/time> | a href/sometimes-youve-just-got-to-deploy/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>Sometimes the deadline has arrived and you still have some failing tests. After a discussion with the dev team, you decide to deploy anyway and fix the bugs for the next release. You need to get the build server to ignore the tests./p>p>One way is just to mark the test with the code>Ignore/code> attribute./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>/pre>/td>td classcode>pre>code classc#>span classline>span classna>Test/span>/span>span classline>span classna>Ignore/span> span classc1>// TODO: Fix this test before the next release!/span>/span>span classline>span classk>public/span> span classk>void/span> span classnf>Test/span>span classp>()/span>/span>span classline>span classp>{/span>/span>span classline> span classc1>// Some failing test code.../span>/span>span classline>span classp>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>After the weekend, everyone forgets about the ignored tests and they never get fixed./p>p>Instead, I like to do this./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classc#>span classline>span classna>Test/span>/span>span classline>span classk>public/span> span classk>void/span> span classnf>Test/span>span classp>()/span>/span>span classline>span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>DateTime/span>span classp>./span>span classn>Now/span> span classp></span> span classk>new/span> span classn>DateTime/span>span classp>(/span>span classm>2016/span>span classp>,/span> span classm>10/span>span classp>,/span> span classm>17/span>span classp>))/span>/span>span classline> span classn>Assert/span>span classp>./span>span classn>Ignore/span>span classp>(/span>span classs>"Temporarily ignored until October 17."/span>span classp>);/span>/span>span classline> span classc1>// Some failing test code.../span>/span>span classline>span classp>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This is a fairly rare occurrence for my team, so the above approach is sufficient and works with all test frameworks. But if you want to go further a hrefhttps://www.amido.com/code/conditional-ignore-nunit-and-the-ability-to-conditionally-ignore-a-test/>Richard Slater shows how to create an NUnit attribute/a>./p>/div> /article> div classpagination> a classprev href/blog/page/2/>← Older/a> a href/blog/archives>Blog Archives/a> /div>/div>aside classsidebar> /aside> /div> /div> footer rolecontentinfo>p> Copyright © 2018 - Robert Anderson span classcredit>Powered by a hrefhttp://octopress.org>Octopress/a>/span>/p>/footer> script typetext/javascript> var disqus_shortname zerosharp; var disqus_script count.js; (function () { var dsq document.createElement(script); dsq.type text/javascript; dsq.async true; dsq.src http:// + disqus_shortname + .disqus.com/ + disqus_script; (document.getElementsByTagName(head)0 || document.getElementsByTagName(body)0).appendChild(dsq); }());/script>div idfb-root>/div>script>(function(d, s, id) { var js, fjs d.getElementsByTagName(s)0; if (d.getElementById(id)) {return;} js d.createElement(s); js.id id; js.src //connect.facebook.net/en_US/all.js#appId212934732101925&xfbml1; fjs.parentNode.insertBefore(js, fjs);}(document, script, facebook-jssdk));/script> script typetext/javascript> (function() { var script document.createElement(script); script.type text/javascript; script.async true; script.src https://apis.google.com/js/plusone.js; var s document.getElementsByTagName(script)0; s.parentNode.insertBefore(script, s); })(); /script> script typetext/javascript> (function(){ var twitterWidgets document.createElement(script); twitterWidgets.type text/javascript; twitterWidgets.async true; twitterWidgets.src http://platform.twitter.com/widgets.js; document.getElementsByTagName(head)0.appendChild(twitterWidgets); })(); /script>/body>/html>
Port 443
HTTP/1.1 200 OKConnection: keep-aliveContent-Length: 99369Server: GitHub.comContent-Type: text/html; charsetutf-8Last-Modified: Sun, 04 Nov 2018 21:09:23 GMTAccess-Control-Allow-Origin: *ETag: 5bdf6003-18429expires: Sun, 06 Oct 2024 01:28:48 GMTCache-Control: max-age600x-proxy-cache: MISSX-GitHub-Request-Id: 1893:3FD743:21A5375:22ABE52:6701E577Accept-Ranges: bytesAge: 0Date: Sun, 06 Oct 2024 01:18:48 GMTVia: 1.1 varnishX-Served-By: cache-bfi-kbfi7400098-BFIX-Cache: MISSX-Cache-Hits: 0X-Timer: S1728177529.800944,VS0,VE95Vary: Accept-EncodingX-Fastly-Request-ID: 776d8424a0118aa21f595a441d7953e126db277d !DOCTYPE html>!--if IEMobile 7 >html classno-js iem7>!endif-->!--if lt IE 9>html classno-js lte-ie8>!endif-->!--if (gt IE 8)|(gt IEMobile 7)|!(IEMobile)|!(IE)>!-->html classno-js langen>!--!endif-->head> meta charsetutf-8> title>ZeroSharp/title> meta nameauthor contentRobert Anderson> meta namedescription contentTomorrow could be an exciting moment in the history of maths. Sir Michael Atiyah is presenting a proof of the Riemann Hypothesis at the Heidelberg …> !-- http://t.co/dKP3o1e --> meta nameHandheldFriendly contentTrue> meta nameMobileOptimized content320> meta nameviewport contentwidthdevice-width, initial-scale1> link relcanonical hrefhttp://ZeroSharp.github.com/> link href/favicon.png relicon> link href/stylesheets/screen.css mediascreen, projection relstylesheet typetext/css> script src/javascripts/modernizr-2.0.js>/script> script src/javascripts/ender.js>/script> script src/javascripts/octopress.js typetext/javascript>/script> link hrefhttp://feeds.feedburner.com/zerosharp relalternate titleZeroSharp typeapplication/atom+xml> !--Fonts from Googles Web font directory at http://google.com/webfonts -->link hrefhttp://fonts.googleapis.com/css?familyPT+Serif:regular,italic,bold,bolditalic relstylesheet typetext/css>link hrefhttp://fonts.googleapis.com/css?familyPT+Sans:regular,italic,bold,bolditalic relstylesheet typetext/css> !-- ra+> -->link hrefhttp://fonts.googleapis.com/css?familyUbuntu:500 relstylesheet typetext/css>link hrefhttp://fonts.googleapis.com/css?familyOpen+Sans relstylesheet typetext/css>link hrefhttp://fonts.googleapis.com/css?familyInconsolata relstylesheet typetext/css>link href/stylesheets/custom/data-table.css mediascreen, projection relstylesheet typetext/css>!-- /ra+> --> script typetext/javascript> var _gaq _gaq || ; _gaq.push(_setAccount, UA-30564687-1); _gaq.push(_trackPageview); (function() { var ga document.createElement(script); ga.type text/javascript; ga.async true; ga.src (https: document.location.protocol ? https://ssl : http://www) + .google-analytics.com/ga.js; var s document.getElementsByTagName(script)0; s.parentNode.insertBefore(ga, s); })(); /script>/head>body classcollapse-sidebar sidebar-footer > header rolebanner>hgroup> !--h1>a href/>ZeroSharp/a>/h1>--> a hrefhttp://www.zerosharp.com/>h1>ZeroSharp/h1>/a> h2>Robert Andersons ones and zeros/h2> /hgroup>/header> nav rolenavigation> form actionhttp://google.com/search methodget> fieldset rolesearch> input typehidden nameq valuesite:ZeroSharp.github.com /> input classsearch typetext nameq results0 placeholderSearch/> /fieldset>/form>ul classmain-navigation> li>a href/>Blog/a>/li> li>a href/blog/archives>Archives/a>/li> li>a href/about/>About/a>/li> li>a href/license/>License/a>/li> /ul>ul classsubscription> li>a relme hrefhttps://plus.google.com/112685056596124127572?relauthor> img src/images/asides/googleplus.png width24 height24 altRob on Google+> /a>/li> li>a relme hrefhttp://twitter.com/8ctopus> img src/images/asides/twitter.png width24 height24 altRob on Twitter /> /a>/li> !--li>a relme hrefhttp://stackoverflow.com/users/1077279/shamp00> img src/images/asides/stackoverflow.png width24 height24 altRob on StackOverflow /> /a>/li> li>a relme hrefhttps://github.com/zerosharp> img src/images/asides/github.png width24 height24 altRob on GitHub /> /a>/li> li>a relme hrefhttp://www.linkedin.com/profile/view?id926740 class googleplus-hidden > img src/images/asides/linkedin.png width24 height24 altRob on LinkedIn /> /a>/li> li>a relme hrefhttp://springpad.com/#!/shamp00 class googleplus-hidden > img src/images/asides/springpad.png width24 height24 altRob on SpringPad /> /a>/li> li>a relme hrefhttp://pinterest.com/shamp00 class googleplus-hidden > img src/images/asides/pinterest.png width24 height24 altRob on Pinterest /> /a>/li> li>a relme hrefhttp://www.last.fm/user/nosredna class googleplus-hidden > img src/images/asides/lastfm.png width24 height24 altRob on Last.fm /> /a>/li>--> li>a hrefhttp://feeds.feedburner.com/zerosharp> img src/images/asides/rss.png relsubscribe-rss width24 height24 altRSS Feed /> /a>/li>/ul>/nav> div idmain> div idcontent> div classblog-index> article> header> h1 classentry-title>a href/has-the-riemann-hypothesis-been-proved/>Has the Riemann Hypothesis Been Proved?/a>/h1> p classmeta> time datetime2018-09-23T08:35:00+01:00 pubdate data-updatedtrue>Sep 23span>rd/span>, 2018/time> | a href/has-the-riemann-hypothesis-been-proved/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>img classright src/images/blog/has-the-riemann-hypothesis-been-proved-michael-atiyah.jpg titleBy Tugsataydin CC BY-SA 4.0 from Wikimedia Commons >Tomorrow could be an exciting moment in the history of maths. a hrefhttps://en.wikipedia.org/wiki/Michael_Atiyah>Sir Michael Atiyah/a> is presenting a proof of the Riemann Hypothesis at the Heidelberg Laureate Forum which will be available on a hrefhttps://www.youtube.com/user/LaureateForum>their youtube channel/a>. There is a good angle by Ken Regan on the a hrefhttps://rjlipton.wordpress.com/2018/09/21/the-specter-of-simpler-proofs/>Gödel’s Lost Letter blog/a>./p>p>The Riemann Hypothesis is one of the most important unsolved problems in mathematics and the subject of one of my favourite books about maths: a hrefhttps://www.amazon.com/Prime-Obsession-Bernhard-Greatest-Mathematics/dp/0452285259>Prime Obsession/a>./p>p>A few years ago in Paris, I had the pleasure of seeing a href/an-afternoon-with-two-fields-medallists>Sir Michael speak/a>. He spoke so cheerfully about life and mathematics. There is a great interview with him on the a hrefhttps://www.youtube.com/playlist?listPLVV0r6CmEsFzjttuP9WTFDzu0oAOJBM_3>Web of Stories/a> YouTube channel./p>/div> /article> article> header> h1 classentry-title>a href/my-essential-web-applications/>My Essential Web Applications and iPhone Apps/a>/h1> p classmeta> time datetime2018-09-18T09:27:00+01:00 pubdate data-updatedtrue>Sep 18span>th/span>, 2018/time> | a href/my-essential-web-applications/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>This is part three of a series of posts about the software and tools I find invaluable. See a href/essential-applications>Part 1: essential applications/a> and a href/my-essential-visual-studio-tools-and-extensions>Part 2: Visual Studio tools/a>. In this post I’m covering the online applications and iPhone apps I find indispensible./p>h2>a hrefhttps://www.google.com/gmail/>Gmail/a>/h2>p>Does the job./p>h2>a hrefhttps://www.lastpass.com/>Lastpass/a>/h2>p>Everyone needs a password manager./p>h2>a hrefhttps://www.pinboard.in>Pinboard/a> (and the a hrefhttps://pinswiftapp.com/>PinSwift/a> iPhone app)/h2>p>The best bookmark tracking tool. Simple, fast, powerful. The best mobile app for it is a hrefhttps://pinswiftapp.com/>PinSwift/a>./p>h2>a hrefhttps://bear.app/>Bear/a>/h2>p>A very pretty MarkDown editor for Mac and iPhone. I use a hrefhttps://bear.app/>Bear/a> for all my notes./p>h2>a hrefhttps://www.google.com/drive/download/>Google Drive File Stream/a>/h2>p>Since I use a hrefhttps://gsuite.google.com/>GSuite/a>, it makes sense to try to put everything there. Google Drive has improved enormously since they moved to a file streaming approach./p>h2>a hrefhttps://mail.google.com/tasks/canvas>Google Tasks/a> (and the a hrefgotasksapp.com/>GoTasks/a> app)/h2>p>I need simple task manager with support for multiple lists, hierarchies and available everywhere. Google Tasks is often overlooked in this regard. Check out the a hrefhttps://mail.google.com/tasks/canvas>Google Tasks canvas/a>. There is also a fantastic free iPhone app for it a hrefhttp://gotasksapp.com/>GoTasks/a>./p>h2>a hrefhttps://feedly.com/>Feedly/a>/h2>p>a hrefhttps://feedly.com/>Feedly/a> is the best RSS news feed reader, in my opinion. I keep up with a few development blogs, a few science blogs and the blogs of my friends. The mobile app is great too./p>h2>a hrefhttps://www.xero.com/>Xero/a>/h2>p>I’ve been using a hrefhttps://www.xero.com/>Xero/a> for eight years now. Business accounting software done right./p>h2>a hrefhttps://www.amazon.com/kindle-dbs/fd/kcp>Kindle/a>/h2>p>I like real books but don’t always lug them about with me, so often I buy both the hard copy and the kindle version (there shoudl be some sort of clever discount for this…). The Kindle app is where I spend my time when I have no connectivity (the London tube, airplanes, etc.)/p>h2>a hrefhttps://chess.com>Chess.com/a> and a hrefhttps://lichess.com>Lichess.com/a>/h2>p>I waste hours playing online blitz chess. I’ve even written a couple of Chrome extensions: a hrefhttps://chrome.google.com/webstore/detail/lichess-print-friendly-pd/goijhimgdjppmhmjkaglhggoapkgobfg>Pretty print your games/a> and a hrefhttps://chrome.google.com/webstore/detail/chesscom-v3-analysis/bhjlkimpkkgkmfjlcfngmakenalgleap>Analyse any chess.com game with lichess/a>./p>p>Chess is a mascohistic, character-building pastime. Progress is elusive. You play a couple of good games and you think you’re improving and then you get thrashed repeatedly by a 10 year old./p>/div> /article> article> header> h1 classentry-title>a href/my-essential-visual-studio-tools-and-extensions/>My Essential Visual Studio Tools and Extensions/a>/h1> p classmeta> time datetime2018-09-10T15:45:00+01:00 pubdate data-updatedtrue>Sep 10span>th/span>, 2018/time> | a href/my-essential-visual-studio-tools-and-extensions/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>This is part two of a series of posts about the software and tools I find invaluable. See a href/essential-applications>part 1/a> and a href/my-essential-web-applications>part 3/a>./p>h2>CodeRush/h2>p>I’ve been using DevExpress a hrefhttps://www.devexpress.com/products/coderush/>CodeRush/a> since 2005. Check out a hrefhttps://youtu.be/v5-MVSoqCnU>this video tutorial/a> for a lightening tour of a lot of the features, and look at the DevExpress youtube channel for a hrefhttps://www.youtube.com/playlist?listPL8h4jt35t1wgawacCN9wmxq1EN36CNUGk>a load of other tutorials/a>./p>h2>NCrunch/h2>p>a hrefhttps://www.ncrunch.net/>NCrunch/a> provides continuous testing for Visual Studio. When I make any change to my code which breaks a unit test, the NCrunch risk status goes red a few seconds later, even without recompiling. I get immediate feedback for any breaking change, so long as I have a test for it. Not only does it encourages me and my team to write good tests, but it allows us to make new changes andrefactor with confidence./p>p>img src/images/blog/ncrunch-progress-bar.png>/p>h2>Redgate .NET Reflector Developer Bundle/h2>p>When the going gets tough, the a hrefhttps://www.red-gate.com/products/dotnet-development/ants-performance-profiler/index>ANTS Performance Profiler/a> and a hrefhttps://www.red-gate.com/products/dotnet-development/ants-memory-profiler/index>ANTS Memory Profiler/a> have helped me find some of the hardest bugs I’ve come across./p>p>Also, while there are several good .NET decompilers, many of them free, I got used to a hrefhttps://www.red-gate.com/products/dotnet-development/reflector/index>.NET Reflector/a> which comes part of this bundle./p>h2>T4/h2>p>I use code generation to automatically generate templates for unit tests for validation rules and a hrefhttps://docs.microsoft.com/en-us/visualstudio/modeling/code-generation-and-t4-text-templates?viewvs-2017>T4/a> and the a hrefhttps://marketplace.visualstudio.com/items?itemNameOlegVSych.T4ToolboxforVisualStudio2017>T4 Toolbox/a> fit the bill nicely./p>p>For a more advanced use case, see my post about automatically a href/making-xaf-reports-even-better-part-1/>converting DevExpress v1 report scripts/a> to check for compilation errors and allow for unit testing of report scripts./p>h2>AWS Toolkit/h2>p>I always install the a hrefhttps://aws.amazon.com/visualstudio/>Amazon Web Services Toolkit/a> to make it easy to spin up test servers in the Amazon cloud./p>h2>Next up/h2>p>My a href/my-essential-web-applications>essential web applications and iPhone apps/a>./p>/div> /article> article> header> h1 classentry-title>a href/essential-applications/>My Essential Applications/a>/h1> p classmeta> time datetime2018-09-07T15:23:00+01:00 pubdate data-updatedtrue>Sep 7span>th/span>, 2018/time> | a href/essential-applications/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>This is the first in a series of posts where I list the applications that I use and enjoy the most. See a href(/my-essential-visual-studio-tools-and-extensions>part 2/a>) and a href/my-essential-web-applications>part 3/a>./p>p>A bit of preamble, my most powerful machine is a Windows-only desktop with lots of RAM and an SSD drive. I use it almost exclusively for development./p>p>I also have a Macbook Pro which is configured to dual-boot Windows and MacOS. The Windows machine is more or less a mirror of my main development machine. The Mac is where I do all my document editing, Word, blogging, etc. I also use it for my occasional forays in to iPhone development or other non-Windows experiments./p>p>When I upgrade my development machine, I reconfigure the previous system for Linux, currently Ubuntu./p>h2>Chocolatey/h2>p>In Windows, a hrefChocolatey%20-%20The%20package%20manager%20for%20Windows>Chocolatey/a> is a very convenient way to install programs. Just go:/p>pre>code>C:> choco install nodejs/code>/pre>h2>Boxstarter/h2>p>Even better, create a powershell script with all the applications you want to install and run it with a hrefhttps://boxstarter.org/>boxstarter/a>. Repeatable and reboot-resilient environment installations using chocolatey under the hood. For several years now, I have maintained a script for installing my entire development environment (and the build server) from scratch. Works whether it’s a physical or a virtual machine./p>h2>BeyondCompare/h2>p>a hrefhttps://www.scootersoftware.com/>BeyondCompare/a> is the best file-comparison tool I’ve found. Cross-platform too, I have it installed on my Mac as well./p>h2>Synergy/h2>p>a hrefhttps://symless.com/synergy>Synergy/a> allows me to share one mouse and keyboard across all my machines. It works just like dual monitors, except when the mouse moves onto the next screen, you’ve actually changed computer. I don’t have multiple monitors any more, I just switch the input on my giant a hrefhttps://www.dell.com/en-us/shop/dell-ultrasharp-34-curved-monitor-u3417w/apd/210-aiyz/monitors-monitor-accessories>curved 34” Dell monitor/a> via a keyboard shortcut./p>h2>7Zip/h2>p>Nothing to say./p>h2>VS Code/h2>p>First class support for .NET and C#, Typescript in particular, but a hrefhttps://code.visualstudio.com/>VS Code/a> is also extremely good with Javascript, Powershell, Python, Markdown, etc. Multiple cursor support. Cross-platform. Extensions. I’m writing this blog post in VS Code./p>h2>Visual Studio/h2>p>My daily workhorse. I’ve spent more screen time here than anywhere./p>h2>Zotero/h2>p>Keep track of academic papers. Download them for offline reading. Handle citations and bibliographies effortlessly from within Word. a hrefhttps://www.zotero.org/>Zotero/a>./p>h2>Next up/h2>p>More on Visual Studio in the a href/my-essential-visual-studio-tools-and-extensions>next post/a> where I go through my essential extensions and tools./p>/div> /article> article> header> h1 classentry-title>a href/macbook-and-the-mysterious-sleep/>Macbook and the Mysterious Sleep/a>/h1> p classmeta> time datetime2017-08-23T16:46:00+01:00 pubdate data-updatedtrue>Aug 23span>rd/span>, 2017/time> | a href/macbook-and-the-mysterious-sleep/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>I finally worked out why my Macbook was randomly sleeping./p>p>strong>TL;DR/strong> - a href#anchor-tldr>Skip to the end/a>./p>h2>Clues/h2>p>It only seemed to happen when I was working while sitting up on the bed with the computer on my lap. It seemed to be related to the position of the computer or possibly the lid. The computer would sleep. I’d wake it and login again. Continue. Sometimes it would happen once. Sometimes three times in ten minutes. Annoying. I assumed some hardware defect./p>h2>Pajamas/h2>p>Then over several days I cracked it. I realised it never happened when I was wearing pajamas. Very strange./p>h2>Reflections/h2>p>I started thinking about what normally triggers sleep mode. Closing the lid. How does a Macbook know the lid is closed. There’s not really a clasp or anything so it must be a magnet. Perhaps it’s getting confused by my belt buckle or something. My phone?/p>p>No, my phone em>case/em>! The flip-case of my phone has a magnet to keep the flap closed. In my jeans pocket it’s near enough to make the laptop think the lid has been closed. Duh./p>h2>a nameanchor-tldr>/a>TL;DR/h2>p>Take your mobile phone out of your pocket!/p>/div> /article> article> header> h1 classentry-title>a href/improvements-to-serverless-php-support/>Improvements to Serverless PHP Support/a>/h1> p classmeta> time datetime2017-03-02T11:37:00+00:00 pubdate data-updatedtrue>Mar 2span>nd/span>, 2017/time> | a href/improvements-to-serverless-php-support/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>I was inspired by two events to jump back into serverless framework./p>p>img classleft src/images/blog/serverless-php-improvements-001.jpeg width200 titleServerless London Meetup >/p>p>Firstly, I attended the second a hrefhttps://www.meetup.com/Serverless-London/>London serverless meetup/a> yesterday evening which was excellent and showed just how much enthusiasm there is for serverless architectures. Check out their new logo on the left. It was significant that each of the three speakers announced that they are actively hiring serverless developers./p>p>Secondly, a hrefhttps://github.com/Stolz>Stolz/a> has contributed improvements to my sample project for integrating PHP into the serverless framework. It’s the purpose of this blog post to cover the changes./p>p>The trick to getting AWS lambda to support PHP is to bundle in a PHP binary so that nodejs can call it with code>child_process.spawn()/code>. In a href/the-serverless-framework-and-php/>my first implementation/a>, I used an Ubuntu docker base image to compile and produce the php binary. Unfortunately, this is not identical to the container that AWS Lambda uses and so sometimes the logs would contain errors such as:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>/pre>/td>td classcode>pre>code classsh>span classline>START RequestId: 728dcddf-feaa-11e6-8346-2125e1c055d7 Version: span classnv>$LATEST/span>/span>span classline>2017-03-01 18:11:10.455 span classo>(/span>+00:00span classo>)/span> 728dcddf-feaa-11e6-8346-2125e1c055d7 stderr: ./php: /usr/lib64/libcurl.so.4: no version information available span classo>(/span>required by ./phpspan classo>)/span>/span>span classline>/span>span classline>END RequestId: 728dcddf-feaa-11e6-8346-2125e1c055d7/span>span classline>REPORT RequestId: 728dcddf-feaa-11e6-8346-2125e1c055d7 Duration: 6000.08 ms Billed Duration: 6000 ms Memory Size: 1024 MB Max Memory Used: 23 MB /span>/code>/pre>/td>/tr>/table>/div>/figure>p>In my experience, these errors were often not fatal, but the correct approach is to build the php binary from a base image which is closer to the one lambda uses. So instead of my docker file starting with code>FROM ubuntu/code>, it now starts with code>FROM amazonlinux/code>. Also, with this image, I can use code>yum/code> to install other dependencies like code>libpng-devel/code>. So the new docker build script for producing the php binary looks like this:/p>figure classcode>figcaption>span>dockerfile.buildphp/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>span classline-number>16/span>span classline-number>17/span>span classline-number>18/span>span classline-number>19/span>span classline-number>20/span>span classline-number>21/span>span classline-number>22/span>span classline-number>23/span>span classline-number>24/span>span classline-number>25/span>span classline-number>26/span>span classline-number>27/span>span classline-number>28/span>span classline-number>29/span>span classline-number>30/span>span classline-number>31/span>span classline-number>32/span>span classline-number>33/span>span classline-number>34/span>span classline-number>35/span>span classline-number>36/span>span classline-number>37/span>span classline-number>38/span>span classline-number>39/span>span classline-number>40/span>span classline-number>41/span>span classline-number>42/span>/pre>/td>td classcode>pre>code classsh>span classline>span classc># Compile PHP with static linked dependencies/span>/span>span classline>span classc># to create a single running binary/span>/span>span classline>/span>span classline>FROM amazonlinux/span>span classline>/span>span classline>ARG PHP_VERSION/span>span classline>/span>span classline>RUN yum install span classse>\/span>/span>span classline> autoconf span classse>\/span>/span>span classline> automake span classse>\/span>/span>span classline> libtool span classse>\/span>/span>span classline> bison span classse>\/span>/span>span classline> re2c span classse>\/span>/span>span classline> libxml2-devel span classse>\/span>/span>span classline> openssl-devel span classse>\/span>/span>span classline> libpng-devel span classse>\/span>/span>span classline> libjpeg-devel span classse>\/span>/span>span classline> curl-devel -y/span>span classline>/span>span classline>RUN curl -sL https://github.com/php/php-src/archive/span classnv>$PHP_VERSION/span>.tar.gz | tar -zxv/span>span classline>/span>span classline>WORKDIR /php-src-span classnv>$PHP_VERSION/span>/span>span classline>/span>span classline>RUN ./buildconf --force/span>span classline>/span>span classline>RUN ./configure span classse>\/span>/span>span classline> --enable-staticspan classo>/span>yes span classse>\/span>/span>span classline> --enable-sharedspan classo>/span>no span classse>\/span>/span>span classline> --disable-all span classse>\/span>/span>span classline> --enable-json span classse>\/span>/span>span classline> --enable-libxml span classse>\/span>/span>span classline> --enable-mbstring span classse>\/span>/span>span classline> --enable-phar span classse>\/span>/span>span classline> --enable-soap span classse>\/span>/span>span classline> --enable-xml span classse>\/span>/span>span classline> --with-curl span classse>\/span>/span>span classline> --with-gd span classse>\/span>/span>span classline> --with-zlib span classse>\/span>/span>span classline> --with-openssl span classse>\/span>/span>span classline> --without-pear/span>span classline>/span>span classline>RUN make -j 5/span>/code>/pre>/td>/tr>/table>/div>/figure>p>If you run this with/p>pre>code>$ sh dockerfile.buildphp/code>/pre>p>It will use docker to overwrite the php binary which will get shipped when you deploy with code>sls deploy/code>. And this time, there are no more libcurl errors. All the code is a hrefhttps://github.com/ZeroSharp/serverless-php>on Github/a>./p>/div> /article> article> header> h1 classentry-title>a href/a-concrete-php-serverless-example/>A Concrete PHP Serverless Example - Export Chess Games in PDF/a>/h1> p classmeta> time datetime2016-11-29T17:37:00+00:00 pubdate data-updatedtrue>Nov 29span>th/span>, 2016/time> | a href/a-concrete-php-serverless-example/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>In a href/the-serverless-framework-and-php/>the last post/a> I built a PHP capable sample project for a hrefhttps://serverless.com/>the Serverless Framework/a>. In this post, I’ll show a concrete use of it./p>p>The service I’m building connects runs a PHP function for pretty-printing chess games from the a hrefhttp://lichess.org/>lichess online chess server/a>. a hrefhttps://github.com/clarkerubber/lichessPDFExporter>James Clarke/a> has written a PHP function to do this using a hrefhttp://www.fpdf.org/>fpdf17/a>./p>p>The lichess exporter takes the game id of any game that has been played on the lichess server and produced a PDF output. Take for example, Game 8 of the current World Championship which is a hrefhttps://en.lichess.org/COQChpzH>here/a>. When I open the resulting file, I see this:/p>p>img src/images/blog/serverless-lichess-pdf-exporter-001.png>/p>p>In this blog post I’ll describe how I turned this into a serverless service. The goal is to create:/p>ul>li>Add an endpoint which takes the game id as a parameter/li>li>Run the PHP function via an AWS lambda function/li>li>Return the result as a stream/li>/ul>h2>Prerequisites/h2>p>First check everything we need is installed./p>pre>code>$ serverless --version1.2.1$ node --versionv7.1.0/code>/pre>h2>Initial setup/h2>pre>code>$ mkdir serverless-lichess-to-pdf$ cd serverless-lichess-to-pdf$ sls install --url https://github.com/ZeroSharp/serverless-php/code>/pre>p>Next copy in the source from https://github.com/clarkerubber/lichessPDFExporter./p>p>You can check it works by running the following./p>pre>code>$ php main.php COQChpzH > COQChpzH.pdf/code>/pre>p>What’s going on here? The php binary (from the serverless-php project) is running main.php (from the lichess-pdf-exporter project) with argument code>COQChpzH/code> (which corresponds to a a hrefhttps://en.lichess.org/hsXtkVk8>chess game/a> on the lichess server. The main.php function downloads the game from the lichess API and passes it through the fpdf17 library to create a pdf stream which is written out to the code>COQChpzH.pdf/code> file./p>h2>Lessons learned/h2>p>I learned a few things while trying to get this project working. The basic plan is to modify handler.js so that it return the output of the call described above. Turns out there are quite a few gotchas along the way./p>h2>Lesson 1 - Defining a path parameter/h2>p>I want my API to look like this:/p>pre>code>http://.../serverless-lichess-to-pdf/export/{gameid}/code>/pre>p>I could not find an example in the serverless docs for getting a parameter that is passed in the URL./p>p>Turns out your code>serverless.yml/code> file should look like this:/p>figure classcode>figcaption>span>serverless.yml/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classyaml>span classline>span classl-Scalar-Plain>functions/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>exportToPdf/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>handler/span>span classp-Indicator>:/span> span classl-Scalar-Plain>handler.exportToPdf/span>/span>span classline> span classl-Scalar-Plain>events/span>span classp-Indicator>:/span>/span>span classline> span classp-Indicator>-/span> span classl-Scalar-Plain>http/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>path/span>span classp-Indicator>:/span> span classl-Scalar-Plain>export/{gameid}/span>/span>span classline> span classl-Scalar-Plain>method/span>span classp-Indicator>:/span> span classl-Scalar-Plain>get/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Then, in your handler.js you can retrieve the parameter with:/p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classjs>span classline>span classnx>module/span>span classp>./span>span classnx>exports/span>span classp>./span>span classnx>exportToPdf/span> span classo>/span> span classp>(/span>span classnx>event/span>span classp>,/span> span classnx>context/span>span classp>,/span> span classnx>callback/span>span classp>)/span> span classo>>/span> span classp>{/span>/span>span classline> span classkd>var/span> span classnx>gameid/span> span classo>/span> span classnx>event/span>span classp>./span>span classnx>pathParameters/span>span classp>./span>span classnx>gameid/span>span classp>;/span>/span>span classline> span classc1>// etc.../span>/span>span classline>span classp>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>/p>h2>Lesson 2 - API Gateway does not support binary data/h2>p>I was hoping I could just do something like this:/p>figure classcode>figcaption>span>handler.js/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>/pre>/td>td classcode>pre>code classjs>span classline>span classc1>// this does NOT work/span>/span>span classline>span classkr>const/span> span classnx>response/span> span classo>/span> span classp>{/span>/span>span classline> span classnx>statusCode/span>span classo>:/span> span classmi>200/span>span classp>,/span>/span>span classline> span classnx>body/span>span classo>:/span> span classnx>outputFromPhpCall/span>span classp>,/span>/span>span classline> span classnx>content/span>span classo>-/span>span classnx>type/span>span classo>:/span> span classs2>"application/pdf"/span>/span>span classline>span classp>};/span>/span>span classline>/span>span classline>span classk>return/span> span classnx>callback/span>span classp>(/span>span classkc>null/span>span classp>,/span> span classnx>response/span>span classp>);/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>At present, you cannot return a binary file. Amazon have just (November 2016) a hrefhttps://aws.amazon.com/blogs/compute/binary-support-for-api-integrations-with-amazon-api-gateway/>released support for binary types in API Gateway/a> but it’s currently a hrefhttps://github.com/serverless/serverless/issues/2797>an open issue/a> in the Serverless Framework./p>h2>Lesson 3 - You can redirect the response to an S3 bucket/h2>p>So instead of returning the binary output, I can write the output to an S3 bucket and return a 302 redirection to the S3 resource. Like this:/p>figure classcode>figcaption>span>handler.js/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>span classline-number>16/span>span classline-number>17/span>span classline-number>18/span>span classline-number>19/span>span classline-number>20/span>span classline-number>21/span>span classline-number>22/span>span classline-number>23/span>span classline-number>24/span>span classline-number>25/span>/pre>/td>td classcode>pre>code classjs>span classline>span classc1>// body contains the output from the PHP call/span>/span>span classline>span classkr>const/span> span classnx>params/span> span classo>/span> span classp>{/span>/span>span classline> span classnx>Bucket/span>span classo>:/span> span classnx>bucket/span>span classp>,/span>/span>span classline> span classnx>Key/span>span classo>:/span> span classnx>key/span>span classp>,/span>/span>span classline> span classnx>ACL/span>span classo>:/span> span classs1>'public-read-write'/span>span classp>,/span>/span>span classline> span classnx>Body/span>span classo>:/span> span classnx>body/span>span classp>,/span>/span>span classline> span classnx>ContentType/span>span classo>:/span> span classs1>'application/pdf'/span>/span>span classline>span classp>};/span>/span>span classline>/span>span classline>span classc1>// Save the pdf file to S3 /span>/span>span classline>span classnx>s3/span>span classp>./span>span classnx>putObject/span>span classp>(/span>span classnx>params/span>span classp>,/span> span classkd>function/span>span classp>(/span>span classnx>err/span>span classp>,/span> span classnx>data/span>span classp>)/span> span classp>{/span>/span>span classline>span classk>if/span> span classp>(/span>span classnx>err/span>span classp>)/span>/span>span classline>span classp>{/span>/span>span classline> span classk>return/span> span classnx>callback/span>span classp>(/span>span classk>new/span> span classnb>Error/span>span classp>(/span>span classerr>`/span>span classnx>Failed/span> span classnx>to/span> span classnx>put/span> span classnx>s3/span> span classnx>object/span>span classo>:/span> span classnx>$/span>span classp>{/span>span classnx>err/span>span classp>}/span>span classerr>`/span>span classp>));/span>/span>span classline>span classp>}/span>/span>span classline>/span>span classline>span classc1>// respond with a 302 redirect to the PDF file/span>/span>span classline>span classkr>const/span> span classnx>response/span> span classo>/span> span classp>{/span>/span>span classline> span classnx>statusCode/span>span classo>:/span> span classmi>302/span>span classp>,/span>/span>span classline> span classnx>headers/span>span classo>:/span> span classp>{/span>/span>span classline> span classnx>location/span> span classo>:/span> span classerr>`/span>span classnx>https/span>span classo>:/span>span classc1>//s3-eu-west-1.amazonaws.com/${bucket}/${key}`/span>/span>span classline> span classp>}/span>/span>span classline>span classp>};/span>/span>span classline>/span>span classline>span classk>return/span> span classnx>callback/span>span classp>(/span>span classkc>null/span>span classp>,/span> span classnx>response/span>span classp>);/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h2>Lesson 4 - You can automatically delete S3 objects after a number of days/h2>p>Each S3 bucket has optional a hrefhttps://docs.aws.amazon.com/AmazonS3/latest/dev/object-lifecycle-mgmt.html>lifecycle rules/a> where you can specify that files are automatically removed after a time period. I wanted to set this up within the code>serverless.yml/code> resources section, but the syntax for the lifecycle rules were not very obvious and I could not find any examples online. The following seems to work:/p>figure classcode>figcaption>span>serverless.yml/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>/pre>/td>td classcode>pre>code classyaml>span classline>span classl-Scalar-Plain>resources/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>Resources/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>PackageStorage/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>Type/span>span classp-Indicator>:/span> span classl-Scalar-Plain>AWS::S3::Bucket/span>/span>span classline> span classl-Scalar-Plain>Properties/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>AccessControl/span>span classp-Indicator>:/span> span classl-Scalar-Plain>PublicRead/span>/span>span classline> span classl-Scalar-Plain>BucketName/span>span classp-Indicator>:/span> span classl-Scalar-Plain>${self:custom.exportToPdfBucket}/span>/span>span classline> span classl-Scalar-Plain>LifecycleConfiguration/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>Rules/span>span classp-Indicator>:/span>/span>span classline> span classp-Indicator>-/span> span classl-Scalar-Plain>ExpirationInDays/span>span classp-Indicator>:/span> span classl-Scalar-Plain>1/span>/span>span classline> span classl-Scalar-Plain>Status/span>span classp-Indicator>:/span> span classl-Scalar-Plain>Enabled/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>h2>It’s all working now/h2>p>You can check it out by visiting a hrefhttps://e7tyur4sib.execute-api.eu-west-1.amazonaws.com/dev/export/COQChpzH>this link/a>./p>p>The a hrefhttps://github.com/ZeroSharp/serverless-lichess-to-pdf>source code is on Github/a>./p>p>I also wrote a hrefhttps://chrome.google.com/webstore/detail/lichess-print-friendly-pd/goijhimgdjppmhmjkaglhggoapkgobfg>a Chrome extension/a> which injects the link into the lichess page./p>/div> /article> article> header> h1 classentry-title>a href/the-serverless-framework-and-php/>The Serverless Framework and PHP/a>/h1> p classmeta> time datetime2016-11-21T09:21:00+00:00 pubdate data-updatedtrue>Nov 21span>st/span>, 2016/time> | a href/the-serverless-framework-and-php/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>The goal of this post is to explain how to call a PHP function from within an AWS lambda using the a hrefhttps://serverless.com/>Serverless Framework/a>./p>h2>Prerequisites/h2>p>First check everything we need is installed./p>pre>code>$ serverless --version1.1.0$ node --versionv7.1.0/code>/pre>h2>Install the sample PHP function/h2>p>Install my sample em>Hello/em> function from my github repository./p>pre>code>$ sls install --url https://github.com/ZeroSharp/serverless-php/code>/pre>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>/pre>/td>td classcode>pre>code classsh>span classline>Serverless: Downloading and installing span classs2>"serverless-php"/span>…/span>span classline>Serverless: Successfully installed span classs2>"serverless-php"/span>./span>/code>/pre>/td>/tr>/table>/div>/figure>h2>The code/h2>pre>code>$ cd serverless-php/code>/pre>p>Let’s have a look at the code>serverless.yml/code> file./p>figure classcode>figcaption>span>serverless.yml/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>/pre>/td>td classcode>pre>code classyaml>span classline>span classl-Scalar-Plain>service/span>span classp-Indicator>:/span> span classl-Scalar-Plain>serverless-php/span>/span>span classline>/span>span classline>span classl-Scalar-Plain>provider/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>name/span>span classp-Indicator>:/span> span classl-Scalar-Plain>aws/span>/span>span classline> span classl-Scalar-Plain>runtime/span>span classp-Indicator>:/span> span classl-Scalar-Plain>nodejs4.3/span>/span>span classline> span classc1># region: eu-west-1/span>/span>span classline>/span>span classline>span classl-Scalar-Plain>functions/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>hello/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>handler/span>span classp-Indicator>:/span> span classl-Scalar-Plain>handler.hello/span>/span>span classline> span classl-Scalar-Plain>events/span>span classp-Indicator>:/span>/span>span classline> span classp-Indicator>-/span> span classl-Scalar-Plain>http/span>span classp-Indicator>:/span>/span>span classline> span classl-Scalar-Plain>path/span>span classp-Indicator>:/span> span classl-Scalar-Plain>hello/span>/span>span classline> span classl-Scalar-Plain>method/span>span classp-Indicator>:/span> span classl-Scalar-Plain>get/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Now look at the php function code>index.php/code> that we’d like our lambda to call./p>figure classcode>figcaption>span>index.php/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>/pre>/td>td classcode>pre>code classphp>span classline>span classcp><?php/span>/span>span classline>/span>span classline>span classc1># $argv will contain the event object. You can output its contents like this if you like/span>/span>span classline>span classc1>#var_export($argv, true);/span>/span>span classline>/span>span classline>span classnb>printf/span>span classp>(/span>span classs1>'Go Serverless v1.0! Your PHP function executed successfully!'/span>span classp>);/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>And the code>handler.js/code> for the hello function looks as follows. It defines a simple lambda which calls the PHP binary, logs any errors and returns the result./p>figure classcode>figcaption>span>handler.js/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>span classline-number>16/span>span classline-number>17/span>span classline-number>18/span>span classline-number>19/span>span classline-number>20/span>span classline-number>21/span>span classline-number>22/span>span classline-number>23/span>span classline-number>24/span>span classline-number>25/span>span classline-number>26/span>span classline-number>27/span>span classline-number>28/span>span classline-number>29/span>span classline-number>30/span>span classline-number>31/span>span classline-number>32/span>span classline-number>33/span>span classline-number>34/span>span classline-number>35/span>span classline-number>36/span>span classline-number>37/span>span classline-number>38/span>span classline-number>39/span>span classline-number>40/span>span classline-number>41/span>span classline-number>42/span>span classline-number>43/span>span classline-number>44/span>/pre>/td>td classcode>pre>code classjs>span classline>span classs1>'use strict'/span>span classp>;/span>/span>span classline>/span>span classline>span classkd>var/span> span classnx>child_process/span> span classo>/span> span classnx>require/span>span classp>(/span>span classs1>'child_process'/span>span classp>);/span>/span>span classline>/span>span classline>span classnx>module/span>span classp>./span>span classnx>exports/span>span classp>./span>span classnx>hello/span> span classo>/span> span classp>(/span>span classnx>event/span>span classp>,/span> span classnx>context/span>span classp>,/span> span classnx>callback/span>span classp>)/span> span classo>>/span> span classp>{/span>/span>span classline>/span>span classline> span classkd>var/span> span classnx>strToReturn/span> span classo>/span> span classs1>''/span>span classp>;/span>/span>span classline>/span>span classline> span classkd>var/span> span classnx>php/span> span classo>/span> span classs1>'./php'/span>span classp>;/span>/span>span classline>/span>span classline> span classc1>// workaround to get 'sls invoke local' to work/span>/span>span classline> span classk>if/span> span classp>(/span>span classk>typeof/span> span classnx>process/span>span classp>./span>span classnx>env/span>span classp>./span>span classnx>PWD/span> span classo>!/span> span classs2>"undefined"/span>span classp>)/span> span classp>{/span>/span>span classline> span classnx>php/span> span classo>/span> span classs1>'php'/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classkd>var/span> span classnx>proc/span> span classo>/span> span classnx>child_process/span>span classp>./span>span classnx>spawn/span>span classp>(/span>span classnx>php/span>span classp>,/span> span classp>/span> span classs2>"index.php"/span>span classp>,/span> span classnx>JSON/span>span classp>./span>span classnx>stringify/span>span classp>(/span>span classnx>event/span>span classp>),/span> span classp>{/span> span classnx>stdio/span>span classo>:/span> span classs1>'inherit'/span> span classp>}/span> span classp>);/span>/span>span classline>/span>span classline> span classnx>proc/span>span classp>./span>span classnx>stdout/span>span classp>./span>span classnx>on/span>span classp>(/span>span classs1>'data'/span>span classp>,/span> span classkd>function/span> span classp>(/span>span classnx>data/span>span classp>)/span> span classp>{/span>/span>span classline> span classkd>var/span> span classnx>dataStr/span> span classo>/span> span classnx>data/span>span classp>./span>span classnx>toString/span>span classp>()/span>/span>span classline> span classc1>// console.log('stdout: ' + dataStr);/span>/span>span classline> span classnx>strToReturn/span> span classo>+/span> span classnx>dataStr/span>/span>span classline> span classp>});/span>/span>span classline>/span>span classline> span classc1>// this ensures any error messages raised by the PHP function end up in the logs/span>/span>span classline> span classnx>proc/span>span classp>./span>span classnx>stderr/span>span classp>./span>span classnx>on/span>span classp>(/span>span classs1>'data'/span>span classp>,/span> span classkd>function/span> span classp>(/span>span classnx>data/span>span classp>)/span> span classp>{/span>/span>span classline> span classnx>console/span>span classp>./span>span classnx>log/span>span classp>(/span>span classerr>`/span>span classnx>stderr/span>span classo>:/span> span classnx>$/span>span classp>{/span>span classnx>data/span>span classp>}/span>span classerr>`/span>span classp>);/span>/span>span classline> span classp>});/span>/span>span classline>/span>span classline> span classnx>proc/span>span classp>./span>span classnx>on/span>span classp>(/span>span classs1>'close'/span>span classp>,/span> span classkd>function/span>span classp>(/span>span classnx>code/span>span classp>)/span> span classp>{/span>/span>span classline> span classk>if/span>span classp>(/span>span classnx>code/span> span classo>!/span> span classmi>0/span>span classp>)/span> span classp>{/span>/span>span classline> span classk>return/span> span classnx>callback/span>span classp>(/span>span classk>new/span> span classnb>Error/span>span classp>(/span>span classerr>`/span>span classnx>Process/span> span classnx>exited/span> span classkd>with/span> span classnx>non/span>span classo>-/span>span classnx>zero/span> span classnx>status/span> span classnx>code/span> span classnx>$/span>span classp>{/span>span classnx>code/span>span classp>}/span>span classerr>`/span>span classp>));/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classkr>const/span> span classnx>response/span> span classo>/span> span classp>{/span>/span>span classline> span classnx>statusCode/span>span classo>:/span> span classmi>200/span>span classp>,/span>/span>span classline> span classnx>body/span>span classo>:/span> span classnx>JSON/span>span classp>./span>span classnx>stringify/span>span classp>({/span>/span>span classline> span classnx>message/span>span classo>:/span> span classnx>strToReturn/span>span classp>,/span>/span>span classline> span classc1>//input: event,/span>/span>span classline> span classp>}),/span>/span>span classline> span classp>};/span>/span>span classline>/span>span classline> span classnx>callback/span>span classp>(/span>span classkc>null/span>span classp>,/span> span classnx>response/span>span classp>);/span>/span>span classline> span classp>});/span>/span>span classline>span classp>};/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Included is the PHP binary to bundle with our serverless function./p>p>(You may need to compile it yourself with different options. See below for help on how to do this.)/p>p>Check it works from your shell./p>pre>code>$ php index.php/code>/pre>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>/pre>/td>td classcode>pre>code classsh>span classline>Go Serverless v1.0! Your PHP span classk>function /span>executed successfully!/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Run it locally through the Serverless Framework./p>pre>code>$ sls invoke local --function hello/code>/pre>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>/pre>/td>td classcode>pre>code classsh>span classline>Serverless: Your span classk>function /span>ran successfully./span>span classline>/span>span classline>span classo>{/span>/span>span classline> span classs2>"statusCode"/span>: 200,/span>span classline> span classs2>"body"/span>: span classs2>"{\"message\":\"Go Serverless v1.0! Your PHP function executed successfully!\"}"/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Looks good. Let’s deploy./p>pre>code>$ sls deploy/code>/pre>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>span classline-number>16/span>span classline-number>17/span>span classline-number>18/span>/pre>/td>td classcode>pre>code classsh>span classline>Serverless: Packaging service…/span>span classline>Serverless: Uploading CloudFormation file to S3…/span>span classline>Serverless: Uploading service .zip file to S3…/span>span classline>Serverless: Updating Stack…/span>span classline>Serverless: Checking Stack update progress…/span>span classline>........../span>span classline>Serverless: Stack update finished…/span>span classline>/span>span classline>Service Information/span>span classline>service: serverless-php/span>span classline>stage: dev/span>span classline>region: eu-west-1/span>span classline>api keys:/span>span classline> None/span>span classline>endpoints:/span>span classline> GET - https://c1w0hct166.execute-api.eu-west-1.amazonaws.com/dev/hello/span>span classline>functions:/span>span classline> serverless-php-dev-hello: arn:aws:lambda:eu-west-1:962613113552:function:serverless-php-dev-hello/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Run the remote function via Serverless./p>pre>code>$ sls invoke --function hello/code>/pre>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>/pre>/td>td classcode>pre>code classsh>span classline>span classo>{/span>/span>span classline> span classs2>"statusCode"/span>: 200,/span>span classline> span classs2>"body"/span>: span classs2>"{\"message\":\"Go Serverless v1.0! Your PHP function executed successfully!\",\"input\":{}}"/span>/span>span classline>span classo>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Visit the endpoint in your browser./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classjson>span classline>span classp>{/span>/span>span classline> span classnt>"message"/span>span classp>:/span> span classs2>"Go Serverless v1.0! Your PHP function executed successfully!"/span>/span>span classline>span classp>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Nice. It’s all working./p>h2>Rebuilding the PHP binary/h2>p>Depending on the PHP function you need to run, it may be necessary to rebuild the php binary with different flags and dependencies. You can do this best with docker./p>pre>code>$ docker --versionDocker version 1.12.3, build 6b644ec/code>/pre>p>Modify code>dockerfile.buildphp/code> as necessary./p>p>Then run:/p>pre>code>$ sh buildphp.sh/code>/pre>p>This will build a new PHP binary and copy it to the project root. You can immediately deploy for testing with:/p>pre>code>$ sls deploy/code>/pre>h2>Thanks/h2>p>Shout out to a hrefhttps://github.com/dannylinden/aws-lambda-php>Danny Linden/a> whose code got me started on this./p>/div> /article> article> header> h1 classentry-title>a href/smart-hiding-of-the-selection-boxes-in-xaf-web-applications/>Smart Hiding of the Selection Boxes in XAF Web Applications/a>/h1> p classmeta> time datetime2016-11-06T18:39:00+00:00 pubdate data-updatedtrue>Nov 6span>th/span>, 2016/time> | a href/smart-hiding-of-the-selection-boxes-in-xaf-web-applications/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>When an a hrefhttps://www.devexpress.com/products/net/application_framework/>XAF/a> list view has no selection-based actions available, the selection box still appears in the grid. Users get confused. In this post, we’ll look at a workaround./p>h2>The problem/h2>p>In the XAF MainDemo, lets make Departments read-only for the User role./p>figure classcode>figcaption>span>Updater.cs/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>/pre>/td>td classcode>pre>code classc#>span classline>span classn>userRole/span>span classp>./span>span classn>AddTypePermissionsRecursively/span>span classp></span>span classn>Department/span>span classp>>(/span>span classn>SecurityOperations/span>span classp>./span>span classn>Create/span>span classp>,/span> span classn>SecurityPermissionState/span>span classp>./span>span classn>Deny/span>span classp>);/span>/span>span classline>span classn>userRole/span>span classp>./span>span classn>AddTypePermissionsRecursively/span>span classp></span>span classn>Department/span>span classp>>(/span>span classn>SecurityOperations/span>span classp>./span>span classn>Write/span>span classp>,/span> span classn>SecurityPermissionState/span>span classp>./span>span classn>Deny/span>span classp>);/span>/span>span classline>span classn>userRole/span>span classp>./span>span classn>AddTypePermissionsRecursively/span>span classp></span>span classn>Department/span>span classp>>(/span>span classn>SecurityOperations/span>span classp>./span>span classn>Delete/span>span classp>,/span> span classn>SecurityPermissionState/span>span classp>./span>span classn>Deny/span>span classp>);/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Then start the web application, login as John and navigate to the Departments list view. There is a column selection box, but it serves no purpose. There are no actions that depend on a grid selection./p>p>span classcaption-wrapper>img classcaption src/images/blog/selection-visibility-controller-001.png width height titleWithout the SelectionColumnVisibilityController>span classcaption-text>Without the SelectionColumnVisibilityController/span>/span>/p>h2>The fix/h2>p>Here is a controller which calculates whether there are any available actions which require one or more rows to be selected. If there are none, the selection box will not appear./p>p>Add the following controller to the MainDemo.Module.Web project. It hides the selection box if there are no actions which depend on a grid selection./p>figure classcode>figcaption>span>SelectionColumnVisibilityController.cs/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>span classline-number>8/span>span classline-number>9/span>span classline-number>10/span>span classline-number>11/span>span classline-number>12/span>span classline-number>13/span>span classline-number>14/span>span classline-number>15/span>span classline-number>16/span>span classline-number>17/span>span classline-number>18/span>span classline-number>19/span>span classline-number>20/span>span classline-number>21/span>span classline-number>22/span>span classline-number>23/span>span classline-number>24/span>span classline-number>25/span>span classline-number>26/span>span classline-number>27/span>span classline-number>28/span>span classline-number>29/span>span classline-number>30/span>span classline-number>31/span>span classline-number>32/span>span classline-number>33/span>span classline-number>34/span>span classline-number>35/span>span classline-number>36/span>span classline-number>37/span>span classline-number>38/span>span classline-number>39/span>span classline-number>40/span>span classline-number>41/span>span classline-number>42/span>span classline-number>43/span>span classline-number>44/span>span classline-number>45/span>span classline-number>46/span>span classline-number>47/span>span classline-number>48/span>span classline-number>49/span>span classline-number>50/span>span classline-number>51/span>span classline-number>52/span>span classline-number>53/span>span classline-number>54/span>span classline-number>55/span>span classline-number>56/span>span classline-number>57/span>span classline-number>58/span>span classline-number>59/span>span classline-number>60/span>span classline-number>61/span>span classline-number>62/span>span classline-number>63/span>span classline-number>64/span>span classline-number>65/span>span classline-number>66/span>span classline-number>67/span>span classline-number>68/span>span classline-number>69/span>span classline-number>70/span>span classline-number>71/span>span classline-number>72/span>span classline-number>73/span>span classline-number>74/span>span classline-number>75/span>span classline-number>76/span>span classline-number>77/span>span classline-number>78/span>span classline-number>79/span>span classline-number>80/span>span classline-number>81/span>span classline-number>82/span>span classline-number>83/span>span classline-number>84/span>span classline-number>85/span>span classline-number>86/span>span classline-number>87/span>span classline-number>88/span>span classline-number>89/span>span classline-number>90/span>span classline-number>91/span>span classline-number>92/span>span classline-number>93/span>span classline-number>94/span>span classline-number>95/span>span classline-number>96/span>span classline-number>97/span>span classline-number>98/span>span classline-number>99/span>span classline-number>100/span>span classline-number>101/span>span classline-number>102/span>span classline-number>103/span>span classline-number>104/span>span classline-number>105/span>span classline-number>106/span>span classline-number>107/span>span classline-number>108/span>span classline-number>109/span>span classline-number>110/span>span classline-number>111/span>span classline-number>112/span>span classline-number>113/span>span classline-number>114/span>span classline-number>115/span>span classline-number>116/span>span classline-number>117/span>span classline-number>118/span>span classline-number>119/span>span classline-number>120/span>span classline-number>121/span>span classline-number>122/span>span classline-number>123/span>span classline-number>124/span>span classline-number>125/span>span classline-number>126/span>span classline-number>127/span>span classline-number>128/span>span classline-number>129/span>span classline-number>130/span>span classline-number>131/span>span classline-number>132/span>span classline-number>133/span>span classline-number>134/span>span classline-number>135/span>span classline-number>136/span>span classline-number>137/span>span classline-number>138/span>span classline-number>139/span>span classline-number>140/span>span classline-number>141/span>/pre>/td>td classcode>pre>code classc#>span classline>span classk>using/span> span classnn>System/span>span classp>;/span>/span>span classline>span classk>using/span> span classnn>DevExpress.ExpressApp/span>span classp>;/span>/span>span classline>span classk>using/span> span classnn>DevExpress.ExpressApp.Actions/span>span classp>;/span>/span>span classline>span classk>using/span> span classnn>DevExpress.ExpressApp.Editors/span>span classp>;/span>/span>span classline>span classk>using/span> span classnn>DevExpress.ExpressApp.SystemModule/span>span classp>;/span>/span>span classline>span classk>using/span> span classnn>DevExpress.Web/span>span classp>;/span>/span>span classline>span classk>using/span> span classnn>System.Linq/span>span classp>;/span>/span>span classline>/span>span classline>span classk>namespace/span> span classnn>MainDemo.Module.Web.Controllers/span>/span>span classline>span classp>{/span>/span>span classline> span classk>public/span> span classk>class/span> span classnc>SelectionColumnVisibilityController/span> span classp>:/span> span classn>ViewController/span>/span>span classline> span classp>{/span>/span>span classline> span classk>public/span> span classnf>SelectionColumnVisibilityController/span>span classp>()/span>/span>span classline> span classp>{/span>/span>span classline> span classn>TargetViewType/span> span classp>/span> span classn>ViewType/span>span classp>./span>span classn>ListView/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>private/span> span classkt>bool/span> span classnf>IsSelectionColumnVisible/span>span classp>()/span>/span>span classline> span classp>{/span>/span>span classline> span classkt>bool/span> span classn>isSelectionColumnRequired/span> span classp>/span> span classk>false/span>span classp>;/span>/span>span classline> span classc1>// remove checkbox if there are no available actions/span>/span>span classline> span classk>foreach/span> span classp>(/span>span classn>Controller/span> span classn>controller/span> span classk>in/span> span classn>Frame/span>span classp>./span>span classn>Controllers/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(!/span>span classn>controller/span>span classp>./span>span classn>Active/span>span classp>)/span>/span>span classline> span classk>continue/span>span classp>;/span>/span>span classline>/span>span classline> span classk>if/span> span classp>(/span>span classn>controller/span>span classp>./span>span classn>Actions/span>span classp>./span>span classn>Count/span> span classp>/span> span classm>0/span>span classp>)/span>/span>span classline> span classk>continue/span>span classp>;/span>/span>span classline>/span>span classline> span classkt>bool/span> span classn>allowEdit/span> span classp>/span> span classk>true/span>span classp>;/span>/span>span classline> span classk>if/span> span classp>((/span>span classn>Frame/span> span classk>is/span> span classn>NestedFrame/span>span classp>)/span> span classp>&&/span> span classp>(((/span>span classn>NestedFrame/span>span classp>)/span>span classn>Frame/span>span classp>)./span>span classn>ViewItem/span> span classk>is/span> span classn>PropertyEditor/span>span classp>))/span>/span>span classline> span classn>allowEdit/span> span classp>/span> span classp>(/span>span classkt>bool/span>span classp>)((/span>span classn>PropertyEditor/span>span classp>)((/span>span classn>NestedFrame/span>span classp>)/span>span classn>Frame/span>span classp>)./span>span classn>ViewItem/span>span classp>)./span>span classn>AllowEdit/span>span classp>;/span>/span>span classline>/span>span classline> span classk>foreach/span> span classp>(/span>span classn>ActionBase/span> span classn>action/span> span classk>in/span> span classn>controller/span>span classp>./span>span classn>Actions/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>action/span>span classp>./span>span classn>SelectionDependencyType/span> span classp>/span> span classn>SelectionDependencyType/span>span classp>./span>span classn>RequireMultipleObjects/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>action/span>span classp>./span>span classn>Active/span> span classp>||/span> span classn>IsActionInactiveBySelectionContext/span>span classp>(/span>span classn>action/span>span classp>))/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>action/span>span classp>./span>span classn>Enabled/span> span classp>||/span> span classn>IsActionDisabledBySelectionContext/span>span classp>(/span>span classn>action/span>span classp>))/span>/span>span classline> span classp>{/span>/span>span classline> span classn>isSelectionColumnRequired/span> span classp>/span> span classk>true/span>span classp>;/span>/span>span classline> span classk>break/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>isSelectionColumnRequired/span>span classp>)/span>/span>span classline> span classk>break/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classk>return/span> span classn>isSelectionColumnRequired/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>private/span> span classkt>bool/span> span classnf>IsActionInactiveBySelectionContext/span>span classp>(/span>span classn>ActionBase/span> span classn>action/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>action/span>span classp>./span>span classn>Active/span>span classp>)/span>/span>span classline> span classk>return/span> span classk>true/span>span classp>;/span>/span>span classline> span classk>else/span>/span>span classline> span classp>{/span>/span>span classline> span classk>foreach/span> span classp>(/span>span classkt>string/span> span classn>item/span> span classk>in/span> span classn>action/span>span classp>./span>span classn>Active/span>span classp>./span>span classn>GetKeys/span>span classp>())/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>item/span> span classp>/span> span classn>ActionBase/span>span classp>./span>span classn>RequireMultipleObjectsContext/span> span classp>||/span> span classn>item/span> span classp>/span> span classn>ActionBase/span>span classp>./span>span classn>RequireSingleObjectContext/span>span classp>)/span>/span>span classline> span classk>continue/span>span classp>;/span>/span>span classline> span classk>if/span> span classp>(!/span>span classn>action/span>span classp>./span>span classn>Active/span>span classp>/span>span classn>item/span>span classp>)/span>/span>span classline> span classk>return/span> span classk>false/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classk>return/span> span classk>true/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>private/span> span classkt>bool/span> span classnf>IsActionDisabledBySelectionContext/span>span classp>(/span>span classn>ActionBase/span> span classn>action/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>action/span>span classp>./span>span classn>Enabled/span>span classp>)/span>/span>span classline> span classk>return/span> span classk>true/span>span classp>;/span>/span>span classline> span classk>else/span>/span>span classline> span classp>{/span>/span>span classline> span classk>foreach/span> span classp>(/span>span classkt>string/span> span classn>item/span> span classk>in/span> span classn>action/span>span classp>./span>span classn>Enabled/span>span classp>./span>span classn>GetKeys/span>span classp>())/span>/span>span classline> span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>item/span> span classp>/span> span classn>ActionBase/span>span classp>./span>span classn>RequireMultipleObjectsContext/span> span classp>||/span>/span>span classline> span classn>item/span> span classp>/span> span classn>ActionBase/span>span classp>./span>span classn>RequireSingleObjectContext/span> span classp>||/span>/span>span classline> span classn>item/span> span classp>/span> span classn>ActionsCriteriaViewController/span>span classp>./span>span classn>EnabledByCriteriaKey/span>span classp>)/span>/span>span classline> span classk>continue/span>span classp>;/span>/span>span classline> span classk>if/span> span classp>(!/span>span classn>action/span>span classp>./span>span classn>Enabled/span>span classp>/span>span classn>item/span>span classp>)/span>/span>span classline> span classk>return/span> span classk>false/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classk>return/span> span classk>true/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>protected/span> span classk>override/span> span classk>void/span> span classnf>OnViewControlsCreated/span>span classp>()/span>/span>span classline> span classp>{/span>/span>span classline> span classk>base/span>span classp>./span>span classn>OnViewControlsCreated/span>span classp>();/span>/span>span classline> span classn>ASPxGridView/span> span classn>grid/span> span classp>/span> span classp>((/span>span classn>ListView/span>span classp>)/span>span classk>this/span>span classp>./span>span classn>View/span>span classp>)./span>span classn>Editor/span>span classp>./span>span classn>Control/span> span classk>as/span> span classn>ASPxGridView/span>span classp>;/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>grid/span> span classp>!/span> span classk>null/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classn>grid/span>span classp>./span>span classn>Load/span> span classp>+/span> span classn>grid_Load/span>span classp>;/span>/span>span classline> span classn>grid/span>span classp>./span>span classn>DataBound/span> span classp>+/span> span classn>grid_DataBound/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>protected/span> span classk>override/span> span classk>void/span> span classnf>OnDeactivated/span>span classp>()/span>/span>span classline> span classp>{/span>/span>span classline> span classk>base/span>span classp>./span>span classn>OnDeactivated/span>span classp>();/span>/span>span classline> span classn>ASPxGridView/span> span classn>grid/span> span classp>/span> span classp>((/span>span classn>ListView/span>span classp>)/span>span classk>this/span>span classp>./span>span classn>View/span>span classp>)./span>span classn>Editor/span>span classp>./span>span classn>Control/span> span classk>as/span> span classn>ASPxGridView/span>span classp>;/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>grid/span> span classp>!/span> span classk>null/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classn>grid/span>span classp>./span>span classn>DataBound/span> span classp>-/span> span classn>grid_DataBound/span>span classp>;/span>/span>span classline> span classn>grid/span>span classp>./span>span classn>Load/span> span classp>-/span> span classn>grid_Load/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>void/span> span classnf>grid_Load/span>span classp>(/span>span classkt>object/span> span classn>sender/span>span classp>,/span> span classn>EventArgs/span> span classn>e/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classn>SetSelectionColumnVisibility/span>span classp>(/span>span classn>sender/span>span classp>,/span> span classn>e/span>span classp>);/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>void/span> span classnf>grid_DataBound/span>span classp>(/span>span classkt>object/span> span classn>sender/span>span classp>,/span> span classn>EventArgs/span> span classn>e/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classn>SetSelectionColumnVisibility/span>span classp>(/span>span classn>sender/span>span classp>,/span> span classn>e/span>span classp>);/span>/span>span classline> span classp>}/span>/span>span classline>/span>span classline> span classk>private/span> span classk>void/span> span classnf>SetSelectionColumnVisibility/span>span classp>(/span>span classkt>object/span> span classn>sender/span>span classp>,/span> span classn>EventArgs/span> span classn>e/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classkt>bool/span> span classn>isSelectionColumnVisible/span> span classp>/span> span classn>IsSelectionColumnVisible/span>span classp>();/span>/span>span classline> span classk>if/span> span classp>(!/span>span classn>isSelectionColumnVisible/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classkt>var/span> span classn>grid/span> span classp>/span> span classp>(/span>span classn>ASPxGridView/span>span classp>)/span>span classn>sender/span>span classp>;/span>/span>span classline> span classkt>var/span> span classn>selectionBoxColumn/span> span classp>/span>/span>span classline> span classn>grid/span>span classp>./span>span classn>Columns/span>/span>span classline> span classp>./span>span classn>OfType/span>span classp></span>span classn>GridViewCommandColumn/span>span classp>>()/span>/span>span classline> span classp>./span>span classn>Where/span>span classp>(/span>span classn>x/span> span classp>>/span> span classn>x/span>span classp>./span>span classn>ShowSelectCheckbox/span>span classp>)/span>/span>span classline> span classp>./span>span classn>FirstOrDefault/span>span classp>();/span>/span>span classline>/span>span classline> span classk>if/span> span classp>(/span>span classn>selectionBoxColumn/span> span classp>!/span> span classk>null/span>span classp>)/span>/span>span classline> span classp>{/span>/span>span classline> span classn>selectionBoxColumn/span>span classp>./span>span classn>Visible/span> span classp>/span> span classk>false/span>span classp>;/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline> span classp>}/span>/span>span classline>span classp>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>Run the application again and see the difference. Now the grid looks like this. Notice, there is no longer a selection box on the row./p>p>img src/images/blog/selection-visibility-controller-002.png titleWith the SelectionColumnVisibilityController >/p>p>By the way, this is how it looks with old-style XAF web apps./p>p>span classcaption-wrapper>img classcaption src/images/blog/selection-visibility-controller-003.png width height titleWithout the SelectionColumnVisibilityController>span classcaption-text>Without the SelectionColumnVisibilityController/span>/span>/p>p>span classcaption-wrapper>img classcaption src/images/blog/selection-visibility-controller-004.png width height titleWith the SelectionColumnVisibilityController>span classcaption-text>With the SelectionColumnVisibilityController/span>/span>/p>/div> /article> article> header> h1 classentry-title>a href/sometimes-youve-just-got-to-deploy/>Sometimes You’ve Just Got to Deploy/a>/h1> p classmeta> time datetime2016-10-16T18:44:00+01:00 pubdate data-updatedtrue>Oct 16span>th/span>, 2016/time> | a href/sometimes-youve-just-got-to-deploy/#disqus_thread>Comments/a> /p> /header> div classentry-content>p>Sometimes the deadline has arrived and you still have some failing tests. After a discussion with the dev team, you decide to deploy anyway and fix the bugs for the next release. You need to get the build server to ignore the tests./p>p>One way is just to mark the test with the code>Ignore/code> attribute./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>/pre>/td>td classcode>pre>code classc#>span classline>span classna>Test/span>/span>span classline>span classna>Ignore/span> span classc1>// TODO: Fix this test before the next release!/span>/span>span classline>span classk>public/span> span classk>void/span> span classnf>Test/span>span classp>()/span>/span>span classline>span classp>{/span>/span>span classline> span classc1>// Some failing test code.../span>/span>span classline>span classp>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>After the weekend, everyone forgets about the ignored tests and they never get fixed./p>p>Instead, I like to do this./p>figure classcode>figcaption>span>/span>/figcaption>div classhighlight>table>tr>td classgutter>pre classline-numbers>span classline-number>1/span>span classline-number>2/span>span classline-number>3/span>span classline-number>4/span>span classline-number>5/span>span classline-number>6/span>span classline-number>7/span>/pre>/td>td classcode>pre>code classc#>span classline>span classna>Test/span>/span>span classline>span classk>public/span> span classk>void/span> span classnf>Test/span>span classp>()/span>/span>span classline>span classp>{/span>/span>span classline> span classk>if/span> span classp>(/span>span classn>DateTime/span>span classp>./span>span classn>Now/span> span classp></span> span classk>new/span> span classn>DateTime/span>span classp>(/span>span classm>2016/span>span classp>,/span> span classm>10/span>span classp>,/span> span classm>17/span>span classp>))/span>/span>span classline> span classn>Assert/span>span classp>./span>span classn>Ignore/span>span classp>(/span>span classs>"Temporarily ignored until October 17."/span>span classp>);/span>/span>span classline> span classc1>// Some failing test code.../span>/span>span classline>span classp>}/span>/span>/code>/pre>/td>/tr>/table>/div>/figure>p>This is a fairly rare occurrence for my team, so the above approach is sufficient and works with all test frameworks. But if you want to go further a hrefhttps://www.amido.com/code/conditional-ignore-nunit-and-the-ability-to-conditionally-ignore-a-test/>Richard Slater shows how to create an NUnit attribute/a>./p>/div> /article> div classpagination> a classprev href/blog/page/2/>← Older/a> a href/blog/archives>Blog Archives/a> /div>/div>aside classsidebar> /aside> /div> /div> footer rolecontentinfo>p> Copyright © 2018 - Robert Anderson span classcredit>Powered by a hrefhttp://octopress.org>Octopress/a>/span>/p>/footer> script typetext/javascript> var disqus_shortname zerosharp; var disqus_script count.js; (function () { var dsq document.createElement(script); dsq.type text/javascript; dsq.async true; dsq.src http:// + disqus_shortname + .disqus.com/ + disqus_script; (document.getElementsByTagName(head)0 || document.getElementsByTagName(body)0).appendChild(dsq); }());/script>div idfb-root>/div>script>(function(d, s, id) { var js, fjs d.getElementsByTagName(s)0; if (d.getElementById(id)) {return;} js d.createElement(s); js.id id; js.src //connect.facebook.net/en_US/all.js#appId212934732101925&xfbml1; fjs.parentNode.insertBefore(js, fjs);}(document, script, facebook-jssdk));/script> script typetext/javascript> (function() { var script document.createElement(script); script.type text/javascript; script.async true; script.src https://apis.google.com/js/plusone.js; var s document.getElementsByTagName(script)0; s.parentNode.insertBefore(script, s); })(); /script> script typetext/javascript> (function(){ var twitterWidgets document.createElement(script); twitterWidgets.type text/javascript; twitterWidgets.async true; twitterWidgets.src http://platform.twitter.com/widgets.js; document.getElementsByTagName(head)0.appendChild(twitterWidgets); })(); /script>/body>/html>
View on OTX
|
View on ThreatMiner
Please enable JavaScript to view the
comments powered by Disqus.
Data with thanks to
AlienVault OTX
,
VirusTotal
,
Malwr
and
others
. [
Sitemap
]