RewriteRules in .htaccess files that run after a set date/time

If you’re going to launch a website out of hours and want an old site that uses Apache to redirect to the new site, you can set a list of rewrite rules to run after a certain time. The trick is to write a condition that makes a rule run until the launch date and that rule skips the new rules. After the launch date, the rule doesn’t run, so the new rules aren’t skipped: ...

July 27, 2016 · 1 min

DataTables – automatic recognition of which table columns contain date/time information

I’ve used the JavaScript DataTables plug-in for jQuery a lot. It’s great for easily adding sorting to tables and lots more. It works nicely with Bootstrap too. The clunkiest thing I’ve found is trying to sort columns that contain date / time information. In the past, I used the datetables-date-sort.js plugin, which allows you to specify for each column what the data type is e.g. <script type="text/javascript"> $(document).ready(function () { $("#myTable").dataTable({ "aLengthMenu": \[\[10, 25, 50, -1\], \[10, 25, 50, "All"\]\], "iDisplayLength": -1, "aoColumnDefs": \[ { "bSortable": false, "aTargets": \[0\] }, { "asSorting": \["asc", "desc"\], "aTargets": \[1, 2, 3, 4, 5, 6, 7, 8, 9, 10\] }, { "sType": "uk-date-time", "aTargets": \[8,10\] } \] }); }); </script> That’s nice and flexible but you have to specify it for each table and, worse still, you have to (remember to) change it each time you add/remove/reorder columns. ...

November 24, 2015 · 2 min

A couple of articles on accessibility

http://a11ywins.tumblr.com/ lists user contributed sites that are good for accessibility or have made significant improvements. There’s usually a reasonable technical overview of the technologies used. It highlights the efforts that other companies/developers are making, which is useful to spur us on to do better and to help provide justifications to our business owners for why this is important. http://simplyaccessible.com/article/spangular-accessibility/ a really helpful demo site with explainations on how to make an angularjs application accessible. The code from the demo application would be a good starting point when creating your own angularjs application.

April 10, 2015 · 1 min

Avoiding monolithic applications

I spend a lot (perhaps too much?) time worrying about how applications can become too big and extend beyond their original scope. When asked to create a small application that is either stand-alone or only slightly linked to other systems, it’s too tempting to just add it as an exatra section of an existing application, rather copy/re-create the infrastructure needed for it to be in its own application. Visual Studio now provides a lot of the infrastructure, so with a few button clicks you can have an ASP.Net MVC application that’s all plumbed together but often the first thing you do is get rid of the that auto-generated stuff and it doesn’t include all of your own standard customisations. There are a few ways to implement those standard customisations: ...

April 10, 2015 · 3 min

JWT and CORS for cross-site API authentication

In my previous post on avoiding monolithic applications, I mentioned that JSON Web Tokens and CORS could be used to access protected web apis on other sites. Here’s the why and how. The requirement for accessing protected web apis on other sites Ideally (my ideal), each application that is developed would be relatively compact and include only the functionality that is unique to that application. Functionality from other applications would be provided by APIs in those applications and generic functionality (e.g. a staff lookup) would be provided by an application (or multiple) that all other applications can access (almost like a CDN for functionality). ...

April 10, 2015 · 5 min

HTTP Referer / Referrer and HTTPS

The rule for whether the HTTP referrer (incorrectly spelt in the original spec, so forever incorrectly spelt in headers) is sent along with a request has always been a bit odd. If the referring site uses https, the referrer isn’t sent, unless the site linked too also uses https. It isn’t sent because the originating URL may contain sensitive information but the browser happily sends the sensitive URL to any other site if it uses https. ...

March 27, 2015 · 2 min

Updated error handling

