Tuesday, 22 June 2010
Asp net and app domains
Great Article - What ASP.NET Programmers Should Know About Application Domains
Tuesday, 1 June 2010
Visual Studio project GUIDS
Some care needs to be taken when a large number of people are contributing to a solution... When a VS project is created a new (unique of course) GUID is assigned to the project, when the project is part of a solution the GUID is used to reference the project by VS.
Here comes the trouble... If VS sees inconsistency, i.e. it spots a project GUID within a solution which is cannot resolve
1. Because another project exists with the same guid (in which case VS will generate a new guid for one of these projects)
2. Because another user has the same project or the same solution but either the project or the project reference in the solution has a different GUID to the one you have and they checked-in! In this case (with automatic check-out configured) VS will correct the mistake and the user may not have been aware (or not bothered to check) when they checked-in their changes.
Either way great care is required, we've seen this when people create a new project by copying-and-pasting an existing project.
If it's not noticed, or not acted upon, it can cause a nasty circle of check-in, check-out, change, check-in amongst a large group or between teams. This causes a great deal of confusion with a lot of developers not familiar with the details.
The way to fix this is to make sure all projects within a solution have unique guid, and that a project referenced in the solution has the correct guid (note because the project can be changed by VS, you have to look carefully in history to get the correct guid, which other people may still be referencing).
This situation applies to scenarios where lot's of "project references" exist in the solution and where the solution is stored in source control.
Here comes the trouble... If VS sees inconsistency, i.e. it spots a project GUID within a solution which is cannot resolve
1. Because another project exists with the same guid (in which case VS will generate a new guid for one of these projects)
2. Because another user has the same project or the same solution but either the project or the project reference in the solution has a different GUID to the one you have and they checked-in! In this case (with automatic check-out configured) VS will correct the mistake and the user may not have been aware (or not bothered to check) when they checked-in their changes.
Either way great care is required, we've seen this when people create a new project by copying-and-pasting an existing project.
If it's not noticed, or not acted upon, it can cause a nasty circle of check-in, check-out, change, check-in amongst a large group or between teams. This causes a great deal of confusion with a lot of developers not familiar with the details.
The way to fix this is to make sure all projects within a solution have unique guid, and that a project referenced in the solution has the correct guid (note because the project can be changed by VS, you have to look carefully in history to get the correct guid, which other people may still be referencing).
This situation applies to scenarios where lot's of "project references" exist in the solution and where the solution is stored in source control.
Thursday, 22 April 2010
MS Build, deployment of websites
I had a bit of trouble with this, finally coming accross this blog: blog.m.jedynak.pl
Two things to watch out for with _CopyWebApplication
1. You need to resolve the references by making an explicit call to "ResolveReferences"
2. You need to specify both the output / virtual directory path *and* the web project output path, if you don't (and as noted in the linked blog post) the references will only get copied one level deep!
However, once it's working, is well worth the effort and of course invaluable for that continuous integration!!!
Update: We have has some issues with this approach, principle is what appears to be a bug within the ResolveReferences target.
We always build a solution containing the web services to deploy and we do this first.
However (and I am not sure exactly what triggers this) the corecompile target can be called if the framework thinks an assembly is "out of date" and needs re-compliling. As I say this shouldn't happen for us given we build the solution up-front, but sometimes it does.
When this does happen (on a project by project basis) and if it happens where a project has either a direct or indirect reference to another project AND that other project has a binary/file ref to a MS assembly - in this example System.Web.Services then we hit some trouble.
The corecompile will call the compiler directly passing in a list of commands including all the dependancies, but in this case System.Web.Services is a second level dependancy (it's not directly referenced by the assembly being built, but is by a child assembly) and it doesn't get added causing an exception.
I am still not sure if there's a fix for this, but this problem was in context of some old vs2005 projects and I have a feeling this wouldn't be an issue with 2008 and 2010.
Anyway for now we are using a Folder.Copy target (given that we manage GAC dependancies and we pre build the solution) and this is fine for us, for now.
Two things to watch out for with _CopyWebApplication
1. You need to resolve the references by making an explicit call to "ResolveReferences"
2. You need to specify both the output / virtual directory path *and* the web project output path, if you don't (and as noted in the linked blog post) the references will only get copied one level deep!
However, once it's working, is well worth the effort and of course invaluable for that continuous integration!!!
<MSBuild
Projects ="%(WebProject.path)"
Properties ="OutDir=$(DestFolder)\%(WebProject.Identity)\BIN\;
WebProjectOutputDir=$(DestFolder)\%(WebProject.Identity)\"
Targets="ResolveReferences;
_CopyWebApplication"
/>
Update: We have has some issues with this approach, principle is what appears to be a bug within the ResolveReferences target.
We always build a solution containing the web services to deploy and we do this first.
However (and I am not sure exactly what triggers this) the corecompile target can be called if the framework thinks an assembly is "out of date" and needs re-compliling. As I say this shouldn't happen for us given we build the solution up-front, but sometimes it does.
When this does happen (on a project by project basis) and if it happens where a project has either a direct or indirect reference to another project AND that other project has a binary/file ref to a MS assembly - in this example System.Web.Services then we hit some trouble.
The corecompile will call the compiler directly passing in a list of commands including all the dependancies, but in this case System.Web.Services is a second level dependancy (it's not directly referenced by the assembly being built, but is by a child assembly) and it doesn't get added causing an exception.
I am still not sure if there's a fix for this, but this problem was in context of some old vs2005 projects and I have a feeling this wouldn't be an issue with 2008 and 2010.
Anyway for now we are using a Folder.Copy target (given that we manage GAC dependancies and we pre build the solution) and this is fine for us, for now.
Thursday, 8 April 2010
Testing biztalk maps where the xsl calls out to deployed components
It's quite common to write an xsl which obtains values from or makes use of existing .net lib functions
Example
Where the extension(s) are defined in a "mapper extension" xml file (pointed from the btm map file)
However it's less straight forward to test the xsl outside of Biztalk.
The xslt-compiled-transform requires information relating to these assemblies along with the test xml instance.
The orginal map extensions file can be utilised to do this with the following code, which loads an xsl argument list to be applied to the xsl-compiled transform (possibly to be run from a test)
Example
<xsl:stylesheet version="1.0"
xmlns:bjg="http://ns.com/myext"
exclude-result-prefixes="bjg">
<xsl:template match="/">
<SomeOutput>
<xsl:value-of select="bjg:SomeMethod()"/>
</SomeOutput>
</xsl:template>
</xsl:stylesheet>
Where the extension(s) are defined in a "mapper extension" xml file (pointed from the btm map file)
<Extensionobjects>
<ExtensionObject
Namespace="http://ns.com/myext"
AssemblyName="MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=123456abc123a123"
ClassName="MyAssembly.MyClass" />
</ExtensionObjects>
However it's less straight forward to test the xsl outside of Biztalk.
The xslt-compiled-transform requires information relating to these assemblies along with the test xml instance.
The orginal map extensions file can be utilised to do this with the following code, which loads an xsl argument list to be applied to the xsl-compiled transform (possibly to be run from a test)
XmlDocument xmld = new XmlDocument();
xmld.Load(mapperExtensionsFilePath);
XmlNodeList ns = xmld.SelectNodes("/ExtensionObjects/ExtensionObject");
// load each extension
foreach (XmlNode n in ns)
{
// get attributes
string assemblyName = n.SelectSingleNode("@AssemblyName").InnerText;
string theNamespace = n.SelectSingleNode("@Namespace").InnerText;
string className = n.SelectSingleNode("@ClassName").InnerText;
// find type
foreach (Type t in Assembly.Load(assemblyName).GetTypes())
{
if (t.FullName.Equals(className) )
{
xslArgs.AddExtensionObject(theNamespace, Activator.CreateInstance(t));
break;
}
}
} // get next extension
Thursday, 4 March 2010
Biztalk gotcha?
BTS 2006
Exception type: TypeInitializationException
Source: MyNS.MyService
Additional error information: Field not found: 'ReferencedAssembly_.Type.Method'.
Exception type: MissingFieldException
at MyNS.MyService..cctor()
****
Biztalk Assembly 1: Assm1.dll
Biztalk Assembly 2: Assm2.dll
Assm1 references Assm2
Assm2 contains a "web reference" to a service, but in this scenario Assm1 has referenced Assm2 to access a shared type, it doesn't care about the web ref.
Now, say I updated the web ref and build Assm1, which will in turn cause Assm2 to be built...
I need to ensure *both* assemblies get deployed...
Because the web service "proxy" will have been propogated into Assm1.
This isn't a problem until the web service contract is changed - a breaking change, say a method is added.
If this happens and only Assm1 is deployed, then I'll get a missing field exception in the Assm1 constructor as the proxy definition there will be expecting a field in the proxy which doesn't yet exist on the target machine!
In order to deal with this, I'd need to deploy both assemblies.
A better idea would be to have an assembly wrapping the web reference and nothing else, so I'm only referencing this assembly if I actually need the web proxy!
Snippet of constructor in Assm1
static MyType()
{
__access = 1;
__execable = false;
_serviceId = HashHelper.HashServiceType(typeof(MyType));
_lockIdentity = new object();
_portInfo = new PortInfo[] { new PortInfo(new OperationInfo[] {
Assm2WebProxy.Method1, Assm2WebProxy.Method2, Assm2WebProxy.Method3 ....
Exception type: TypeInitializationException
Source: MyNS.MyService
Additional error information: Field not found: 'ReferencedAssembly_.Type.Method'.
Exception type: MissingFieldException
at MyNS.MyService..cctor()
****
Biztalk Assembly 1: Assm1.dll
Biztalk Assembly 2: Assm2.dll
Assm1 references Assm2
Assm2 contains a "web reference" to a service, but in this scenario Assm1 has referenced Assm2 to access a shared type, it doesn't care about the web ref.
Now, say I updated the web ref and build Assm1, which will in turn cause Assm2 to be built...
I need to ensure *both* assemblies get deployed...
Because the web service "proxy" will have been propogated into Assm1.
This isn't a problem until the web service contract is changed - a breaking change, say a method is added.
If this happens and only Assm1 is deployed, then I'll get a missing field exception in the Assm1 constructor as the proxy definition there will be expecting a field in the proxy which doesn't yet exist on the target machine!
In order to deal with this, I'd need to deploy both assemblies.
A better idea would be to have an assembly wrapping the web reference and nothing else, so I'm only referencing this assembly if I actually need the web proxy!
Snippet of constructor in Assm1
static MyType()
{
__access = 1;
__execable = false;
_serviceId = HashHelper.HashServiceType(typeof(MyType));
_lockIdentity = new object();
_portInfo = new PortInfo[] { new PortInfo(new OperationInfo[] {
Assm2WebProxy.Method1, Assm2WebProxy.Method2, Assm2WebProxy.Method3 ....
Subscribe to:
Posts (Atom)