Showing posts with label Presentation Layer. Show all posts
Showing posts with label Presentation Layer. Show all posts

Monday, April 09, 2012

More On Closing WCF Connections

Some time ago I blogged about how to implement a WCF client in C# using VS2008. In particular I mentioned that implementing the client side code with a using statement may potentially lead to problems as – against their own advice – Microsoft chose to implement the Dispose() method of class System.ServiceModel.ClientBase<TChannel> in such a way that it can throw exceptions. (Dispose() implementations should not throw exceptions.) This implementation that violates Microsoft’s own guideline is also described in an article where Microsoft recommends not to use “using” when working with WCF clients.

In this blog post I’ll revisit the options for handling client side code. In the meantime I’ve moved to VS2010 and I’m using .NET 4.0. To get started let’s recall the code from back then:

var client = new PondServiceClient();

try {
   _pondStatusMessage.Text = _pondNameTextBox.Text +
      (client.IsFrozen(_pondNameTextBox.Text) ?
      " is frozen." : " free of ice.");
   client.Close();
}
catch (CommunicationException ex) {
   // Handle exception
   client.Abort();
}
catch (TimeoutException ex) {
   // Handle exception
   client.Abort();
}
catch (Exception ex) {
   // Handle exception
   client.Abort();
}

So the canonical form (also described on MSDN) is to check for CommunicationException and TimeoutException. If the service defines Service Fault's you may want to catch those exceptions (FaultException<T>) as well.

It would be great if there were ways to fix this problem as there is one more issue with using the canonical way. Imagine you have lots of touch points between your client and a service. Wouldn’t it be nice if you could avoid all that try-catch business? It looks like a lot of code duplication after all.

Marc Gravell’s Solution

One possible solution is described by Marc Gravell in his blog. He makes extensive use of generics. Using Marc’s solution the above code would look something like this:

using (var client = new Proxy().Wrap()) {
   _pondStatusMessage.Text = _pondNameTextBox.Text +
      (client.BaseObject.IsFrozen(_pondNameTextBox.Text) ?
      " is frozen." : " free of ice.");
}

I agree with Marc that this solution would be safe, easy to call and would eliminate the code duplications. His solution calls the service client’s Dispose() method (ClientBase<TChannel>.Dispose()) but wraps it inside a try-catch construct. If an exception is thrown by the Dispose() it is swallowed.

The first concern I have with this solution is that it doesn’t call Abort() and Close() respectively as per Microsoft’s recommendation. It just swallows the exception that might be thrown by the Dispose method.

The second concern I have is that the expression “new Proxy().Wrap()” doesn’t appear very intuitive and easy to understand. This is probably a minor point as with more experience in using this solution one can will become used to it.

Jeremy Jameson’s Solution

Another option can be found at Jeremy Jameson’s blog. Jeremy suggests to derive a class and add a new implementation for Dispose(). To stay with the pond service example, that new class would then look as follows:

public class PondServiceClientWithDisposeFix 
   : PondServiceClient, IDisposable {
   void IDisposable.Dispose() {
      if (this.State == CommunicationState.Faulted) {
         this.Abort();
      }
      else if (this.State != CommunicationState.Closed) {
         this.Close();
      }
   }
}

With this class in place the implementation of the client side could then be re-written as follows:

using(var client = new PondServiceClientWithDisposeFix()) {
   _pondStatusMessage.Text = _pondNameTextBox.Text +
      (client.IsFrozen(_pondNameTextBox.Text) ?
      " is frozen." : " free of ice.");
}

Very elegant, easy to understand and correct by the looks of it. I was tempted to use this option if it wasn’t for a concern that I have with this. With reverse engineering it is possible to find out what ClientBase<TChannel>.Dispose() does. When Jeremy wrote his blog (March 2010) the Dispose() implementation simply called Close().

My concern is that the new implementation doesn’t call the base class implementation at all. By the way the PondServiceClient class is declared partial so the Dispose method could probably be implemented as an extension method as well. As long as the base class implementation is not called, this couldn’t resolve my concern, though. What if Microsoft at any time decides to change the implementation of ClientBase<TChannel>.Dispose()? This kind of change typically happens – thanks, Murphy! – we we expect it the least.

Even if the implementation was never changed, there is a small thing that concerns me. Microsoft has included a little note regarding the use of the ClientBase<TChannel>.State property:

image

