Showing posts with label VS2005. Show all posts
Showing posts with label VS2005. Show all posts

Monday, 30 June 2008

XBAP applications and Strong Naming.

One of the first things that is hammered into you when start reading up on XBAP applications is that they run with Partial Trust. There are ways to get your XBAP application running with full trust but this is not the typical scenario (and that topic is worth a whole series of blog posts).

When you Strong Name an assembly, by default the assembly will not allow Partially Trusted callers. As the sandbox in which your XBAP applications run is running with Partial Trust, this means that you will get the following error in the browser when you try to run your application

Startup URI: C:\dir\MyApplication.xbapApplication Identity: file:///C:/dir/MyApplication.xbap#MyApplication.xbap, Version=x.x.x.x, Culture=neutral, PublicKeyToken=0000000000000000, processorArchitecture=msil/MyApplication.exe, Version=x.x.x.x, Culture=neutral, PublicKeyToken=0000000000000000, processorArchitecture=msil, type=win32
System.Security.SecurityException: That assembly does not allow partially trusted callers. at System.Security.CodeAccessSecurityEngine.ThrowSecurityException(Assembly asm, PermissionSet granted, PermissionSet refused, RuntimeMethodHandle rmh, SecurityAction action, Object demand, IPermission permThatFailed) at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args) at System.Runtime.Hosting.ManifestRunner.Run(Boolean checkAptModel) at System.Runtime.Hosting.ManifestRunner.ExecuteAsAssembly() at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext, String[] activationCustomData) at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext) at System.Windows.Interop.PresentationApplicationActivator.CreateInstance(ActivationContext actCtx) at System.Activator.CreateInstance(ActivationContext activationContext) at System.AppDomain.InternalRemotelySetupRemoteDomainHelper(Object[] args) at System.Threading.Thread.CompleteCrossContextCallback(InternalCrossContextDelegate ftnToCall, Object[] args) at System.AppDomain.nCreateInstance(String friendlyName, AppDomainSetup setup, Evidence providedSecurityInfo, Evidence creatorsSecurityInfo, IntPtr parentSecurityDescriptor) at System.Runtime.Hosting.ApplicationActivator.CreateInstanceHelper(AppDomainSetup adSetup) at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext, String[] activationCustomData) at System.Windows.Interop.PresentationApplicationActivator.CreateInstance(ActivationContext actCtx) at System.Windows.Interop.ApplicationLauncherXappDebug.Initialize() at System.Windows.Interop.DocObjHost.MS.Internal.AppModel.IBrowserHostServices.Run(String path, String debugSecurityZoneURL, String viewerUri, String fragment, String applicationId, MimeType mime, Object streamContainer, Object ucomLoadIStream, String userAgentString, Boolean isDebugMode, String progressAssemblyName, String progressClassName, String errorAssemblyName, String errorClassName)The action that failed was:LinkDemandThe method that caused the failure was:Void Main()


To prevent this problem, you need to mark your XBAP assembly with the AllowPartiallyTrustedCallersAttribute, for example:

[assembly: AllowPartiallyTrustedCallers]


With this Attribute your XBAP application will now run.

Thursday, 13 March 2008

Generating a Schema for the BizTalk SQL Adapter

To call a Stored Procedure from BizTalk you need to use the SQL Adapter. This requires you add a special Schema to your BizTalk application, this Schema is generated by a wizard in Visual Studio (the wizard is installed as part of the BizTalk SDK).

This process isn't as straight forward as it should be an its easy to end up with a Schema where the value returned from the Stored Procedure is represented by a "Success" Element of "anyType which is useless.

Firstly, you must have a Stored Procedure that that returns a result set using "FOR XML AUTO". Secondly, when you run through the wizard you must add "XMLDATA" to the end of the Stored Procedure (and remove it after you have generated the Schema). The XMLDATA clause causes SQL Server to return the Schema for the result set (as well as the result). So, when you go through the wizard you must have a stored procedure looking something like this:

SELECT ColumnA, ColumnB FROM MyTable FOR XML AUTO, XMLDATA

After you have generated your schema, remove the "XMLDATA" clause to leave:

SELECT ColumnA, ColumnB FROM MyTable FOR XML AUTO

When you run through the wizard, most of the values you need to enter are obvious but when you get to the "Schema Information" screen, you need to change the "Port Type" to "Send".

When you get to the "Statement Information" screen, you need to enter valid values into the "Value" column (click the Value cell twice to enter data). Then hit "Generate", then hit "Next".

The SQL Adapter Wizard does not seem to support "FOR XML EXPLICIT", you get an error that says "the required attribute 'name' is missing". However, I would guess that if you can generate the boiler plate Schema using "FOR XML AUTO," you should be able to change your Stored Procedure and then manually edit the Schema generated by the Wizard to match what your XML EXPLICIT format.

