Tuesday, August 17, 2010

Silverlight error message: Invalid or malformed application: Check manifest

I'm a perfectionist. I like nice namespaces. I recently created a new Silverlight project and it worked well -- until I "fixed" the namespaces. I got this message:

Invalid or malformed application: Check manifest

Checking the manifest in the XAP file revealed that my EntryPointType had not been updated to reflect the new namespaces. The Silverlight project setttings were holding on to the old name. The simple fix is on the Silverlight tab, Startup object. That combo box still has the old name.

Silverlight, WCF, IIS, HTTPS, BasicHttpBinding, and UserNamePasswordValidator

Creating a WCF service and Silverlight client that work together seems like a fairly common requirement. You would probably also require username/password and HTTPS. And it would be best if your development bindings were similar to deployment bindings. Here is what I used:
  • Visual Studio 2010, .NET 4.0
  • Windows 7
  • IIS 7
Note that you cannot use the built-in ASP.NET Development Server. It does not support HTTPS. And you cannot use Message credentials without HTTPS. Here is how I did it:
  • Make sure you have IIS and the "IIS Metabase and IIS6 configuration compatibility" installed.
  • Run Visual Studio as an Administrator so that you can access IIS configuration features from within Visual Studio.
  • Create a new WCF Service Application.
    • Change the debug options on the Project Properties, Web tab to Use Local IIS Web Server.
    • Press the Create a Virtual Directory button.
    • Test that your service provides metadata. (http://localhost/WcfService1/Service1.svc?wsdl)
    • Optional: Enable directory browsing on your virtual directory.
  • Setup IIS, IE, and Visual Studio for HTTPS.
    • In Internet Information Server (IIS) Manager, select the local computer and the "Server Certificates."
    • Create a Self-Signed Certificate.
    • On the web site (not the virtual directory), add a binding for HTTPS and test that it works. (https://localhost/WcfService1/Service1.svc)
    • In Internet Explorer, install the self-signed certificate, placing the certificate in the Trusted Root Certification Authorities.
    • Change the WCF project's Project URL to use https and the machine name, instead of http and the localhost. (https://mishael/WcfService1)
    • Test that Visual Studio can launch the web service view in Internet Explorer without a certificate error.
  • Create a new Silverlight Application.
    • Add a Service Reference to the WCF service.
    • Add a button that calls the WCF service.

      int counter = 0;
      private void button1_Click(object sender, RoutedEventArgs e)
      {
          var c = new Service1Client();
          c.GetDataCompleted += c_GetDataCompleted;
          c.GetDataAsync(++counter);
      }
      
      void c_GetDataCompleted(object sender, GetDataCompletedEventArgs e)
      {
          if (e.Error != null)
              textBlock1.Text = e.Error.Message;
          else
              textBlock1.Text = e.Result;
      }
    • Edit the generated ServiceReferences.ClientConfig to use https instead of http.
    • Edit the generated ServiceReferences.ClientConfig to use security mode of Transport.

      security mode="Transport"
  • Using the WCF Service Configuration Tool, update the WCF service as follows:
    • Create a new service, with the endpoint address pointing to the services.
    • Create a New Binding Configuration for basicHttpBinding. On the Security tab, change the mode to Transport.
    • Use the new binding configuration for the service endpoint. It will be something like this:

      
        
          
            
          
        
      
      
        
          
        
      
    • Testing the service endpoint with Internet Explorer (https://mishael/WcfService1/Service1.svc) reveals that there is an issue with multipleSiteBindingsEnabled. Comment out the multipleSiteBindingsEnabled attribute in the web.config.
  • Test that the Silverlight app can successfully communicate with the WCF service using HTTPS, including stopping at breakpoints in both the Silverlight client and WCF service.
  • Enable client username and password authentication as follows:
    • In the Web.config, switch the security from "Transport" to "TransportWithMessageCredential". and a client message credential type of "UserName".


      
         
      
    • In the ServiceReferences.ClientConfig, switch the security from "Transport" to "TransportWithMessageCredential".
    • Define a UserNamePasswordValidator class to do the username and password validation. (The base class UserNamePasswordValidator is in System.IdentifyModel.dll.)

      namespace WcfService1
      {
          public class MyUserNamePasswordValidator: UserNamePasswordValidator
          {
              public override void Validate(string userName, string password)
              {
                  if (userName == "Wally" && password == "password")
                      return;
                  throw new SecurityTokenValidationException("Unrecognized user.");
              }
          }
      }
    • Update the service behavior to use the new UserNamePasswordValidator class.

      
        
          
            
          
        
      
    • Update the Silverlight client code set a username and password.

      var c = new Service1Client();
      c.ClientCredentials.UserName.UserName = "Wally";
      c.ClientCredentials.UserName.Password = "password";
      
    • Using breakpoints, verify that the UserNamePasswordValidator class is being called.
  • In your WCF operation, throw a FaultException. Testing will reveal that on the client, all you get is a CommunicationException. Improve the availability of exception messages sent to the client as follows:
    • Update the Web.config to includeExceptionDetailInFaults.
      serviceDebug includeExceptionDetailInFaults="true"
    • Create a BehaviorExtensionElement class using the code here.
    • Update the Web.config to include this behavior extension.
      
        
          
        
      
      
    • Update the Web.config to add the extension to the endpoint behavior.
      
              
                
              
            
      
    • Update the Web.config to use this behavior for your endpoint.
      behaviorConfiguration="SilverlightFaultBehavior"

    Monday, August 16, 2010

    Setting up HTTPS for local development without installing IIS

    As the subject implies, I wanted to do some web development that used HTTPS. The WebDev.WebServer (aka Cassini) that comes with Visual Studio does not support HTTPS. I did not want to require IIS for myself or my colleagues.

    I'm not entirely sure of all the details, but this seemed to work:

    • Create a test certificate as described here. You must run as an Administrator.

      > makecert -ss My -sr LocalMachine -sky exchange -r -n "CN=Wallace Kelly" -sk WallaceKelly -pe
      
    • Get the new certificate's "thumbnail" as described here. I used the MMC snap in.
    • Configure a port with the SSL certificate, as described here. The special IP address 0.0.0.0 matches any IP address for the local machine. The certhash is the "thumbnail" without the spaces. The appid is a GUID. I used the GUID for the WebServer2, from the AssemblyInfo.cs. I'm not sure if this can be any GUID.

      > netsh http add sslcert ipport=0.0.0.0:8080 certhash=4dbcbe2656f62af17ceba1f760
      ba7d065fd919bf appid={D7A0778F-A61C-463F-8C39-893DF0AA3748}
      
      SSL Certificate successfully added
      
      
      > netsh http show sslcert
      
      SSL Certificate bindings:
      -------------------------
      
          IP:port                 : 0.0.0.0:8080
          Certificate Hash        : 4dbcbe2656f62af17ceba1f760ba7d065fd919bf
          Application ID          : {d7a0778f-a61c-463f-8c39-893df0aa3748}
          Certificate Store Name  : (null)
          Verify Client Certificate Revocation    : Enabled
          Verify Revocation Using Cached Client Certificate Only    : Disabled
          Usage Check    : Enabled
          Revocation Freshness Time : 0
          URL Retrieval Timeout   : 0
          Ctl Identifier          : (null)
          Ctl Store Name          : (null)
          DS Mapper Usage    : Disabled
          Negotiate Client Certificate    : Disabled
      
      
      
      
    • Use WebDev.WebServer2, found here.

      > WebDev.WebServer2.exe /path:"c:\temp" /prefix:"http://localhost" /port:8080
      

    Wednesday, May 19, 2010

    Custom numeric string formatting, including engineering notation

    I needed to display numbers in an engineering application. The customer wanted the numbers formatted nicely, with about four significant digits and engineering notation. .NET has very flexible number formatting. However, it lacks standard formatting into engineering notation.

    The extension point for formatting numeric strings is through the IFormatProvider and ICustomFormatter interfaces. I implemented a format provider for the engineering notation. However, exclusively using engineering notation was awkward in our application. As an alternative to exclusively using engineering notation, I decided on the following format, which mixes four significant digits, engineering notation, and thousand separators:

    3.1416E-05  31.42E-06
    0.00031416  314.2E-06
    0.0031416   0.003142
    0.031416    0.03142
    0.31416     0.3142
    3.1416      3.142
    31.416      31.42
    314.16      314.2
    3141.6      3,142
    31416       31,416
    3.1416E+05  314,159
    3.1416E+06  3.142E+06
    3.1416E+07  31.42E+06
    3.1416E+08  314.2E+06
    3.1416E+09  3.142E+09
    

    In case you want similar formatting, here is the class that implements it:

    public class EngineeringFormatProvider : IFormatProvider, ICustomFormatter
    {
        public object GetFormat(Type formatType)
        {
            return (formatType == typeof(ICustomFormatter)) ? this : null;
        }
    
        public string Format(string format, object arg, IFormatProvider formatProvider)
        {
            // for doubles, store the value of the double
            var val = Double.NaN;
            if (arg is Double)
                val = (double)arg;
    
            // for other types, try to convert to a double
            else
            {
                var typeConverter = TypeDescriptor.GetConverter(arg);
                if (typeConverter.CanConvertTo(typeof(Double)))
                {
                    try
                    {
                        val = (double)typeConverter.ConvertTo(arg, typeof(Double));
                    }
                    catch
                    {
                        // ignore
                    }
                }
    
                // if cannot convert, return a default value
                if(Double.IsNaN(val))
                    return arg == null ? String.Empty : arg.ToString();
            }
                    
            // for special cases, just write out the string
            if (val == 0.0 || Double.IsNaN(val) || Double.IsInfinity(val))
                return val.ToString();
    
            else
            {
                // calculate the exponents, as a power of 3
                var exp = Math.Log10(Math.Abs(val));
                var exp3 = (int)(Math.Floor(exp / 3.0) * 3.0);
    
                // calculate the coefficient
                var coef = val / Math.Pow(10, exp3);
    
                // special case, for example 0.3142
                if(exp3 == -3 && Math.Abs(coef / 1000.0) < 1 && Math.Abs(coef / 1000.0) > 0.1)
                    return String.Format("{0:G4}", val);
    
                // for "small" numbers
                if(exp3 <= -6)
                    return String.Format("{0:G4}E{1}{2:00}", coef, exp3 > 0 ? "+" : "", exp3);
    
                // for "large" numbers
                if(exp >= 6)
                    return String.Format("{0:G4}E{1}{2:00}", coef, exp3 > 0 ? "+" : "", exp3);
    
                // for numbers needing thousand separators
                if (exp >= 3)
                    return String.Format("{0:N0}", val);
    
                // default
                return String.Format("{0:G4}", val);
            }
        }
    }
    

    Here is how to use it:

    var p = new EngineeringFormatProvider();
    var s = String.Format(p, "{0}", number);

    Tuesday, May 18, 2010

    Closing a window or dialog box when an escape key is pressed in WPF

    When you pop up a dialog box, users expect to be able to press the ESC key to close the dialog box. It can be quite annoying otherwise. In WPF, the easiest way to do that is to set the IsCancel property of your close button like this:

    <Button Content="Close" Click="OnClose" IsCancel="True" />
    

    On a recent project, however, I did not have a close button to set IsCancel on. The solution is to use WPF commands and input gestures. Here is an example:

    <Window.CommandBindings>
       <CommandBinding Command="Close" Executed="OnCloseCmdExecuted" />
    </Window.CommandBindings>
    
    <Window.InputBindings>
       <KeyBinding Command="Close" Key="Escape" />
    </Window.InputBindings>
    

    private void OnCloseCmdExecuted(object sender, ExecutedRoutedEventArgs e)
    {
       this.Close();
    }
    

    Thursday, April 22, 2010

    MSBUILD 4.0, XmlPeek, XmlPoke, and MSB4036

    I installed Visual Studio 2010. I was creating a new MSBUILD file and was delighted to find the new XmlPeek and XmlPoke tasks have been added to .NET Framework 4.0. However, when I tried the following:

    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <Target Name="XmlPokeTest">
        <XmlPoke etc.../>
      </Target>
    </Project>
    

    ... I get the dreaded task was not found message:

    Microsoft (R) Build Engine Version 4.0.30319.1 Copyright (C) Microsoft Corporation 2007. All rights reserved. error MSB4036: The "XmlPoke" task was not found.

    The error has a standard set of suggested solutions, including this one:

    Check the following:
    3.) The task is correctly declared within the project file,
    or in the *.tasks files located in the
    "C:\Windows\Microsoft.NET\Framework\v2.0.50727" directory.
    

    This works:

    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <UsingTask TaskName="Microsoft.Build.Tasks.XmlPoke"
                 AssemblyName="Microsoft.Build.Tasks.v4.0, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
      <Target Name="XmlPokeTest">
        <XmlPoke etc.../>
      </Target>
    </Project>
    

    There is a Microsoft.Commmon.Tasks file in the C:\Windows\Microsoft.NET\Framework\v4.0.30319 folder that lists the new MSBuild 4.0 tasks, like XmlPeek and XmlPoke. But MSBuild 4.0 is apparently still using the Microsoft.Commmon.Tasks file in C:\Windows\Microsoft.NET\Framework\v2.0.50727.

    Using the toolsversion switch also works, presumably causing MSBuild to reference the new 4.0 Microsoft.Common.Tasks file:

    msbuild /toolsversion:4.0 XmlPokeTest.proj

    For future reference, the 4.0 Microsoft.Common.Tasks file includes these entries that are not included in the the 2.0 version:

    AssignProjectConfiguration
    AssignTargetPath
    CreateCSharpManifestResourceName
    CreateVisualBasicManifestResourceName
    FindAppConfigFile
    FindInList
    FormatUrl
    FormatVersion
    GenerateTrustInfo
    GetReferenceAssemblyPaths
    Move
    RequiresFramework35SP1Assembly
    ResolveManifestFiles
    ResolveNonMSBuildProjectOutput
    UpdateManifest
    XmlPeek
    XmlPoke
    XslTransformation
    

    Thursday, April 15, 2010

    TemplateBinding and the Visual Studio 2010 WPF Designer

    I upgraded to Visual Studio 2010. I was looking forward to the improved WPF designer. However, when I converted one of my projects I found that my WPF windows would not display properly. My windows that displayed properly in the VS2008 WPF designer were not displaying in the VS2010 WPF designer. Compiling and running worked fine in both. It was simply the designer complaining.

    In VS2010, the designer complained about the window: "An error occurred while finding the resource dictionary."

    In VS2010, the resource dictionary complained: "The type 'TemplateBinding' was not found. Verify that you are not missing an assembly reference and that all referenced assemblies have been built."

    I found that my old resource dictionary had this default XML namespace for the XAML:
    xmlns="http://schemas.microsoft.com/netfx/2007/xaml/presentation"

    I found that a new resource dictionary created in VS2010 uses this default XML namespace:
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    Replacing the default namespace in my old resource dictionary solved the problem.

    Hope this helps you!

    Wednesday, March 10, 2010

    Registering for Dependency Property Changed Events

    WPF dependency properties have built-in support for change notification. However, it was not until last week that I realized that I had never registered for a change on a dependency property (at least not one that lacks an explicitly-defined event.) I have made use of the feature many times while data binding. But I had never had to register my own handler for a dependency property changed event.

    The registration mechanism is non-intuitive. So I defined the following extension methods:

    public static void AddDependencyPropertyChangedEventHandler(this DependencyObject obj, DependencyProperty dp, EventHandler handler)
    {
        var dpd = DependencyPropertyDescriptor.FromProperty(dp, obj.GetType());
        dpd.AddValueChanged(obj, handler);
    }
     
    public static void RemoveDependencyPropertyChangedEventHandler(this DependencyProperty obj, DependencyProperty dp, EventHandler handler)
    {
        var dpd = DependencyPropertyDescriptor.FromProperty(dp, obj.GetType());
        dpd.RemoveValueChanged(obj, handler);
    }
    

    Wednesday, February 24, 2010

    Calculating nice chart axis ranges

    I was working on a project that required calculating nice ranges for chart axes. I found a useful discussion here.

    Here is what I used in C# and so far it is working adequately:

    var numGridLines = 5;
    var magnitude = Math.Floor(Math.Log10((maxValue - minValue) * 1.1));
    var basis = Math.Pow(10, (magnitude - 1));
    var margin = (maxValue - minValue) * 0.1;
    var axisMax = Math.Ceiling((maxValue + margin) / basis) * basis;
    var axisMin = Math.Floor((minValue - margin) / 1.1 / basis) * basis;
    var majorGrid = Math.Floor((axisMax - axisMin) / basis / numGridLines) * basis;
    

    Friday, February 12, 2010

    What do you like about Windows 7?

    People ask me if Windows 7 is any better. Sure. Some people are wondering about the security popups and compatibility with old programs. Those questions already have lots of press. But, I'm personally more interested in the small usability features that come in handy several times a day. Here are the ones I've noticed:

    1. The entire organization of the task bar is a huge improvement. Basically the concept of Quick Links has been merged into the task bar functionality. (It acts more like OS X.) In previous versions of Windows, my task bar was always full of running programs, making the task bar difficult to use. Now my task bar stays about half full and my programs (quick links and running) are much easier to access.
    2. Closely related to the previous, is the right click behavior on the task bar icons.
    3. The Recent Document has been replaced. Now recent documents appear to the right of any program that is displayed on the Start's popup. So Word has its own recent documents. Excel has its own etc.
    4. Snap is something I use regularly. You can drag an open application to the top or side of the workspace and it resizes to fill the screen or half of the screen as appropriate. Grabbing an application's border and dragging it towards the top resizes the application to the height of the workspace.
    I notice these features several times a day. They are the main reason I like Windows 7.

    Wednesday, February 10, 2010

    WPF menus that go up

    I needed a menu docked to the bottom of an application's window. Docking to the bottom of the window is no problem. However, it did not work well, because by default, WPF menus drop down. I needed it to drop up. I need behavior like the Windows Start menu when it is docked on the bottom of the workspace. I looked for a PopupDirection or some such property -- no luck.

    I found a solution.

    Using Blender, edit a copy of a menu's ItemContainerStyle. The default style has two Popup elements with a Placement property. Placement = "Top" is a valid option.