So, Jeremy’s solution probably will work. But it is against Microsoft’s recommendation of not using the State property. In particular I get nervous because of the term “race condition”. If problems occur because of race conditions these are typically hard to find and resolve, therefore a very expensive type of issue.

Therefore if we want to follow that recommendation we are back to square one. We would have to surround the use of ClientBase<TChannel> derived objects with boilerplate try-catch statements.

Using Anonymous Methods

Basically the problem is that in order to remove the code duplication a pair of code snipped has be executed before and after the service invocation. Proper handling of communication objects almost sounds like an aspect… so for a moment I even considered looking into libraries like DynamicProxy2 or Ninject. On second thought, though, these felt like overkill for something that appears very simple.

Enter anonymous methods. Basically you can pass a block of code to a different method that does things, executes the block of code, maybe does other things, then returns. How does this apply to the code snippet for the pond service example above. Let’s try to highlight with colors what the boiler plate code is and what the code is that is different:

image

The code within green rectangles is the actual implementation while the code in the orange rectangles is the boilerplate code. Note, how the orange pieces surround the second green piece.

The way to simply this is using a class that works like an interceptor. I implemented a class called ServiceClientInterceptor and it’s main method now looks as follows, again using green and orange rectangles as above:

image

As you can see the green rectangle simply invokes the function that was passed in. With the ServiceClientInterceptor in place you can now write the client side code as follows:

using (var client = new PondServiceClient()) {
   new ServiceClientInterceptor(client).Invoke(() => {
      _pondStatusMessage.Text = _pondNameTextBox.Text +
         (client.IsFrozen(_pondNameTextBox.Text) ?
         " is frozen." : " free of ice.");
   });
}

Line 2 in this example show the beginning of an anonymous method that is passed in as a parameter to the Invoke() method. The cool thing is that inside of the anonymous method you have access to the variables that are accessible at the point of where the anonymous method is defined. It is not limited to where the intercept invokes the execution of that anonymous method.

As a result you can now wrap service invocations with try-catch statements without code duplication.


With this general concept working there are of course further questions that I haven’t covered in this blog post. For example, what if you want reuse the service client for further invocations in the same using block? What if you had multiple service clients that are used within the same anonymous method? I’ll leave these to you for further explorations as there several options in each case.

The solution presented here meets the following requirements:

  • Allows use of using construct
  • Properly closes or aborts WCF connections depending on exception thrown
  • Avoids code duplication
  • Does not make use of ClientBase<TChannel>.State property as per Microsoft’s recommendation

To complete this blog post, below is the full source for the ServiceClientInterceptor class. In that case I have changed the parameter type of the Invoke method to Action. In the screenshots above I still used ServiceMethod which had an identical definition but was the result of earlier experimentation. The Action delegate encapsulates a method that has no parameters and does not return a value. As always you are welcome to use this code at your own risk.

If you know of a solution better than any of the ones mentioned in this post I'd like to hear from you. Happy coding!

public class ServiceClientInterceptor {
   public ServiceClientInterceptor(
         ICommunicationObject serviceClient) {
      _serviceClient = serviceClient;
   }

   public void Invoke(Action func) {
      try {
         func.Invoke();
         _serviceClient.Close();
      }
      catch (CommunicationException ex) {
         _serviceClient.Abort();
         // Handling and/or re-throwing exception is 
         // application specific
      }
      catch (TimeoutException ex) {
         _serviceClient.Abort();
         // Handling and/or re-throwing exception is 
         // application specific
      }
      catch (Exception ex) {
         _serviceClient.Abort();
         // Handling and/or re-throwing exception is 
         // application specific
      }
   }

   private ICommunicationObject _serviceClient;
}

Saturday, December 24, 2011

Razor, MVC3, Client-Side Validation and Multiple Submit Buttons

In a details view for creating a new model object I wanted to replace the Cancel link with a Cancel button. I wanted both to be buttons as I felt that to be more consistent. I didn’t realize that I would be up for a surprise when I placed two submit buttons into a single form since, of course, not matter what button I would click I would always end up in the same controller method. It was even worse. As client-side validation was enabled, clicking the Cancel button would perform client-side validation and not even make it to the server.

I googled and found a couple of ideas for how to handle multiple submit buttons. For example one type of suggestions is based on implementing a class derived from ActionMethodSelectorAttribute, for example here or here. Another type of suggestions is based on implementing a class derived from ActionNameSelectorAttribute, for example here.