Saturday, 16 February 2008

Using the MSTest AspNetDevelopmentServer Attribute

If you want to have Integration-type tests and run automated tests against a web service (or web site), with MSTest you can use the "AspNetDevelopmentServer" Attribute on your Test Method. There is a gotcha with the use of this attribute. See the following example:

[TestClass]

public class MyTestClass

{

    [TestMethod]

    [AspNetDevelopmentServer("name", "path")]

    public void MyTestMethod()

    {

        // Do stuff

    }

}



You might be tempted to put the "name" and "path" properties in constants somewhere. Unfortunately if you do this, the "AspNetDevelopmentServer" Attribute will cease to function and the ASP.NET Development Server will not be activated when your tests run. Why is a mystery. So, keep the property values as hard-coded strings in-line.

Friday, 15 February 2008

Installing Visual Studio 2005 Extensions for .NET Framework 3.0 after Visual Studio 2008

This took me a while to resolve.

If you come to install the Visual Studio 2005 Extensions for .NET Framework 3.0 after you have installed .NET Framework 3.0 SP1 or Visual Studio 2008 (which installs .NET 3.0 SP1) then you will receive get a message saying you need to have .NET Framework 3.0 installed (as in, no Service Pack). Obviously you can't because you'll have to un-install/re-install a whole chain of stuff.

A small registry hack will let you re-try the installation, add the following to your registry:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{15095BF3-A3D7-4DDF-B193-3A496881E003}]
"DisplayName"="Microsoft .NET Framework 3.0"

This will fool the installer. I'd recommend removing the registry entry afterwards (that's what I did).

More details here: http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2550726&SiteID=1

Sunday, 27 January 2008

Extending MSTest

One criticism that is levelled against MSTest, especially when comparing it against the xUnit testing frameworks, is its lack of extensibility. While MSTest is missing any explicit extension points, it is possible to extend its functionality and add additional Test Attributes. In this post I will describe how to do this.

I have created a project on CodePlex hosting the solution which supports VS2005 and VS2008 (link at the end). The CodePlex release contains MSIs plus the full source code.

The MSTest extensions Attributes are as follows:
  • TestTransaction – this provides equivalent functionality to MbUnit’s much lauded “RollBack” attribute.
  • ExpectedExceptionMessage – this is an alternative to MSTest’s built-in “ExpectedException” Attribute. The built in “ExpectedException” Attribute is broken, it allows you to provide a message which you would expect is the exception message that is thrown by the expected type. But it isn’t. It’s actually a message that is displayed to the user in the test results log which is very confusing. This alternative allows you to supply the exception message. If the exception message thrown by the Test Method does not match the message in the ExpectedExceptionMessage Attribute, then the test fails.
  • TestTimer – this allows us to put a timer on the unit tests so if a unit test takes longer than the time specified in the Attribute then the test fails.

An example usage of the custom Attributes for MSTest are as follows:

[TestClass]

public class TestTransactionAttributeTest : MSTestExtensionsTestFixture

{

    [TestMethod]

    [TestTransaction]

    public void SomeTest1()

    {

        // Do database stuff, will be

        // rolled back  after test ends.

    }

 

    [TestMethod]

    [TestTimer(10)]

    public void SomeTest2()

    {

        // Do stuff, if it takes longer

        // than  10 milliseconds the test

        // will fail.

    }

 

    [TestMethod]

    [ExpectedExceptionMessage(typeof(MSTestExtensionsException), "Message.")]

    public void SomeTest3()

    {

        throw new MSTestExtensionsException("Message.");

        // This test passes

        // (see above comments).

    }

}

Please note there are no references to any xUnit frameworks! All that is required is to inherit from “MSTestExtensionsTestFixture” and to decorate the Test Methods with the relevant Attribute.

Here’s how we get there...

A comprehension of Aspect Oriented Programming (AOP) is needed to understand how this all fits together. I won’t go into AOP in detail as there are many on-line resources that do a much better job than I would. This is as good a place as any to start: http://en.wikipedia.org/wiki/Aspect-oriented_programming.

MSTest, like the xUnit testing frameworks, uses Attributes on Classes and Methods to specify tests and their behaviour. AOP uses the same style of Attributes on Types to extend their behaviour. If you were building your own application, you might use a framework such as Spring.NET which would provide you with a transparent AOP mechanism. Unfortunately, as MSTest is effectively “closed” (there are no extension points) we don’t have any such options. We have to wire up the AOP features ourselves.

The only way to implement AOP is to use the following objects from the .NET Framework:

  • System.ContextBoundObject – the object that you wish to decorate with Attributes as a means to change the behaviour must inherit from this class.
  • System.Runtime.Remoting.Contexts.ContextAttribute – Attributes inheriting from this Attribute will be called at run-time when the type that they are decorating is called.

