I’ve been doing more work in the ASP.Net Web API Beta that’s part of MVC 4. One of the rather odd things I’ve come across is that despite the automatic content negotiation, the ASP.Net custom error page (yellow screen of death) still gets returned when an error occurs by default. If all you want to do is fix this, you can disable it and pass it along with the following setting in the system.webServer node in the web.config:

<httpErrors existingResponse="PassThrough" />

You still get the correct http status code, and now the error message will get serialized to a string and returned in the requested content type.

My desired scenario was slightly more complex, though. In my view, a proper API should have a consistent error format and some meaningful error messages. So I wanted to return a custom class I wrote with all of the details that I wanted returned, and have it serialized by content negotiation into the correct type. Something like the following:

[Serializable]
[DataContract] public class MyCustomError {
[DataMember] public int Code { get; set; }
[DataMember]
public string Headline { get; set; }
  [DataMember]
public string Message { get; set; }

public MyCustomError() { }
public MyCustomError(int ErrorCode, string ErrorTitle, string ErrorDetails) { Code = ErrorCode; Message = ErrorDetails; Headline = ErrorTitle; } }

Take note of the Serializable attribute and DataContract bits, they are important on there. So now that I have the class, I need to get it returned. Now you need another class that inherits from the ExceptionFilterAttribute. This will be what actually configures the error response back to the client when an error occurs.

    public class CustomResponseException : ExceptionFilterAttribute
    {
        public override void OnException(HttpActionExecutedContext context)
        {
            HttpStatusCode responseStatus = HttpStatusCode.InternalServerError;
            if (context.Exception.Data.Contains("StatusCode"))
            {
                responseStatus = (HttpStatusCode)context.Exception.Data["StatusCode"];
            }
            if (context.Exception.Data.Contains("MyCustomError"))
            {
                context.Response = context.Request.CreateResponse<MyCustomError>(responseStatus, (MyCustomError)context.Exception.Data["MyCustomError"]);
            }
            else
            {                
                context.Response = context.Request.CreateResponse<MyCustomError>(responseStatus, new MyCustomError(ErrorNumber.UNSPECIFIEDERROR.ConvertToInt(), "Unknown error", "An error occurred."));
} base.OnException(context); } }

When I throw an error in code, I’m setting two pieces of data into the exception so that I can use it in this class. I put an instance of MyCustomError into the exception Data dictionary key “MyCustomError” so that I can return a specific message to the client. The second is a custom status code for cases like a 401 Unauthorized or a 404 NotFound, but much of the time I don’t set it as the 500 error is appropriate. Then I take these and put them in the context.Response, which along with the PassThrough attribute set in the web.config and the Serializable attribute on MyCustomError lets it automatically serialize to either XML or JSON according the client request type. (ErrorNumber in the code above is an enum that I’m using internally to signify the various custom error numbers for my API.) 

There’s one last step to actually get this hooked up. You have to either enable the CustomResponseException attribute globally, on a class level, or on a method level. If you want to do it class by class or method by method basis, use it as you would any attribute, by adding [CustomResponseException] above the method or class name. (Just like the [Serializable] on the MyCustomError class.) If you want it marked globally, go to the Application_Start method in Global.asax and add the line below.

GlobalConfiguration.Configuration.Filters.Add(new CustomResponseException());

Reference the links below for more information on the various parts of this.

Exception Filters

Another Custom Type Approach

httpErrors PassThrough setting

HttpStatusCode enum

Notes: This post was written during the Beta. I’ve updated the code for the release candidate on 2012-06-11.

I’ve been playing with the new MVC 4 Web API bits this week, and it seems really great so far. After playing around a bit, one of the first things that I realized I would need to do would be to fix the JSON serialization date format. Below are links to a couple of great articles that help when switching it from the DataContractSerializer to JSON.Net while it’s in Beta. Apparently JSON.Net will be there as the default once it releases, though.

Using JSON.Net with ASP.Net Web API

On the nightmare that is JSON Dates…

