Skip to the content Back to Top

We are excited to announce that the newly published "Librarian's Introduction to Programming Languages: A LITA Guide" includes a chapter written by our Peter Tyrrell on programming in C#. 

Peter was approached last year by the editor, Beth Thomsett-Scott, who has gathered together chapters by experts on nine different programming languages that librarians might need to know more about.

"There are many books on programming languages but no recent items directly written for librarians that span a variety of programs. Many practicing librarians see programming as something for IT people or beyond their capabilities. This book will help these librarians to feel comfortable discussing programming with others by providing an understanding of when the language might be useful, what is needed to make it work, and relevant tools to extend its application. Additionally, the inclusion of practical examples lets readers try a small "app" for the language. This also will assist readers who want to learn a language but are unsure of which language would be the best fit for them in terms of learning curve and application.

This book is designed to provide a basic working knowledge of each language presented, case studies which show the programming language used in real ways and resources for exploring each language in more detail."

Peter is of course both a librarian and a programmer himself, so was delighted to contribute a chapter to the book.

If you've read and followed up on my previous posts about handling errors, you might have found yourself pulling out your hair when you discovered that your error handling went south again when you changed your target ASP.NET framework from 2.0 to 3.5/4.0 (applies to WebForms only of course). So here I am to save your day again (and yes, I wasted an entire Friday evening figuring this one out - good times).

In a nutshell, upgrade to 3.5 and your awesomely handled 500 and 404 errors start going back to 302 and 200 redirects the ol' fashioned (and completely idiotic) ASP.NET way of doing things. Of course, if you are like me, you'd waste an entire evening on it. But fortunately, you're not so you won't.

There's two issues/solutions:

  1. As of ASP.NET 3.5 there's now a redirectMode="ResponseRewrite" setting for your customErrors setting in your Web.config (yeah!). Put it in and you're halfway there (the default is the aforementioned moronic "ResponseRedirect"). Now your:
  2.             Context.Response.Clear();
                Context.Response.TrySkipIisCustomErrors = true;
                Context.Response.StatusCode = statusCode;
                Context.Response.Status = status;
               
                Context.Server.Transfer(errorPage, false);
    is back firing on all cylinders again.
  3. Except that your 404s are fine now, but your 500 errors return your error page twice in the body of your error page! Genius that I am, I went back to my experiences with IIS 6 and wrapped error pages and figured out that IIS 7/7.5 was sending back "its own" error page and then my server transfer was getting tacked on as well. Again, this does not effect 404s - I'm guessing because we clear the error (see previous post). So remove the Server.Transfer for non-404s and we're golden again.

In summary, for IIS 7/7.5 and .NET 3.5/4.0, use the following as a starting point for your Global.asax.cs or, better yet, an error module (for good measure figure out how it could be all tested):

        private readonly static ILog Log = LogManager.GetLogger(typeof(Global));
        private string _errorPageLocation;
        private string _error404PageLocation;


        protected void Application_Start(object sender, EventArgs e)
        {
            // Wire up log4net database connection string if desired.


            if (Log.IsInfoEnabled)
                Log.Info("Log4Net initialized - Ignore.");
        }


        protected void Application_Error(object sender, EventArgs e)
        {
            InitConfigurationFields();


            Exception exception = Context.Server.GetLastError();

            if (exception is HttpUnhandledException)
                if (exception.InnerException != null)
                    exception = exception.InnerException;


            if (exception is HttpException)
            {
                var ex = (HttpException)exception;
                var statusCode = ex.GetHttpCode();

                if (statusCode == 404)
                {
                    ServerTransfer(_error404PageLocation,
"404 Not Found", statusCode);
                    return;
                }
            }


            Log.Error("Unhandled error caught in error module.", exception);

            //Todo: Any way to get the correct status statement for a specifc code?
//Hard-coding all to "500 Internal Server Error" here.
            ServerTransfer(_errorPageLocation, "500 Internal Server Error", 500);
        }


        /// <summary>
        /// Gets configuration fields for database connection (if applicable),