The combination of these two objects will allow us to intercept method calls. If we can intercept calls to Methods, we can intercept the calls to Test Methods and modify their behaviour. Every one of our Test Classes (or Fixtures if you prefer) will need to inherit from “ContextBoundObject” and be decorated with our own specialised “ContextAttribute”. Instead of having to do this every time we write a Test Class, we’ll create a Class from which we can inherit when we want to write a Test Class. We’ll call this base class “MSTestExtensionsTestFixture” (as per the previous examples).This is as follows:

[MSTestExtensionsTest]

public class MSTestExtensionsTestFixture : ContextBoundObject

{

}

The “MSTestExtensionsTestFixture” class is as simple as that, it inherits from “ContextBoundObject”, so any classes that inherit from this will be ready for our AOP widgets. Any Test Classes that are to take advantage of our “extensions” will need to inherit from this class or else we won’t be able to intercept the Method calls.

The “MSTestExtensionsTest” Attribute that this base Test Class is decorated with needs explaining. The “MSTestExtensionsTest” Attribute inherits from the “ContextAttribute” mentioned above. The “ContextAttribute” class has a virtual method called “GetPropertiesForNewContext” which we override. This method allows us to add “Aspects” to the context (see above link for a detailed description of Aspects and other AOP concepts). These “Aspects” will intercept Method calls i.e. when the Test Methods are executed, allowing us to change their behaviour. The important “MSTestExtensionsTest” Attribute code is as follows:

[AttributeUsage(AttributeTargets.Class)]

public sealed class MSTestExtensionsTestAttribute : ContextAttribute

{

    ...

 

    public override void GetPropertiesForNewContext(IConstructionCallMessage msg)

    {

        if (msg == null)

            throw new ArgumentNullException("msg");

        msg.ContextProperties.Add(new TestProperty<TestTimerAspect>());

        msg.ContextProperties.Add(new TestProperty<TestTransactionAspect>());

        msg.ContextProperties.Add(new TestProperty<ExpectedExceptionMessageAspect>());

    }

 

    ...

}

The "TestProperty" is a generic Class to reduce the amount of boiler plate code in each Aspect Class. I will skip this for the sakes on brevity, please look at the attached source code for details.

Fast forwarding, this is what an Aspect looks like:

public class MyAspect : TestAspect<TestTimerAttribute>, IMessageSink, ITestAspect

{

    ...

 

    [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]

    public IMessage SyncProcessMessage(IMessage msg)

    {

        if (msg == null)

            throw new ArgumentNullException("msg");

        // The following line is the call

        // to the actual method we have

        // intercepted. We can do stuff

        // before we call this or after.

        // This lets us change behaviour.

        IMessage returnMessage = _nextSink.SyncProcessMessage(msg);

        return returnMessage;

    }

 

    ...

}

Please review the in-line comments above. If this code was used as-is, it would simply call the Method that had been intercepted and we would notice no change in behaviour. However, we can add code before and/or after the call to “SyncProcessMessage” to do whatever we wish. This is the point at which we add our custom code to change the behaviour of the calls to the Test Methods.

From the above code, the “TestAspect” Class is another Class containing boiler plate code which I will skip over and the “ITestAspect” Interface is an Interface that our Aspects must satisfy.

An Aspect must be accompanied by an Attribute, an Attribute is simple and is essentially a placeholder for properties and ensures an Aspect is called. An example Attribute is as follows:

public sealed class MyAttribute : Attribute

{

    private string _someProperty;

 

    public MyAttribute(string someProperty)

    {

        _testLength = someProperty;

    }

 

    public string SomeProperty

    {

        get { return _someProperty; }

    }

}

And bringing it all together, if we were to use our (rather useless) Attribute it would look like so:

[TestClass]

public class MyTest : MSTestExtensionsTestFixture

{

    [TestMethod]

    [MyAttribute("some value")]

    public void SomeTest()

    {

        // Unit test code.

    }

}

Summary

I have skipped over the details of AOP as I would only be repeating other resources you can find on-line. However, I hope I’ve given you a taste of how the solution was implemented. Full source code is available from the CodePlex project

I think this shows that MSTest can be extended and via this mechanism can match a lot of the features of the xUnit frameworks. If you want to make further extensions, all you need to do is implement you own "TestAttribute" and an accompanying "TestAspect". Inherit from the "MSTestExtensionsFixture" and apply your Attribute and you are good to go.

Note the CodePlex solution supports VS2005 and VS2008. With the extensions that are possible and the performance improvements in VS2008 (MSTest is noticeably faster), then MSTest is not such a poor cousin to the xUnit frameworks anymore.

MSTest...it’s not all that bad, honest!

The CodePlex project hosting the solution can be found here: http://www.codeplex.com/MSTestExtensions

Callum


About Me