Media Formatters

Continuing on with a previous post where I did a C# version of the Delta-E algorithm, which is really mostly just converting RGB to CIE-L*ab. Getting the delta score at that point is really pretty simple. I’ve had a chance now to convert one of the better algorithms now as well. To use the 1994 version below, just replace the CompareTo function in my original post with the one below. You could also overload it and pass in the K_1 and K_2 values as parameters, or create an enum to pass in as a parameter. I would recommend using a couple of existing values and eyeballing them if you’re not sure if you should use the graphics or textiles ones. Dark blues, teal, and tan were the ones that I used.

There is obviously a performance hit as it’s significantly more complex than the older version. I haven’t done any performance testing to compare the two yet, but I may post those in the future if I get a chance. I may do the CMC and 2000 formulas as well when I get some more time.

 public int CompareTo(ColorFormulas oComparisionColor)
        {
            // Based upon the Delta-E (1994) formula at easyrgb.com (http://www.easyrgb.com/index.php?X=DELT&H=04#text4)
            // Also referenced the python ColorMath project for factoring in textile vs screen: https://github.com/gtaylor/python-colormath/blob/master/colormath/color_diff.py
            double CIE_L1 = CieL;                       //Color #1 CIE-L*ab values
            double CIE_a1 = CieA;
            double CIE_b1 = CieB;
            double CIE_L2 = oComparisionColor.CieL;     //Color #2 CIE-L*ab values
            double CIE_a2 = oComparisionColor.CieA;
            double CIE_b2 = oComparisionColor.CieB;

            double K_1 = 0.048;      // 0.045 graphic arts, 0.048 textiles
            double K_2 = 0.014;      // 0.015 graphic arts, 0.014 textiles

            double K_L = 2;         // 1 default, 2 textiles
            double K_C = 1;
            double K_H = 1;

            double xC1 = Math.Sqrt(Math.Pow(CIE_a1, 2) + Math.Pow(CIE_b1, 2));
            double xC2 = Math.Sqrt(Math.Pow(CIE_a2, 2) + Math.Pow(CIE_b2, 2));

            double S_L = 1;
            double S_C = 1 + K_1 * xC1;
            double S_H = 1 + K_2 * xC1;

            double delta_L = CIE_L1 - CIE_L2;
            double delta_C = xC1 - xC2;
            double delta_a = CIE_a1 - CIE_a2;
            double delta_b = CIE_b1 - CIE_b2;

            double delta_H = 0;
            double deltaHCalc = Math.Pow(delta_a, 2) + Math.Pow(delta_b, 2) - Math.Pow(delta_C, 2);

            // Can't do a sqrt of a negative num
            if (deltaHCalc < 0)
            {
                delta_H = 0;
            }
            else
            {
                delta_H = Math.Sqrt(deltaHCalc);
            }

            // Make double sure that delta_H is non-negative 
            if (Double.IsNaN(delta_H) || delta_H < 0) delta_H = 0;

            double L_group = Math.Pow(delta_L / (K_L * S_L), 2);
            double C_group = Math.Pow(delta_C / (K_C * S_C), 2);
            double H_group = Math.Pow(delta_H / (K_H * S_H), 2);

            double Delta94 = Math.Sqrt(L_group + C_group + H_group);
            return Convert.ToInt16(Math.Round(Delta94));
        }

I’ve had to do some work on color comparison recently. There are some really great algorithms out there for this, particularly at easyrgb.com. Unfortunately, I couldn’t find a good C# version of this anywhere, so I had to convert my own. So for my own future reference, and for anyone that needs it here it is.