/// and customError redirects.
        /// </summary>
        private void InitConfigurationFields()
        {
            var section = WebConfigurationManager.GetSection("system.web/customErrors");

            if (section != null && section is CustomErrorsSection)
            {
                var customErrorsSection = (CustomErrorsSection)section;
                _errorPageLocation = customErrorsSection.DefaultRedirect;

                var error404 = customErrorsSection.Errors["404"];

                if (error404 != null)
                    _error404PageLocation = error404.Redirect;
            }


            if (string.IsNullOrEmpty(_errorPageLocation))
                throw new NullReferenceException(
"customErrors DefaultRedirect must be specified in Web.config.
...For i.e. ~/error.aspx"
);


            if (string.IsNullOrEmpty(_error404PageLocation))
                throw new NullReferenceException(
"customErrors 404 statusCode redirect must be specified
...in Web.config. For i.e. ~/page-not-found.aspx"
);
        }


        private void ServerTransfer(string errorPage, string status, int statusCode)
        {
            // If customErrors is off, just let ASP.NET default happen.
            if (Context == null || !Context.IsCustomErrorEnabled)
                return;


            // Want the error around so that we can provide a little more
// descriptive message to end user in error page.
            // However, for 404 errors (only!), not clearing the error causes IIS7 to
// still hijack the process and the custom 404 error page.
            if (statusCode == 404)
                Server.ClearError();

            Context.Response.Clear();
            Context.Response.TrySkipIisCustomErrors = true;
            Context.Response.StatusCode = statusCode;
            Context.Response.Status = status;

            // For .NET 3.5, doing a Server.Transfer combined with customErrors
// redirectMode="ResponseRewrite" returns the error page body *twice*.
            if (statusCode == 404)
                Context.Server.Transfer(errorPage, false);
        }

MS Word uses characters from the Windows-1252 character encoding set which are not represented in ASCII or ISO-8859-1. This is often a pain in the butt. Special characters include:

  • the… ellipsis
  • ‘smart’ “quotes”
  • en – dash and em — dash
  • dagger † and double dagger ‡
  • and more, but these are most common.

If you want to replace them with ASCII cognates, here's a function to do that. (Daggers don't have cognates as far as I know.)

Javascript

/// Replaces commonly-used Windows 1252 encoded chars that do not exist in ASCII or ISO-8859-1 with ISO-8859-1 cognates.
var replaceWordChars = function(text) {
    var s = text;
    // smart single quotes and apostrophe
    s = s.replace(/[\u2018\u2019\u201A]/g, "\'");
    // smart double quotes
    s = s.replace(/[\u201C\u201D\u201E]/g, "\"");
    // ellipsis
    s = s.replace(/\u2026/g, "...");
    // dashes
    s = s.replace(/[\u2013\u2014]/g, "-");
    // circumflex
    s = s.replace(/\u02C6/g, "^");
    // open angle bracket
    s = s.replace(/\u2039/g, "<");
    // close angle bracket
    s = s.replace(/\u203A/g, ">");
    // spaces
    s = s.replace(/[\u02DC\u00A0]/g, " ");
    
    return s;
}

C# extension method

public static string ReplaceWordChars(this string text)
        {
            var s = text;
            // smart single quotes and apostrophe
            s = Regex.Replace(s, "[\u2018\u2019\u201A]", "'");
            // smart double quotes
            s = Regex.Replace(s, "[\u201C\u201D\u201E]", "\"");
            // ellipsis
            s = Regex.Replace(s, "\u2026", "...");
            // dashes
            s = Regex.Replace(s, "[\u2013\u2014]", "-");
            // circumflex
            s = Regex.Replace(s, "\u02C6", "^");
            // open angle bracket
            s = Regex.Replace(s, "\u2039", "<");
            // close angle bracket
            s = Regex.Replace(s, "\u203A", ">");
            // spaces
            s = Regex.Replace(s, "[\u02DC\u00A0]", " ");
            
            return s;
        }
Categories

Let Us Help You!

We're Librarians - We Love to Help People