Converting a Class Library to an MS Test Library

by timvasil 6/10/2008 5:15:00 PM

If you add the [TestMethod] attribute to methods in a regular class library, they won't show up in the test view or test editor.  You may see a message "no tests are loaded."  This happens because Visual Studio doesn't look for the attribute in projects that don't have special "I am a test" markings.  If you create a test project from scratch and add the code the problem will go away, but if you've spent time customizing a project, its references, etc., fear not; you don't need to start over.  Edit the .csproj (or .vbproj) file manually and add the following XML as a child of the first <PropertyGroup> element that appears:

<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Visual Studio | MSTest

WiX: DLL could not be loaded

by timvasil 6/6/2008 7:33:00 PM

Playing around with WiX 3.0, candle.exe started emitting a weird message and failing:

   WixUIExtension.dll could not be loaded

I fixed this by editing the WiX project file by hand and changing the HintPath to remove the ".dll" extension, i.e. instead of this:

   <HintPath>../path/WixUIExtension.dll</HintPath>

Use this:

   <HintPath>../path/WixUIExtension</HintPath>

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

WiX

Form.DefaultButton in Firefox

by timvasil 6/4/2008 11:53:00 AM

Setting the DefaultButton property on a form to an ImageButton, LinkButton, or Button with UseSubmitBehavior=false doesn't work on Firefox because the ASP.NET code hooking the Enter key on form submit looks for a "click" method on the button that Firefox does not support.

If you give your button a name attribute, say name='DefaultButton' for example, then throw the following JavaScript in a file that's included on all pages, it'll work.  The trick is to define the click method on Firefox's behalf.

setTimeout(function() { init(); }, 0);

// Fixup link buttons for FF
function init()
{
    if (document.getElementsByName)
    {
        var aoElements = document.getElementsByName("DefaultButton");
        if (aoElements)
        {
            for (var i = 0; i < aoElements.length; i++)
            {
                if (aoElements[i].click == undefined)
                {
                    aoElements[i].click = aoElements[i].onclick;
                }
            }
        }
    }
}


Update on 6/9/08:

That fix apparently doesn't work completely, as when you hit <Enter> in a textarea the form is submitted.  That's a critical flaw.  I didn't want to wholesale replace ASP.NET's WebForm_FireDefaultButton method, but, c'mon, there's only so much tolerance anyone can have for hunting down and working around other people's bugs. 

So, here's a tweaked version of the function that fixes default button handling and works across browsers.  In order to use this patched function, you need to define it *after* all other JavaScript files and also after <ajaxToolkit:ToolkitScriptManager /> if you happen to be using it.

var __defaultFired;
function WebForm_FireDefaultButton(event, target) {
    var element = event.target || event.srcElement;
    if (!__defaultFired && event.keyCode == 13 && !(element && (element.tagName.toLowerCase() == "textarea"))) {
        var defaultButton;
        if (__nonMSDOMBrowser)
            defaultButton = document.getElementById(target);
        else
            defaultButton = document.all[target];

        if (typeof(defaultButton.click) != "undefined") {
            __defaultFired = true;
            defaultButton.click();
            event.cancelBubble = true;
           
            if (event.stopPropagation) event.stopPropagation();
            return false;
        }
        if (typeof(defaultButton.onclick) != "undefined") {
            __defaultFired = true;
            defaultButton.onclick();
            event.cancelBubble = true;
           
            if (event.stopPropagation) event.stopPropagation();
            return false;
        }

    }
    return true;
}

 

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

ASP.NET | JavaScript | Firefox

Fix for IE's 'Operation Aborted' error

by timvasil 5/28/2008 11:17:00 PM

If you've done any dynamic manipulation of web pages, especially with AJAX or any other kind of web magic in the mix, you've run into IE's dreaded "Operation Aborted" error.

Here are some official comments on the issue:

The blog post says that if you aren't meeting all 3 conditions, you're OK.  In my case, I believe I wasn't meeting the 3 conditions, and yet the problem persisted.  It was very hard to reproduce, too.  I had to have the offending website in the "Internet Zone" and experience some network lag to make it happen.

In the end, I found that if I replaced this line:

   document.body.appendChild(element);

With this one:

   document.body.insertAdjacentElement('afterBegin', element);

Everything worked fine.  Of course, this trick works only if you're inserting a node whose position isn't important, e.g. it's a div you're going to give an absolute position anyway.