public class ColorFormulas
    {
        public double X { get; set; }
        public double Y { get; set; }
        public double Z { get; set; }

        public double CieL { get; set; }
        public double CieA { get; set; }
        public double CieB { get; set; }

        public ColorFormulas(int R, int G, int B)
        {
            RGBtoLAB(R, G, B);
        }

        public void RGBtoLAB(int R, int G, int B)
        {
            RGBtoXYZ(R, G, B);
            XYZtoLAB();
        }

        public void RGBtoXYZ(int RVal, int GVal, int BVal)
        {
            double R = Convert.ToDouble(RVal) / 255.0;       //R from 0 to 255
            double G = Convert.ToDouble(GVal) / 255.0;       //G from 0 to 255
            double B = Convert.ToDouble(BVal) / 255.0;       //B from 0 to 255

            if (R > 0.04045)
            {
                R = Math.Pow(((R + 0.055) / 1.055), 2.4);
            }
            else
            {
                R = R / 12.92;
            }
            if (G > 0.04045)
            {
                G = Math.Pow(((G + 0.055) / 1.055), 2.4);
            }
            else
            {
                G = G / 12.92;
            }
            if (B > 0.04045)
            {
                B = Math.Pow(((B + 0.055) / 1.055), 2.4);
            }
            else
            {
                B = B / 12.92;
            }

            R = R * 100;
            G = G * 100;
            B = B * 100;

            //Observer. = 2°, Illuminant = D65
            X = R * 0.4124 + G * 0.3576 + B * 0.1805;
            Y = R * 0.2126 + G * 0.7152 + B * 0.0722;
            Z = R * 0.0193 + G * 0.1192 + B * 0.9505;
        }

        public void XYZtoLAB()
        {
            // based upon the XYZ - CIE-L*ab formula at easyrgb.com (http://www.easyrgb.com/index.php?X=MATH&H=07#text7)
            double ref_X = 95.047;
            double ref_Y = 100.000;
            double ref_Z = 108.883;

            double var_X = X / ref_X;         // Observer= 2°, Illuminant= D65
            double var_Y = Y / ref_Y;
            double var_Z = Z / ref_Z;

            if (var_X > 0.008856)
            {
                var_X = Math.Pow(var_X , (1 / 3.0));
            }
            else
            {
                var_X = (7.787 * var_X) + (16 / 116.0);
            }
            if (var_Y > 0.008856)
            {
                var_Y = Math.Pow(var_Y, (1 / 3.0));
            }
            else
            {
                var_Y = (7.787 * var_Y) + (16 / 116.0);
            }
            if (var_Z > 0.008856)
            {
                var_Z = Math.Pow(var_Z, (1 / 3.0));
            }
            else
            {
                var_Z = (7.787 * var_Z) + (16 / 116.0);
            }

            CieL = (116 * var_Y) - 16;
            CieA = 500 * (var_X - var_Y);
            CieB = 200 * (var_Y - var_Z);
        }

        ///
        /// The smaller the number returned by this, the closer the colors are
        ///
        ///
        /// 
        public int CompareTo(ColorFormulas oComparisionColor)
        {
            // Based upon the Delta-E (1976) formula at easyrgb.com (http://www.easyrgb.com/index.php?X=DELT&H=03#text3)
            double DeltaE = Math.Sqrt(Math.Pow((CieL - oComparisionColor.CieL), 2) + Math.Pow((CieA - oComparisionColor.CieA), 2) + Math.Pow((CieB - oComparisionColor.CieB), 2));
            return Convert.ToInt16(Math.Round(DeltaE));
        }

        public static int DoFullCompare(int R1, int G1, int B1, int R2, int G2, int B2)
        {
            ColorFormulas oColor1 = new ColorFormulas(R1, G1, B1);
            ColorFormulas oColor2 = new ColorFormulas(R2, G2, B2);
            return oColor1.CompareTo(oColor2);
        }
    }

Related to my post yesterday, one of the guys from Microsoft posted a white paper on the dev forums with instructions on upgrading a Metro App from the Visual Studio preview from Build to the Visual Studio 2011 Beta.

//Build to Windows 8 Consumer Preview White Paper

Original Post

It burned me. Since I was using C#, there is no upgrade path. The recommendation there is to create a new project and try to copy and paste in as much code as you can. I know what I’ll be doing this weekend.