In Managing Errors in MVC I got close to having record level error handling working as I wanted but I had to create a view for each error when usually the error is a single line of text that could be stored in a config file. Based on my original code and http://weblogs.asp.net/gunnarpeipman/asp-net-mvc-3-creating-httpstatuscoderesult-with-view-based-body Helpers\ExceptionHelper.cs using System; using System.Linq.Expressions; using System.Net; using System.Web; using System.Web.Mvc; using System.Web.Routing; using System.Collections; using System.Collections.Generic; namespace MyProject { public class ExceptionHelper : ViewResult { private ExceptionName \_exceptionName; private HttpStatusCode? \_statusCode; private bool? \_logException; public ExceptionHelper(ExceptionName exceptionName, HttpStatusCode? statusCode = null, bool? logException = null) { \_exceptionName = exceptionName; \_statusCode = statusCode; \_logException = logException; } public override void ExecuteResult(ControllerContext context) { HttpStatusCode returnStatusCode = HttpStatusCode.BadRequest; bool returnLogException = true; string ExceptionDescription = string.Empty; string sViewName = "Exceptions/\_GenericException"; var httpContext = context.HttpContext; var response = httpContext.Response; // get the defaults for this exception ExceptionActions theseExceptionActions; if (ExceptionDefaults.TryGetValue(\_exceptionName, out theseExceptionActions)) { if (theseExceptionActions.UseCustomView) { sViewName = "Exceptions/" + \_exceptionName.ToString(); } ExceptionDescription = theseExceptionActions.ExceptionDescription; if (null == \_statusCode) { returnStatusCode = theseExceptionActions.StatusCode; } else { returnStatusCode = (HttpStatusCode)\_statusCode; } if (null == \_logException) { returnLogException = theseExceptionActions.LogException; } else { returnLogException = (bool)\_logException; } } response.StatusCode = (int)returnStatusCode; response.StatusDescription = ExceptionDescription; ViewBag.ExceptionDescription = ExceptionDescription; ViewName = sViewName; if (returnLogException) { // log the exception Elmah.ErrorSignal.FromCurrentContext().Raise(new Exception(\_exceptionName.ToString())); } base.ExecuteResult(context); } public enum ExceptionName { DataNotValid, NoPermissionToManageThisPerson, NoPermissionToManageThisProject, RecordNotFound, RecordNotSpecified }; /// <summary> /// Most exceptions will have UseCustomView=false, so the ExceptionDescription will be used for the error message that is displayed in the \_GenericException view /// If a custom view is required, it will have the name of the exception /// </summary> public struct ExceptionActions { public bool UseCustomView; public HttpStatusCode StatusCode; public bool LogException; public string ExceptionDescription; } public static Dictionary<ExceptionName, ExceptionActions\> ExceptionDefaults = new Dictionary<ExceptionName, ExceptionActions\>() { {ExceptionName.DataNotValid, new ExceptionActions {UseCustomView = false, StatusCode = HttpStatusCode.BadRequest, LogException = true, ExceptionDescription = "Data provided was not valid"}}, {ExceptionName.NoPermissionToManageThisPerson, new ExceptionActions {UseCustomView = false, StatusCode = HttpStatusCode.Forbidden, LogException = false, ExceptionDescription = "You don't have permission to manage this person"}}, {ExceptionName.NoPermissionToManageThisProject, new ExceptionActions {UseCustomView = false, StatusCode = HttpStatusCode.Forbidden, LogException = false, ExceptionDescription = "You don't have permission to manage this project"}}, {ExceptionName.RecordNotFound, new ExceptionActions {UseCustomView = false, StatusCode = HttpStatusCode.NotFound, LogException = false, ExceptionDescription = "Record was not found"}}, {ExceptionName.RecordNotSpecified, new ExceptionActions {UseCustomView = false, StatusCode = HttpStatusCode.BadRequest, LogException = false, ExceptionDescription = "Record not specified - one or more identifiers were missing"}}, }; } } Views\Shared\Exceptions\_GenericException.cshtml ...

February 10, 2015 · 3 min

Catching up on accessibility techniques

Concern over whether my modal dialogs are accessible led on this series of articles: A great starting point if you don’t know why your sites should be accessible: http://alistapart.com/article/reframing-accessibility-for-the-web https://www.marcozehe.de/2015/02/05/advanced-aria-tip-2-accessible-modal-dialogs/ http://accessibility.oit.ncsu.edu/training/aria/modal-window/version-2/ http://www.paciellogroup.com/blog/2014/09/web-components-punch-list/ The very dry formal stuff http://www.w3.org/TR/wai-aria/ Some examples http://www.w3.org/WAI/PF/aria-practices/#aria_ex These link to real examples e.g. http://www.oaa-accessibility.org/examplep/grid1/ http://www.paciellogroup.com/resources/ http://www.paciellogroup.com/blog/2015/01/the-browser-accessibility-tree/ http://www.paciellogroup.com/blog/2014/12/using-aria-describedby-to-provide-helpful-form-hints/ http://www.paciellogroup.com/blog/2014/08/using-the-tabindex-attribute/ Screen readers http://webaim.org/projects/screenreadersurvey5/ Free screen reader http://www.nvaccess.org/ (donate if you can) You can change the voice from the notifications area and Preferences > Synthesizer

February 9, 2015 · 1 min

Getting a WebApi2 controller to return HttpStatusCode.Forbidden

If your WebApi controller is checking that the user has permission to view a particular record and it turns out that they don’t then you will want to return a status of Forbidden, rather than Unauthorized as discussed here: http://stackoverflow.com/questions/238437/why-does-authorizeattribute-redirect-to-the-login-page-for-authentication-and-au/5844884#5844884 (You might also want to override the AuthorizeAttribute class as described there) WebApi2 controllers now return IHttpActionResult rather than HttpResponseMessage (see http://stackoverflow.com/questions/21758615/why-should-i-use-ihttpactionresult-instead-of-httpresponsemessage). It’s easy to return a result from the System.Web.Http.Results Namespace e.g. return Unauthorized(); But the namespace doesn’t contain Forbidden, so instead use: ...

January 14, 2015 · 1 min

Managing errors in MVC

Error logging Elmah seems to be the most popular tool for error logging but the Elmah website doesn’t have much up to date information on how to get started. To get Elmah installed, secured and logging to somewhere more permanent than keeping the log in-memory, follow this guide: http://www.erikojebo.se/Code/Details/607 Error handling Elmah just logs error, it doesn’t help the user. So you also need to handle the errors, which this article covers nicely: https://www.simple-talk.com/dotnet/asp.net/handling-errors-effectively-in-asp.net-mvc/ ...

January 14, 2015 · 4 min