Along the way I had tried wrapping the appendChild calls in a try/catch block, but unfortunatley the append would work fine, and then IE would complain with "Operation Aborted" only after the JavaScript finished.  I was hoping for a global exception handler to trap the problem, but fortunately insertAdjacentElement fixes the issue!

Currently rated 4.0 by 1 people

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

JavaScript | IE

System.BadImageFormatException using NHibernate proxies

by timvasil 4/24/2008 11:36:00 AM

I made a bunch of changes to code recently and then ran a unit test to find this:

NHibernate.HibernateException: Creating a proxy instance failed --->  System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. --->  System.BadImageFormatException: An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B).

This happened when I tried to serialize an object graph using WCF and my handy NHibernate data contract surrogate. Strangely, if I set breakpoints in certain places the exception would not occur but proxies elsewhere would behave strangely, e.g. lose property values.

Poking around on the Castle DynamicProxy forums, there were mentions of this being due to an abstract class being proxied.  I turned off lazy initialization of classes that had abstract bases, and yet the problem persisted.  Then, on a clue that DynamicProxy lacked support for proxying generic classes, I removed the "virtual" keyword from what looked like an innocuous method:

        protected virtual IEnumerable<T> GetSubset<T>()
        {
            . . .
        }

Simply removing the "virtual" keyword fixed the problem.  So be warned:  no generic methods on your proxy classes, at least not until DynamicCastle 2.0!

Tim

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Hibernate | Castle.DynamicProxy

Using Spring.NET 1.1.1 with Oracle - Your driver must be this tall

by timvasil 4/23/2008 1:19:00 PM

When I recently upgraded from Spring.NET 1.1.0 to 1.1.1, I started getting a bizarre message:

DbProvider product name = Oracle, Oracle provider V2.102.2.20, could not resolve commandBuilderDeriveParametersMethod DeriveParameters to MethodInfo

It's looking for a method named DeriveParameters on the Oracle.DataAccess.Client.OracleCommandBuilder class.  Poking around with the .NET reflector, the method, sure enough, is not there.

After looking at some forum posts and a logged defect against Spring.NET, there were workarounds.  But surely with a database as common as Oracle these steps shouldn't be necessary!  No one having the issue was using Oracle, and, as it turns out, it's because they're using a newer driver that defines this magical DeriveParameters method.

I was using version 10.1.0.200, which is much newer than the 2.102.2.20 that Spring.NET expects when you look at the dbproviders.xml file.  But, alas, 10.1.0.200 is apparently code for something pre-2.102.2.20.  Oracle has two versioning schemes.  I found that when I downloaded the latest Oracle data access components (ODAC), billed as 11.1.0, I ended up with an Oracle.DataAccess.dll with a version 2.116.6.20 timestamp.  Happily, I found this to work with Spring.NET 1.1 without issue.

As a side note, I upgraded to NHibernate 1.2.1 from 1.2.0 at the same time and found the Oracle dialect suddenly dropped support for the "guid" data type.  Moral of the story:  even point releases have gotchas!

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Hibernate | Oracle | Spring.NET

Working with the Milonic menu API bolt-on

by timvasil 4/22/2008 2:34:00 AM

If you happen to be using the Milonic menu system, you may have noticed the availability of a menu API "bolt-on" module.  It's woefully underdocumented, and reveals just how ugly the architecture for this menu system really is.  For example, global variables abound and there's trickiness around when to pass in a menu's ref (i.e. index into the _m global array of menus) versus a menu's internal name.  This makes me very appreciative of the cleaner menu APIs I've seen in the successor JavaScript frameworks, such as Ext JS.  I'm using the Milonic system with some older code; I wouldn't recommend it for new projects.  I'm not sure I'd recommend Ext JS either, though; the Ext folks just did a bait-and-switch, moving from an LGPL licensing model to a dual GPL/commerical one.  That's damn nasty, but I digress...

First off, understand that if you happen to create any menus without menu items, the menu API will blow up in random ways, e.g. "_m[..] is undefined"-type error messages.  I had modified the API code to work around the problem until I figured out what was going on.  So be aware of that gotcha.

So, for those functions where you need a menu "ref," there's no API function to get it given a menu's internal name.  Nice.  Here you go...

function mm_getMenuRef(sMenuName)
{
 var sMenuName = sMenuName.toLowerCase();
 for (var i=0; i < _m.length; i++)
 {
  if (_m[i] && _m[i][1] == sMenuName)
  {
   return i;
  }
 }
 return -1;
}