I couldn’t get any of these to work the way I wanted. I found that they would work only when I disabled client-side validation or JavaScript on the client altogether. Only in these cases, and by giving the submit button a name using the ‘name’ attribute, would the button value be included in the request. Therefore this was just a partial solution as I wanted to support both scenarios (JavaScript disabled, JavaScript enabled). I tried the actionmethod attribute on the input element but either I used it incorrectly or the handling of this new HTML 5 element is not yet correctly handled by either the browsers or MVC on the server. I didn’t investigate this in more detail.

Here is the solution that worked for me.

First I implemented a JavaScript function which I placed at the end of the view (.cshtml):

<script type="text/javascript">
   function OnFormButtonClick(action, validate) {
      if (!validate) {
         document.forms[0].noValidate = true;
         document.forms[0].action = '' + action;
         document.forms[0].submit();
      }
}
</script>

The first parameter of this short method is the name of the action (controller method) to be invoked on the server side while the second parameter determines whether or not to validate on the client side. Of course the latter would only kick in when JavaScript is enabled on the client side. If you want to use multiple submit buttons in several place you may want to put this function in a shared file such as ‘_Layout.cshtml’ or similar.

With the JavaScript function in place I then added the two submit buttons to the Razor view (HTML form) as follows:

<p>
   <input type="submit" value="Create" name="button"
    onclick="OnFormButtonClick('Create', true);" />
   <input type="submit" value="Cancel" name="button"
    onclick="OnFormButtonClick('Cancel', false);" />
</p>

This would now work with JavaScript enabled on the client. How about the scenario when JavaScript was disabled? In that case submitting the form would always submit to the same action (‘Create’ in my case) no matter what button was clicked. Some server side code was required to distinguish this. This is the point I added a class which is derived from ActionNameSelectorAttribute:

/// <summary>
/// Attribute that helps MVC with selecting the proper method when multiple submit buttons
/// exist in a single form.
/// </summary>
/// <remarks>The implementation is partially based on  </remarks>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MultiSubmitButtonAttribute : ActionNameSelectorAttribute {
   public override bool IsValidName(ControllerContext controllerContext, 
                                    string actionName, 
                                    MethodInfo methodInfo) {
      // Implementation derived from:
      // http://blog.maartenballiauw.be/post/2009/11/26/Supporting-multiple-submit-buttons-on-an-ASPNET-MVC-view.aspx
      if (controllerContext.RequestContext.HttpContext.Request["button"] != null) {
         // JavaScript disabled.
         return controllerContext.RequestContext.HttpContext.Request["button"] == methodInfo.Name;
      }

      return actionName.Equals(methodInfo.Name, StringComparison.InvariantCultureIgnoreCase) 
         || actionName.Equals("Action", StringComparison.InvariantCultureIgnoreCase);
   }
}

The first if()-statement in this implementation yields to true only if JavaScript is disabled on the client. In that case the request contains the information about which submit button was clicked and this can be compared to the name of the controller method (bear with me for a little longer to see how this will work). Having this new attribute available I was now able to add it to the controller methods handling the two cases (‘Create’ and ‘Cancel’):

[HttpPost]
[MultiSubmitButton]
public ActionResult Create(FormCollection collection) {
   // TODO: insert your 'Create' logic here
   return RedirectToAction("Index");
}

[HttpPost]
[MultiSubmitButton]
public ActionResult Cancel() {
   return RedirectToAction("Index");
}

When MVC tries to route the action to a controller method it will now also invoke the IsValidName method in the MultiSubmitButtonAttribute class. The two scenarios now work as follows:

Case 1 - JavaScript enabled: The little JavaScript function is executed on the client side and an appropriate action will be requested. The action is simply routed to the controller method of the same name. Depending on the second parameter of the call to the JavaScript function (and subject to server side settings in web.config) client-side validation is executed or not.

Case 2 – JavaScript disabled: The client includes the name of the submit button and the MultiSubmitButtonAttribute helps MVC to select the correct controller method.

Extending HtmlHelper to Simplify View Implementation

There is a way to simplify the view implementation by extending the HtmlHelper class as follows:

