Hi Guys, last Friday I was invited to be a speaker in a very nice Software Architecture Event organized by the Argentina Microsoft Users Group.
The event (spanish spoken) was named "Jornada de Arquitectura" (something like "Software Architecture Day") and included the presence of very notable local speakers in the Software Architecture field like: Martín Salías, Diego Gonzalez, Hernán Wilkinson, Diego Fontdevila, Roberto Schatz and, of course, me. If you want more information about the event click here.
The slides and videos for the other presenters should be uploaded in the MUG site shortly and into the Code & Beyond site as well, so check for them in a couple days if interested.
Just for the impacient, I'm uploading my slides here, in Skydrive for your convenience.
Best regards,
Andrés G Vettori, Vmbc, CTO
In my last post I talked about how to register dynamically (at runtime) a WCF instance without the need to have an existing .svc file or something in the configuration file (<serviceHostingEnvironment><serviceActivations>).
In this post, we are going deeper in the "Dynamic" domain and we would like to not only host our service dynamically, but also to create the actual service contracts and service operations (and its metadata to support WSDL generation) dynamically (at runtime).
You might be asking yourself: Why on earth anyone would like to create a WCF service (and contracts with methods) at runtime?
Well, there is a big chance that you never need to do something like this (I have lived without this so far, and our current projects are running in production very well) but we are building the next version of our development platform (the elusive project codename "E2" I talked about in my previous post) and in that context we need a way to generate the API that our "Business Models, Modules and Process" define. Those artifacts are completely created by our Business Analyst users and they don't require ANY CODING at all, so why we would settle for less when talking about the exposed APIs of those things.
In the sample code you can download below there are not one but two different approaches to this:
- Using Reflection.Emit to create at runtime a service class that implement the desired operations (methods).
- Using the "ContractDescription" class to create and inject at runtime the service metadata that resembles the desired operations (methods).
Both approaches resolve the service metadata creation, the first by creating a class and letting the WCF runtime to generate the service description metadata in the normal way, and the other build and inject this service description metadata from scratch. Both methods works equally well but I tend to preffer the second because generating and loading a dynamic type in the running process (or AppDomain) have the drawback that is difficult to unload those generated Types and replace them with new versions when the business metadata changes (remember that Business Analysts are doing that, and they are free to change anything they need).
Having said that, I know that it would be possible to unload a generated Type by means of custom AppDomains, but is more work and there are security and performance issues associated with this. By using a metadata only approach we eliminate this problems altogether.
So far we resolved the metadata generation part, but the actual execution of those pesky "Business Process" is not mentioned anywhere, and that's because that is the easy part! :)
WCF already provides all the extensibility you need to intercept the execution of ServiceOperations and do wherever you need, and that's exactly what I do in both examples. I have created an "OperationInvoker" class implementing some WCF interfaces (IOperationInvoker and IOperationBehavior for the injection part) so feel free to explore them, but they are pretty simple. When constructing the metadata we inject it into the "OperationDescription" behaviors collection, check the "CreateOperationDescription" method in the "Service5.cs" project file.
Well, enjoy the code and let me know if have any comments.
Source code download from here: DynamicService2.zip
Best regards,
Andrés G Vettori, CTO, VMBC
I know... I know... it has been a while since my last post, but I never forgot about it, just having a blast doing some fun things. Well, some of that stuff wasn't really THAT fun, but that's part of being a CTO and always there is room for improvement in some processes and structures in the company, and so... after a lot of hard work, we are now in a much better position to actually start doing some fun stuff.
And the fun part has begun, in thre form of a couple new and REALLY interesting and fun projects, where I participate not only as CTO but also I'm fulfilling a role of an Chief Architect as well, overseeing aspects of general architecture from development and infrastructure standpoints, and more important, doing a LOT of research and proof of concepts to hand over to our Architect Team.
So, for this new project (let's say, Codename "E2") I'm in charge of researching some stuff, and here I will present the results of one of those topics: dynamic (runtime) registering of WCF services.
Before jumping in today's topic, let me talk a little about the other topics I'm researching, just to paint a broader picture and set the stage for future posts. Our E2 project is a little ambitious in some aspects, and it's main motto is "Configurable Dynamic", so we are exploring ways to make this happen and the list of things to explore first are:
- Dynamic registration of WCF services (today's topic)
- Dynamic Data Access (ORM without Entities)
- Dynamic Business Rules (or logic, if you want)
- Dynamic Business Processes (workflows are a possibility here, but not the only one)
- Performance of of the above (mainly IIS, ASP.NET, WCF) and how to optimize the platform.
- Performance techniques to use: caching, profiling, monitoring, etc.
Of course there are other topics (like Security, Scalability, Fault Tolerance, etc) but we will advance over those in time. For today's topic, let's explain a little what I'm talking about. For WWCF services there are two ways of let know the runtime environment that we have a Service class and we want to expose it to the world:
The plain old .svc file approach: we need a file with .svc extension and this file will contain the Type information needed to activate the service.
The new CBA (configuration based activation) approach: this is new in NET4, and therefore is possible to create a WCF service WITHOUT the svc file, using only a section in the web.config file (<serviceHostingEnvironment><serviceActivations>).
While this second option is very interesting, we cannot do it at runtime and so the idea of this post was born. We can register HttpModules at runtime (the MVC3 project do that to register the HttpModule that handles Razor views) and so wwe can try to do something similar. That functionality (dynamically register an HttpModule) could be found in the "Microsoft.Web.Infrastructure" assembly using the "RegisterModule" method found in the "DynamicModuleUtility" class.
We are going to take a similar approach to this helper method and use reflection to inject our service configuration somewhere so the runtime thinks it have a CBA Service (file-less) and can active it as any normal service. This is achieved in the "DynamicServiceHelper" class in the attached sample project, using the "RegisterService" method.
This is the source code for the "RegisterService" class: (some lines where removed for brevity)
namespace System.ServiceModel
{
public static class DynamicServiceHelper
{
static object _syncRoot = new object();
static FieldInfo hostingManagerField;
static MethodInfo ensureInitialized;
static FieldInfo serviceActivationsField;
static DynamicServiceHelper()
{
ensureInitialized = typeof(ServiceHostingEnvironment).GetMethod("EnsureInitialized", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.InvokeMethod);
hostingManagerField = typeof(ServiceHostingEnvironment).GetField("hostingManager", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetField);
}
public static void EnsureInitialized()
{
ensureInitialized.Invoke(null, new object[] { });
}
public static void RegisterService(string addr, Type factory, Type service)
{
lock (_syncRoot)
{
object hostingManager = hostingManagerField.GetValue(null);
if (serviceActivationsField == null)
serviceActivationsField = hostingManager.GetType().GetField("serviceActivations", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField);
Hashtable serviceActivations = (Hashtable)serviceActivationsField.GetValue(hostingManager);
string value = string.Format("{0}|{1}|{2}", addr, factory.AssemblyQualifiedName, service.AssemblyQualifiedName);
if (!serviceActivations.ContainsKey(addr))
serviceActivations.Add(addr, value);
}
}
}
}This class have two methods: "RegisterService" and "EnsureInitialized". The first method is pretty self explanatory, it receives the service activation information (endpoint, service type and factory type) but the "EnsureInitialized" method deserves a little explanation. As you can see, we use the "ServiceHostingEnvironment" class, and this class is used internally to manage all WCF services running in our process. It uses an internal class named "HostingManager" that is in charge of doing the discovery of existing WCF services (by looking for ".svc" files in the application folder and reading the <serviceActivations> configuration section, so by using a little reflection we can see that this information is processed in the private method "LoadConfigParameters", and in that method we see that the list of services to activate is added to the private field named "serviceActivations" (a Hashtable).
If you see the example code, you would also see there is another class named "Startup" that contains an assembly attribute named "PreApplicationStartMethod":
[assembly: PreApplicationStartMethod(typeof(WcfService1.Startup), "Init")]
This attribute says to the runtime environment (WAS) that should call the "Init" method in the "Startup" class, and this method is called to give you the chance to initialize your code so it's called almost before anything else so the WCF / WAS infrastructure is not yet initialized at this point. So, in this moment we cannot use anything on the "ServiceHostingEnvironment" class. Hopefully, this class also have an "EnsureInitialized" method (private, of course) so we can try to invoke it and hope it doesn't have any other dependency and will initialize what wew need to register our service. Luckily for me, it worked without any evident side-effects, so let's use it!
Another method to register our services would be not calling the "EnsureInitialize" method and wait for something else to do it. In that case we can create (and dynamically inject) an HttpModule to register our service in it's "Init" method. That will work and I'm including that code in my sample as well (in fact it was my first approach) but it has an important drawback: it needs to something else to initialize the Http stack, and therefore our WCF Service (using TCP to make things more interesting) will not be activated if the hosting application doesn't receive an Http request first.
Well, that's it, hope you enjoyed the reading and find the code useful (by the way, you can use it in any way you want, so I have to include here the usual "No warranties" disclaimer), and if you make some improvement or have any comments about my code I would like to know.
You can download the source code from here: DynamicService.zip
Best regards,
Andrés G Vettori, CTO, VMBC
The symptom is this: you change some area or iteration in a TFS Project, but the change is not reflected (or updated) in VS or any other TFS Client.
Well, it happens that TFS now has some clever caching mechanisms that need to be updated when you make a change like this, and those changes are propagated by some scheduled jobs TFS is continuously running in the Application Tier.
So, you you get this behavior, please check (and possibly restart) the "Visual Studio Team Foundation Background Job Agent" service. In my case, this service was logging a very odd "Object Reference Not Set" into the Windows Event Log, and a simple restart fixed it.
Hope this is fixed by RTM... (we are using the RC version).
And by the way, if the job agent is broken there are some other things that stops working like email notifications.
Best regards,
Andrés G Vettori, CTO, VMBC
The Visual Studio WIT tools team has published a very nice post pointing the most common issues with Sharepoint and TFS 2010.
Check it out at http://blogs.msdn.com/teams_wit_tools/archive/2009/11/24/tfs-2010-beta2-troubleshooting-sharepoint-configuration-issues-tf249038.aspx
Enjoy!
Andres G Vettori, VMBC, CTO
At the PDC 09 Microsoft announced the Release to Manufacturing (RTM) of the Windows Identity Foundation, previously known as "Geneva", "Zermatt" before that, and "IDFX" before that.
Grab the latest bytes from http://msdn.microsoft.com/en-us/evalcenter/dd440951.aspx
Best regards,
Andres G Vettori, VMBC, CTO
Microsoft has released the first version of the Virtual Machine Preparation Tool for Visual Studio Team Lab management 2010. What a mouthfull! Try saying that three times in a row..
Well, the tool function is to prepare existing VMs to be compatible with VS 2010 Lab Management requirements, and believe me, there are a few. Configuring an existing VM by hand is a tedious and VERY error prone task, and so this tool was born.
Download it from http://vslabmgmt.codeplex.com/, this version is prepared to work with VSTS 2010 Beta 2 and Windows Server 2008 X86 SP2 VMs. They will be adding more options as soon they finish testing of different versions (and flavors) of Windows. Perhaps R2 is on the pipeline?
Best regards,
Andres G Vettori, VMBC, CTO
I was trying to build our biggest solution after migration (TEST migration) and found that Silverlight projects won't compile. The first error we received was "The Silverlight 2 SDK is not installed". I found a post on the Silverlight forum about this and managed to fix the error, but then a second error appear:
"The "ValidateXaml" task failed unexpectedly ... System.IO.FileLoadException: Could not load file or assembly 'PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)
According to the people in the Silverlight forum, this is a Silverlight BUG and it won't compile in an x64 environment, so the general workaround is to use an x86 Build Agent.
Fortunately, I found a MUCH BETTER workaround for TFS 2010, wich only involves changing the configuration of the build definition and set the "MSBuild Patform" to "X86" (it was "Auto" before).
After this, my Silverlight projects compile again, even in an x64 Build agent. Nice!
Just for reference, the Silverlight post is here: http://forums.silverlight.net/forums/p/113956/256849.aspx
Andres G Vettori, VMBC, CTO
The test migration of our TFS 2008 went extremely well (the import command processed nearly 7GB of data from our TFS 2008) in less than half hour, and all running in my notebook (not some kickass server...).
Today I executed the script published by Hakan Eskici to upgrate the process template from v4.2 to v5, by simply running a BET file. The process is very simple and fast, and after that we now have the updated process template with all the TFS 2010 goodies enabled.
Check out the process and download the script from http://blogs.msdn.com/hakane/archive/2009/10/19/sample-script-to-enable-new-features-in-upgraded-team-projects-tfs-2010-beta2.aspx
After the upgrade I created a new TASK and found the new "Original estimate" field, and the now separated "Remaining work" and "Completed work", and I almost cryied by the emotion... :)
Also the BUGS have now the new "Repro Steps" and "Test Cases" tabs that are extremely welcome. There also more changes than this (for example the new Test Case WI) so give it a try!
Best regards,
Andres G Vettori, VMBC, CTO
More Posts
Next page »