Notice that -1 is returned if no menu with the name exists.

Now here's a function to delete a menu and all its descendants (not just children):

function mm_deleteMenuRecursively(sMenuName)
{
 var iRef = mm_getMenuRef(sMenuName);
 if (iRef >= 0)
 {
  var asNames = mm_getChildMenus(iRef).menus;
  for (var i = asNames.length - 1; i > 0; i--)
  {
   mm_deleteMenuRecursively(asNames[i]);
  }
  mm_deleteMenu(mm_getMenuRef(sMenuName));
 }
}

Happy menuing!

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Java

Debugging dynamically evaulated JavaScript

by timvasil 4/22/2008 2:10:00 AM

When using AJAX, an easy way to evaluate JavaScript or JSON returned from a web server is the good ol' eval function.  However, if an error is encountered during the evaluation Microsoft's Script Debugger doesn't let you see the offending line.  (I haven't checked what FireBug does yet.)

To get around this problem, you can insert the JavaScript as a <script> DOM node. 

In other words, instead of this:

    eval(js);

try this:

    var scriptTag = document.createElement("script");
    scriptTag.setAttribute('type', 'text/javascript');
    scriptTag.text = js;
    document.body.appendChild(scriptTag);

With the latter approach, the debugger works great.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

JavaScript | AJAX

Handling multiple simultaneous requests from a user in ASP.NET

by timvasil 4/16/2008 8:18:00 PM

If you have an ASP.NET application, have you noticed that out-of-the-box your .aspx requests are serialized?  That is to say, if you request page A.aspx and navigate to B.aspx before A.aspx finishes loading, the B.aspx won't begin until A.aspx completes.

Why is this, you may ask?

The answer is session locking.  The ASP.NET framework protects you from simultaneous access to session state by two HTTP request handing threads by blocking subsequent requests until the first one relinquishes a lock.  This is the default behavior, but it can be overriden (sort of) by using the enableSessionState page attribute:

  • enableSessionState="true" is the default behavior, and acquires a writer lock on session data.  No other readers or writers can gain access while this lock is held.
  • enableSessionState="ReadOnly" acquires a reader lock on session data.  Multiple readers are allowed simultaneously, but no writer can gain access if any reader holds a lock.  Unfortunately, any changes you make to session are local to the request and not visible to other requests that look at the session object.  No error is thrown if you try to modify a "read only" session, so this behavior is not obvious at first blush.
  • enableSessionState="false" doesn't acquire any lock.  The HttpContext.Session property ends up being null, and your page will have no access to session data.

This is a sad state of affairs.  If you want two user requests to execute in parallel, where both need read/write access to the session, you're out of luck.  I wish the ASP.NET framework provided a way for me to manage synchronization to the session data myself as I do in the Java servlet/JSP world, perhaps by using something like a Session.SyncRoot property, but sadly there is absolutely no way to do this. I've looked at the framework code, and in ASP.NET 2.0 there are tons of assumptions all over the place about exclusive write access to the session.

What are the alternative solutions? 

I can think of two solutions off the top of my head:

  1. Create a static singleton (accessible by all sessions) that maps session IDs to string-to-object dictionaries, i.e. IDictionary<string, IDictionary<string, object>>.  The static singleton needs to carefully synchronize access to the data structure.
  2. Create a custom session data store that avoids locking.