public static class HtmlHelperExtensions {
   public static MvcHtmlString SubmitButton<T>(this HtmlHelper<T> helper, string value, string action, bool validate) {
      return new MvcHtmlString(String.Format("<input type=\"submit\" value=\"{0}\" name=\"button\" onclick=\"OnFormButtonClick('{1}', {2});\" />", value, action, validate ? "true" : "false"));
   }
}

With this the submit buttons can be coded like this:

@* Namespace of the HtmlHelper.SubmitButton() implementation: *@
@using Web.Helpers; 

... other code for Razor based view

<p>
   @Html.SubmitButton("Create", "Create", true)
   @Html.SubmitButton("Cancel", "Cancel", false)
</p>

Note that although it appears as if the first two parameters here are duplicated, they are not. The first parameter is the label that appears on the submit button and you may want to localize it. The second parameter is the name of the action which you typically don’t want to change. Even if everything is in the same language (e.g. English) they can be the same but don’t have to.

Automatically Injecting JavaScript

So far the solution requires manually adding the OnFormButtonClick() function either to the Razor view or to have it in some shared file. I would like to remove this by making the HtmlHelper.SubmitButton<T>() implementation a little smarter:

public static class HtmlHelperExtensions {
   public static MvcHtmlString SubmitButton<T>(this HtmlHelper<T> helper, string value, string action, bool validate) {
      var javaScript = string.Empty;
      const string functionName = "_OnFormButtonClicked";
      if (!helper.ViewData.ContainsKey(functionName)) {
         helper.ViewData.Add(functionName, true);
         const string linefeed = " \n\r";
         // Inspiration for the following JavaScript function from:
         // http://www.javascript-coder.com/html-form/html-form-action.phtml
         javaScript = "<script type=\"text/javascript\">" + linefeed
                    + "   function " + functionName + "(action, validate) {" + linefeed
                    + "      if (!validate) {" + linefeed
                    + "         document.forms[0].noValidate = true;" + linefeed
                    + "         document.forms[0].action = '' + action;" + linefeed
                    + "         document.forms[0].submit();" + linefeed
                    + "      }" + linefeed
                    + "   }" + linefeed
                    + "</script>" + linefeed;
      }
      return new MvcHtmlString(String.Format("{0}<input type=\"submit\" value=\"{1}\" name=\"button\" onclick=\"{2}('{3}', {4});\" />", javaScript, value, functionName, action, validate ? "true" : "false"));
   }
}

The basic idea is that if the JavaScript function doesn’t exist yet in the view this code adds it. Then it adds one key to the ViewData. If that key is already present this code assumes the JavaScript function has already been added. With this, the JavaScript function can now be removed from the view and all that is needed is this:

  1. MultiSubmitButtonAttribute applied to appropriate controller methods
  2. Use of HtmlHelper.SubmitButton() in view definition

The JavaScript injection is taken care of automatically. Happy coding!

Sunday, August 01, 2010

Using HTTP Response Filter in ASP.NET

In an ASP.NET application if you want to manipulate the HTML code after it has been rendered but before it is being sent back to the client, you can use a custom filter to intercept that stream and modify it according to your needs.

One scenario is injecting elements that in turn can be used by the browser in conjunction with a CSS to modify the visual appearance. Not in all cases you have access to the source code for the pages.

To demonstrate how to do that I’ll use a simple PassThroughFilter that simply forwards all method calls to the original filter.

Let me show you first how you can register the filter. There are many different places, essentially everywhere where the HttpContext.Response object is accessible. Throughout the processing of a request there are multiple events that you can use to plug in your filter. You can find a list of those events in an article that describes using an HTTP Module for implementing an intercepting filter.

But you don’t have to use an HTTP Module. You can implement your filter and then register it in various places, for example in the pages OnInit(EventArgs) override:

protected override OnInit(EventArgs e) {
   Response.Filter = new PassThroughFilter(Response.Filter);
   base.OnInit(e);
}

