Cymen's Blog

Archive for November, 2011

ASP.NET MVC and DropDownList: One approach…

leave a comment

One thing that I’m not particularly fond of in ASP.NET MVC is figuring out where to put additional data one needs for views. If one is using a “model per view” approach it is simple — stick it in that model. Otherwise you can choose to add it to a model that won’t always need it or pass it via ViewBag/ViewState. I currently lean towards the last option.

The other annoyance is how best to transform a list of objects into a IEnumerable<SelectListItem> collection cleanly with the special case of handling a default value. I have started to approach this with extension methods and am very happy with how it is working.

Transforming your List<MyObject> to IEnumerable<SelectListItem>

Our current data tier has a manager class for each object type. When that object type is going to be used in a select list, I add an extension to IEnumerable<MyObject> like so:

    public static class MyObjectManagerExtensions
    {
        public static IEnumerable AsSelectList(this IEnumerable list, int? value)
        {
            return (from item in list
                    select new SelectListItem
                    {
                        Selected = value.HasValue && item.Id == value.Value,
                        Text = item.Name,
                        Value = item.Id.ToString()
                    });
        }
    }

To support the option of a default value, I have an extension method that applies to IEnumerable:

    public static class SelectListExtension
    {
        public static IEnumerable WithDefault(this IEnumerable list, string defaultLabel = "Select one...", string value = "")
        {
            return (new[] { new SelectListItem { Text = defaultLabel, Value = value } }).Concat(list);
        }
    }

Here is an example of an actually call to this methods in:

ViewBag.MyObject = myObjectManager
                       .GetAllMyObjectBy(isForFoo: true, orderBy: MyObjectColumns.Name)
                       .AsSelectList(myObjectId)
                       .WithDefault();

Written by Cymen

November 18th, 2011 at 8:55 am

Posted in ASP.NET MVC

SSL Certificates, OCSP and CRLs: How to troubleshoot

leave a comment

Recently, I ran into an interesting problem: a website that my workplace was going to start hosting was about to be cut over however the SSL certificate was failing. By disabling OCSP in Firefox, I determined it was likely due to the certificate authority (GoDaddy) revoking the certificate.

The warning displayed by Google Chrome is:

The server’s security certificate is revoked!
You attempted to reach www.xyz.org, but the certificate that the server presented has been revoked by its issuer. This means that the security credentials the server presented absolutely should not be trusted. You may be communicating with an attacker. You should not proceed.

The warning displayed by Mozilla Firefox is:

Secure Connection Failed

An error occurred during a connection to www.xyz.org.
Peer’s Certificate has been revoked.

(Error code: sec_error_revoked_certificate)

  • The page you are trying to view can not be shown because the authenticity of the received data could not be verified.
  • Please contact the web site owners to inform them of this problem. Alternatively, use the command found in the help menu to report this broken site.

At first, we thought there was perhaps an issue with the intermediary certificate bundle. However that bundle matched GoDaddy’s current bundle so it was time to take a closer look at the certificate. Firefox wasn’t much help however Chrome could display all the metadata attached to the failing certificate. The two essential parts for to check the status for OCSP are the serial number and the CRL list.

The CRL list was located at http://crl.godaddy.com/gds1-18.crl and I was able to retrieve this file however I couldn’t find a decent way to view a CRL file on Windows in a searchable way quickly. I found that openssl can dump a CRL to text and I did so with the GoDaddy CRL using this command:

openssl crl -inform DER -in gds1-58.crl -text > list.txt

I then opened up list.txt in a text editor and was able to find a revocation entry similar to this one:

    Serial Number: 049A85BD85BE83
        Revocation Date: Oct 26 18:56:06 2011 GMT
        CRL entry extensions:
            X509v3 CRL Reason Code:
                Cessation Of Operation

Of course, if you have login access to the registrar for the certificate it may be quicker to simply login and see if there is some sort of mention on the account about the failing certificate. But if you need to determine why a certificate is failing OCSP hopefully the above will help. I suspect there are additional CRL to check however I’m not sure how to determine what they are.

Written by Cymen

November 17th, 2011 at 9:07 am

Posted in Internet

jQuery JCrop plugin, Chrome/Webkit: fails to initialize after the first attempt

leave a comment

I recently ran into a bug when using recent versions of Chrome and the jQuery JCrop plugin. I am adding some HTML to a jQuery UI modal window that contains the image I want to crop. I am initializing JCrop using the onload event of the image within this HTML. That worked fine in the past but stopped working sometime in the past year or so.

According to issue 7731 on chromium, the cause of this problem is that Webkit is more strict — the onload event is only triggered the first time the image is loaded. So the issue was the onload event triggered immediately when the modal window was shown — it triggered before the image was displayed (except for the first time). This is a tricky thing to work around. I verified that this was my issue by appending to the image URL the current timestamp (so + ‘?’ + new Date().getTime()) in order to force the browser to reload the image each time. That did fix the problem but it also introduced UI lag as the image had to be fetched each time a crop was attempted.

I put in this short term fix: put my JCrop initialization code in a function named crop and then (still bound to the load event), attempt to initialize it. If the image isn’t loaded, try again in 25ms up to 5 times. I can tell if the image is loaded by checking for a height > 0. The code:

    $('#cropbox').load(function (event) {
        var boxHeight = Math.floor($('#crop').closest('.ui-dialog').height() * 0.8);

        var $img = $(event.target);
        var productDiv = $('div#' + id);
        var sku = $('div.sku', productDiv).text();
        var product = productsData[sku];
        var height, width;

        // put crop loading code into function -- see comment below about chrome hack
        var crop = function () {
            height = $img.height();
            width = $img.width();

            var jcrop = $.Jcrop(
                ...
                });

            ...
        }

        // Ugly hack for chrome -- the load event triggers before the image is actually displayed/in DOM
        // but only on crop attempts after the initial one. One way to detect this is to check if the image
        // height is 0 -- if so, retry.
        // Update: issue probably this: http://code.google.com/p/chromium/issues/detail?id=7731#c12

        var worked = false;
        var attempts = 0;
        var attempt = function () {
            if (worked) return;

            height = $img.height();
            if (typeof height === 'number' && height > 0) {
                crop();
                worked = true;
            }
            else {
                attempts++;
                if (attempts < 5) {
                    // try again in 25 milliseconds
                    setTimeout(attempt, 25);
                }
                else {
                    alert('Bug with cropping image.');
                }
            }
        }

        attempt();
    });

I reported this problem in issue 63 for the JCrop plugin. Hopefully, there is a better way to do this however if you need a quick work around now...

Written by Cymen

November 10th, 2011 at 10:35 am