Option 1 feels like a hack, as it bypasses all of the built-in session infrastructure and has an obvious drawback of not being automatically cleaned up when sessions terminate.  Calling a cleanup method from a Session_End event is possible, but certainly not elegant.   Here's an implementation:

    /// <summary>
    /// Stores session-specific values in application state so the values are available
    /// immediately, even on pages that do not have access to the session object (e.g. enableSessionState=false).
    /// <para/>
    /// If you use this class, make sure <c>RemoveAllItems</c> is called when sessions end
    /// to ensure memory is reclaimed.
    /// <para/>
    /// All methods on this class are thread-safe.
    /// </summary>
    public static class ApplicationSessionStateStore
    {
        private static bool _enabled;

        /// <summary>
        /// Enables this class for use.  This is a safety check.  By invoking this method,
        /// the caller commits to calling <c>RemoveAllItems</c> when sessions terminate.
        /// </summary>
        public static bool IsEnabled
        {
            get { return _enabled; }
            set { _enabled = value; }
        }

        public static void AssertEnabled()
        {
            if (!_enabled)
            {
                throw new InvalidOperationException("Use of ApplicationSessionStateStore is not enabled.  See 'IsEnabled' property documentation for proper usage.");
            }
        }

        public static T GetItem<T>(string sessionId, string key) where T : class
        {
            return GetItem<T>(sessionId, key, false);
        }

        public static T GetItem<T>(string key) where T : class
        {
            return GetItem<T>(HttpContext.Current.Session.SessionID, key, false);
        }

        public static T GetAndRemoveItem<T>(string sessionId, string key) where T : class
        {
            return GetItem<T>(sessionId, key, true);
        }

        public static T GetAndRemoveItem<T>(string key) where T : class
        {
            return GetItem<T>(HttpContext.Current.Session.SessionID, key, true);
        }

        public static void SetItem(string key, object value)
        {
            SetItem(HttpContext.Current.Session.SessionID, key, value);
        }

        public static void SetItem(string sessionId, string key, object value)
        {
            AssertEnabled();
            HttpContext context = HttpContext.Current;
            HttpApplicationState appState = context.Application;
            IDictionary<string, object> sessionDic;
           
            appState.Lock();
            try
            {
                sessionDic = (IDictionary<string, object>)appState.Get(sessionId);
                if (sessionDic == null)
                {
                    sessionDic = new Dictionary<string, object>();
                    appState.Set(sessionId, sessionDic);
                }
            }
            finally
            {
                appState.UnLock();
            }

            lock (sessionDic)
            {
                sessionDic[key] = value;
            }
        }

        public static void RemoveAllItems()
        {
            RemoveAllItems(HttpContext.Current.Session.SessionID);
        }

        public static void RemoveAllItems(string sessionId)
        {
            HttpContext.Current.Application.Remove(sessionId);
        }

        private static T GetItem<T>(string sessionId, string key, bool removeItem) where T : class
        {
            AssertEnabled();
            HttpContext context = HttpContext.Current;
            HttpApplicationState appState = context.Application;
            IDictionary<string, object> sessionDic = (IDictionary<string, object>)appState.Get(sessionId);

            if (sessionDic == null)
            {
                return null;
            }
            else
            {
                object value;
                lock (sessionDic)
                {
                    if (sessionDic.TryGetValue(key, out value))
                    {
                        if (removeItem)
                        {
                            sessionDic.Remove(key);
                        }
                    }
                }
                return value as T;
            }
        }
    }

This implementation requires some special handing in global.asax:

        protected void Application_Start(Object sender, EventArgs e)
        {
            ApplicationSessionStateStore.IsEnabled = true;
        }

        protected void Session_End(Object sender, EventArgs e)
        {
            ApplicationSessionStateStore.RemoveAllItems();
        }

Option 2 is actually surprisingly complex.  When you implement your own session store, it's not like you're subclassing HttpSession.  Oh no, that would be too simple.  You need to subclass a "store" that provides "store data" that HttpSession encapsulates.  So the custom store must avoid locking requests in the places the native store engages in its reader/writer lock magic, and it must also return a "store data" object whose instance methods are thread-safe.  To further complicate matters, the native implementation of the in-process session store is internal and cannot be directly subclassed by your code, so you have to use reflection to instantiate it and the decorator pattern to subclass it.  Here are all of the steps:

  1. Define a MultiThreadedSesionStateStore that subclasses SessionStateStoreProviderBase.
  2. In the constructor, instantiate the native in-proc store System.Web.SessionState.InProcSessionStateStore using Activator.CreateInstance.
  3. In all the methods that must be defined, invoke the appropriate method on the native store using reflection to find the appropriate MethodInfo and calling Invoke.  The key insight is to call the native store's GetItem method when the multi-threaded store's GetItemExclusive method is called.  In essense, you're faking the native store to treat all session acquisitions as read-only acquisitions so the exclusive writer lock is never held.  Since the session store data object returned is not a copy (the framework makes a copy of read-only session data elsewhere) it's possible to modify the data that should be treated as read-only.
  4. In all methods that return SessionStateStoreData, wrap the store data using a custom subclass of SessionStateStoreData.  In the subclass, wrap the inner SessionStateStoreData.Items collection in a custom ISessionStateItemCollection.
  5. Implement the custom ISessionStateItemCollection class so that all methods lock the wrapped ISessionStateItemCollection's SyncRoot object for reads and writes.  Importantly, when defining the Keys property return a custom NameObjectCollectionBase.KeysCollection instance that is a snapshot of the keys at that point in time.  You'll need to use reflection to create a new instance of this class, as its construtor is internal.  This involves defining a subclass NameValueCollectionBase.
  6. In all methods that accept a SessionStateStoreData object, unwrap the decorator before passing the object to the wrapped session store implementation.