Another option is to use the global application object for the registration (:

public class MvcApplication : HttpApplication {
   protected void Application_Start() {
      AreaRegistration.RegisterAllAreas();
      RegisterRoutes(RouteTable.Routes);
   }

   protected void Application_BeginRequest() {
      Response.Filter = new PassThroughFilter(Response.Filter);
   }

   private static void RegisterRoutes(RouteCollection routes) {
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

      routes.MapRoute(
          "Default", // Route name
          "{controller}/{action}/{id}", // URL with parameters
          new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
      );

   }
}

In this example I’m showing this in an MVC 2 based application but the same works for a WebForms based application, too.

Where you intercept depends on your specific requirements. Once you have the basic interception in place you can manipulate the HTML stream before it is sent back to the client.

So here is the full source code for the PassThroughFilter class. Happy Coding!

using System.IO;

namespace WebPortal {
   internal class PassThroughFilter : Stream {
      public PassThroughFilter(Stream originalFilter) {
         _originalFilter = originalFilter;
      }

      #region Overrides of Stream

      public override void Flush() {
         _originalFilter.Flush();
      }

      public override long Seek(long offset, SeekOrigin origin) {
         return _originalFilter.Seek(offset, origin);
      }

      public override void SetLength(long value) {
         _originalFilter.SetLength(value);
      }

      public override int Read(byte[] buffer, int offset, int count) {
         return _originalFilter.Read(buffer, offset, count);
      }

      public override void Write(byte[] buffer, int offset, int count) {
         _originalFilter.Write(buffer, offset, count);
      }

      public override bool CanRead {
         get { return _originalFilter.CanRead; }
      }

      public override bool CanSeek {
         get { return _originalFilter.CanSeek; }
      }

      public override bool CanWrite {
         get { return _originalFilter.CanWrite; }
      }

      public override long Length {
         get { return _originalFilter.Length; }
      }

      public override long Position {
         get { return _originalFilter.Position; }
         set { _originalFilter.Position = value; }
      }

      #endregion

      private readonly Stream _originalFilter;
   }
}

Sunday, July 18, 2010

Selenium RC and ASP.NET MVC 2: Controller Invoked Twice

Admittedly MVC (as of writing I use ASP.NET MVC 2) has been designed from the ground up for automated testability (tutorial video about adding unit testing to an MVC application). For example you can test a controller without even launching the ASP.NET development web server. After all a controller is just another class in a .NET assembly.

However, at some point you may want to ensure that all the bits and pieces work together to provide the planned user experience. That is where acceptance tests enter the stage. I use Selenium for this, and a few days ago I hit an issue that turned out to be caused by Selenium server version 1.0.3. Here are the details.

The symptom that I observed was that a controller action was hit twice for a single Selenium.Open(…) command. First I thought that my test was wrong, so I stepped through it line by line. But no, there was only one open command for the URL in question. Next I checked my implementation, whether maybe accidentally I had created some code that implicitly would call or redirect to the same action. Again, this wasn’t the case as each time when I hit the break point on the action controller there was nothing in the call stack.

Then I used Fiddler (a web debugging proxy) for a while and yes, there were indeed a HEAD request and a GET request triggered by the Selenium.Open(…) command. And even more interesting, when I ran my complete test suite I found several cases where the GET request was preceded by a HEAD request for the same URL.

The concerning bit, however, was that I couldn’t find a way how to reproduce this with a browser that I operated manually. Only the automated acceptance tests through Selenium RC created this behavior.

For a moment I considered trying to use caching on the server side to avoid executing the action more than once. But then I decided to drill down to get more details. In global.asax.cs I added the following code (Of course you can use loggers other than log4net):

protected void Application_BeginRequest() {
   Log.InfoFormat("Request type is {0}.", Request.RequestType);
   Log.InfoFormat("Request URL is {0}.", Request.Url);
}

private static readonly log4net.ILog Log =
   log4net.LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

As a result I was able to track all requests. Of course you wouldn’t want to do this for production purposes. In this case I just wanted to have more information about what was going on. It turned out that Fiddler was right as I found several HEAD requests followed by a GET request.

After some research I came across a discussion about Selenium RC head requests and it turned out that this was a known issue in Selenium server version 1.0.3. As of writing this was fixed in trunk and I thought for a moment about building from trunk but then decided on a different path. And that solution worked as well: Instead of using version 1.0.3 I am now using Selenium Server version 2.0a5 plus the .NET driver from the 1.0.3 package.

So here is what you need to download:

  1. Selenium Remote Control 1.0.3 which includes the .NET driver. Don’t use the server from this download.
  2. Selenium Server Standalone 2.0a5. Use this jar file as your server. The command line at the Windows command prompt changes from “java –jar selenium-server.jar” to “java -jar selenium-server-standalone-2.0a5.jar”.

Then start the 2.0a5 server and run your tests. The HEAD/GET issue should be gone. In my case it was and I’m now back to extending my test suite finally making progress again.

My configuration: Visual Studio 2010, .NET 4.0, ASP.NET MVC 2, Vista Ultimate 32, various browsers (IE, Firefox, Chrome, Opera, Safari). The issue I describe here may be different than the one you observe. Consequentially it is possible that this suggested solution doesn’t work for you.

Sunday, June 13, 2010

A Simple CAPTCHA Mechanism for ASP.NET MVC 2

Sometimes you may want to protect certain functionality from being used by automated tools. One way of preventing this from happening is using a CAPTCHA, which is basically an image that is intended to be impossible to read by software (e.g. OCR) but possible to read by humans. The Wikipedia article is a good starting point with regards to the limitations of a CAPTCHA and suggestions for how to address those limitations.

In this post I’d like to show to you how you could integrate a simple CAPTCHA mechanism for ASP.NET MVC 2 using C#. My objectives for this implementation were:

  1. Ideally all CAPTCHA related code is located in a single class.
  2. Using the CAPTCHA in a view should be a single tag.
  3. Avoid having to register HTTP handlers or any other modification of the web.config file

Having all of that in mind I experimented a while, tried out a number of suggestions that I found on the web and settled for now with the one I’ll describe in this post.

I’ll start with how the CAPTCHA can be used in a view (for MVC newbies: roughly speaking this is MVC-lingo for page or form). In essence the solution uses a controller class named CaptchaController implementing a method Show(). In your view you use it like this:

Next to it, you probably would want to display a text box for the user to enter their reading of the CAPTCHA value, so in the view the markup for that would look as follows:

This will create an image and next to it you would display a text box as follows:

image

Of course the value in the image would change.

Now that we can display the CAPTCHA and also have a text box for the user to enter the CAPTCHA value, the next challenge is to store the CAPTCHA value somewhere so that once the user has entered the value and it is coming back to the server, some server side code can validate the CAPTCHA value. The server side code for this looks like this:

This method returns a boolean that you can then use for further processing.

All the rest happens behind the scenes and is completely handled by the class CaptchaController. So what follows is a description of the implementation.

When the CaptchaController renders an image it also creates a cryptographic hash as a session variable. This hash is an MD5 value in my implementation and the calculation uses an additional value to add some ‘salt’ before calculating the MD5 hash. Since the client has no access to the server side code it won’t be able to calculate a matching pair of MD5 and CAPTCHA value. As ‘salt’ I use the assembly’s full name which changes with each compile as it includes the version number.

And here is the source code for CaptchaController:

As always: If you find any bugs in this source code please let me know. And if you can think of other improvements I’d be interested, too.

In closing I’d like to mention reCAPTCHA, for which an ASP.NET component is available as well. Google is the owner of reCAPTCHA and uses it to correct mistakes due to the limitations of OCR (Optical Character Recognition) in their book scanning activities. Depending on your requirements reCAPTCHA might be a good solution as well in particular if you are seeking better protection and/or want to support visually impaired users.

Maybe one day I’ll have the time to look for a single tag / single class integration of reCAPTCHA for ASP.NET MVC …

Sunday, April 19, 2009

OpenFileDialog in .NET on Vista

I'm working on a WPF based application and as quite some applications do, I need to display an OpenFileDialog as well. Trying to be compliant with what .NET 3.5 SP 1 is offering I tried Microsoft.Win32.OpenFileDialog first. I ran into two issues. The first issue I noted was that the dialog box positioned itself just about anywhere but not centered (or at least on the same screen) as the owner window, even if I set the owner window. I did some research and found that despite .NET having been around for years (I started using it in 2001) there is still no OpenFileDialog box available for .NET that inherits from Window (or Forms previously) and can be easily customized. And therefore - as an example - there is no WindowStartupLocation property. Oh, well ... Even with the latest WPF version running on Vista the old XP style dialog box is displayed: In addition even when I passed the owner as a parameter to ShowDialog() it wouldn't center relative to that owner window. Then I tried the previous System.Windows.Forms.OpenFileDialog(). Although it is not recommended to use that namespace within WPF I thought it would still be worth a try. And voila! Here is the result under Vista: Not only did it display the correct dialogbox under Vista but in addition it's location centered on it's owner is correct as well. To achieve this you have to fiddle a bit with the namespaces as there are a few classes that have the same name in both Microsoft.Win32 and in System.Windows.Forms. Since I wanted the client code to look as simple as possible I created two very small wrapper classes. The first wrapper class is basically a replication of the Microsoft.Win32.OpenFileDialog interface (I left out most of the code since it is simply forwarding):
using SWF = System.Windows.Forms;

namespace FooApp.Presentation {
   internal class OpenFileDialog {
      public OpenFileDialog() {
         _dialog = new SWF.OpenFileDialog();
      }

      public bool? ShowDialog(System.Windows.Window window) {
         return _dialog.ShowDialog(new WindowWrapper(window)) == SWF.DialogResult.OK;
      }

      public string DefaultExt {
         get {
            return _dialog.DefaultExt;
         }
         set {
            _dialog.DefaultExt = value;
         }
      }
      public string FileName {
         get {
            return _dialog.FileName;
         }
         set { _dialog.FileName = value; 
         }
      }
      public string Filter {
         get {
            return _dialog.Filter;
         }
         set {
            _dialog.Filter = value;
         }
      }
      public string Title {
         get {
            return _dialog.Title;
         }
         set {
            _dialog.Title = value;
         }
      }

      private readonly SWF.OpenFileDialog _dialog;
   }
}
The only really interesting piece is the ShowDialog() method which takes a WPF window. System.Windows.Forms.DialogBox.ShowDialog() requires a IWin32Window instead (for easy access to the window handle), so we need a second wrapper class that looks as follows:
using System;
using System.Windows;
using System.Windows.Interop;

namespace FooApp.Presentation {
   /// <summary>WindowWrapper is an IWin32Window wrapper around a WPF window.
   /// </summary>
   /// <remarks>Add System.Windows.Forms to the references of your project to
   /// use this class in a WPF application. You don't need this class in a
   /// Forms based application.</remarks>
   internal class WindowWrapper : System.Windows.Forms.IWin32Window {
      /// <summary>
      /// Construct a new wrapper taking a WPF window.
      /// </summary>
      /// <param name="window">The WPF window to wrap.</param>
      public WindowWrapper(Window window) {
         _hWnd = new WindowInteropHelper(window).Handle;
      }

      /// <summary>Gets the handle to the window represented by the implementer.
      /// </summary>
      /// <returns>A handle to the window represented by the implementer.
      /// </returns>
      public IntPtr Handle {
         get { return _hWnd; }
      }

      private readonly IntPtr _hWnd;
   }
}
With this machinery in place the client code in a WPF based application looks very familiar and simple:
var dialog = new OpenFileDialog {
   DefaultExt = ".dll",
   Filter = "Assemblies (*.dll; *.exe)|*.dll;*.exe",
   Title = "Select Assembly"
};
if( dialog.ShowDialog(this) == true ) {
   // File is selected, do something useful...
}
As a result you have it all, simple client code, the correct OpenFileDialog on Vista and the dialog centered properly on its owner. The only thing that I still can't get my head around: After 8 years of .NET we still don't have a class available that is based on Window (or Form) and can be customized. It seems as if this is a puzzle that the guys in Redmond haven't figured out yet...

Saturday, April 04, 2009

"Configuration system failed to initialize"

If you see a ConfigurationErrorsException along with the information "Configuration system failed to initialize" in your QuickWatch window then in all likelihood your app.config (or web.config) file is not correct. In my case I simply forgot to surround the membership provider section with <system.web></system.web>. Once I added those it worked like a breeze. Also, in case your custom provider cannot be found, make sure you have added the proper assembly name to the 'type' attribute for the <add> element of your provider in the <providers> section. And yes, you can test custom providers without having to deploy to or run in a web server. Just ensure your app.config file contains the bare minimum by copying some content from web.config and you should be fine. For my scenario it was sufficient to copy the config section for NHibernate, the hibernate configuration, and the declaration for my custom membership provider.

Tuesday, June 12, 2007

Windows-Safari

OK, I have downloaded and installed Apple's Safari on my Windows XP notebook. Anything earth shattering? I haven't found it yet, but I guess that's because I have used it only for a short time so far. One thing I have observed: For my taste the usability is behind IE7 or Firefox. But again this might be because I'm biased, spoiled, or it might just be a matter of taste. Maybe I simply can't appreciate the "magic" of Safari. Maybe my expectations were simply too high. I'll give it a few more days, and maybe I'll start to get more into it....