If you don't go through with steps 4 - 6, the session store data object will not be thread safe, and concurrent user requests may end up corrupting this object.  With all steps implemented, reading and writing data to the session, e.g. Session[key] = value, becomes thread-safe.  One important word of caution, though:  If you're placing objects in session state, you must perform locking yourself or ensure the instance methods and properties of the shared object are also thread-safe.

If the 6 steps of this approach seem a bit daunting (I deduced all of this by using the .NET reflector and verifying through inspection that all ways in which the session data could be accessed were done in a thread-safe way), it's also possible to write a session store implementation completely from scratch, but that means you'd have to code up the session timeout logic too.

Why do you need to support concurrent user requests anyway?

There are several reasons why you won't want to run user requests serially.  If you want to allow users to quickly navigate through your app, even when database queries may slow things down a bit, for example, allowing concurrent requests works wonders.  It's also fantastic when multiple dynamic requests may occur in parallel on a page, such as the generation of dynamic charts.

The approach works best in code that periodically checks to ensrue a request is still active, since if a user is bouncing around the app you don't want to spend too much time executing queries and rendering HTML that will never see the light of day.  It's as simple as:

if (!context.Response.IsClientConnected)
{
    context.Response.End();
}

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

ASP.NET | Multithreading

Spring.NET AOP Cheat Sheet

by timvasil 3/31/2008 2:17:00 PM

Getting aspect oriented programming (AOP) working with objects in Spring.NET using the IoC container's XML configuration takes some concentration, since there's plenty going on--from defining the pointcut to coding up the advice to preparing the object factory that wraps the target in a proxy. 

Below is a relatively concise XML configuration to do all of these things:

    <object id="MyPointcutAdvisor" type="Spring.Aop.Support.NameMatchMethodPointcutAdvisor, Spring.Aop">
        <property name="Advice">
            <object type="{ your interceptor type goes here, e.g. something that implements IMethodInterceptor }"/>
        </property>
        <property name="MappedNames">
            <list>
                <value>{ specify a method name to intercept here } </value>
                <value>{ specify a method name to intercept here } </value>
            </list>
        </property>
    </object>
    <object id="MyProxy" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop">
        <property name="Target">
            <object type="{ the wrapped target type goes here }"/>
        </property>
        <property name="InterceptorNames">
            <list>
                <value>MyPointcutAdvisor</value>
            </list>
        </property>
    </object>

Note that you can change NameMatchMethodPointcutAdvisor to something more robust like RegularExpressionMethodPointcutAdvisor if you need to intercept methods based on regular expressions rather than simple names.

To get a reference to the proxy object with advice in place, use ref="MyProxy" in the configuration XML for IoC hookup, or use this code:

MyType proxyObj = (MyType)ContextRegistry.GetContext().GetObject("MyProxy");

You can also wrap a pre-instantiated object at runtime:

MyType proxyObj = (MyType)ContextRegistry.GetContext().ConfigureObject(obj, "MyProxy");

Important note:  Spring.NET proxies use a decorator (inheritance) pattern or a composition pattern.  Neither approach allows advice on methods that are not interface implementations and not virtual!  Further, Spring.NET will not warn you or give you an error if it cannot configure advice for a non-virtual, non-interface method; instead, the methods will simply not be intercepted, leading to sometimes confusing bugs.  This issue is documented on the Spring.NET forums and bug tracker.

The decorator (inheritance) pattern is used when the target being proxied has no interfaces to proxy or ProxyTargetType is set to true on the proxy factory.  In this case the target type is subclassed and contains an internal pointer to the target object.  Otherwise the composition pattern is used, where a new class is defined dynamically implementing all the interfaces and likewise contains an internal pointer to the target object.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Spring.NET | AOP

 

About the author

Tim Vasil Tim Vasil
I'm a software engineer living in Cambridge, MA.

E-mail me Send mail

Search

Calendar

<<  September 2010  >>
MoTuWeThFrSaSu
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

View posts in large calendar

Recent comments