If you have access to an MSDN subscription, you can now download the Windows Vista Service Pack 1.
You’ll find it under the “Top subscribers downloads” at the MSDN subscriptions page.
If you have access to an MSDN subscription, you can now download the Windows Vista Service Pack 1.
You’ll find it under the “Top subscribers downloads” at the MSDN subscriptions page.
Finally we’re getting a developers conference in Norway; NDC.
It will be held in 17th and 18th of June at Radisson SAS Scandinavia Hotel, Oslo.
The official site was officially launched yesterday as well :
Welcome to the version 1.0 of our new design over at Game Camp
Our frontpage now looks a bit different and you’re probably wondering where the tutorials, photos and download sections are.
They are all now located under the resources section.
Besides this everything should be were you found it before.
We hope the new design is more soothing and will motivate you to use the site more. π
I started looking into the profiling API this friday, thanks to a colleague of mine at work; Fredrik Kalseth.
He started working on an AOP framework and came into my office and we discussed the possibility to use the profiler API to achieve a better result for an AOP framework. There’s been a lot of studies on the subject and a couple of solutions as well, AOP.net is one of them.
The principle is very simple; intercept any calls being made to methods in a managed type and modify the execution path by calling before, after, around advices.
By hooking up the JITCompilationStarted callback that the ICorProfilerInfo2 interface provides we can do this really slick and very optimal as well. The ICorProfilerInfo2 provides us with two methods ; GetILFunctionBody and SetILFunctionBody. These can be used to get the current body of the method and then modify it and saving it back before it is JIT compiled. The advantage of doing this is that you only need to do it once per type during the lifecycle of your process, giving it a very low impact for doing this. This method does not work with assemblies that has been installed with NGEN, so adding AOP to existing framework bits might prove difficult. π
One of the quirks with using the CLR profiling API is that you need to set a couple of environment variables in order for it to work, you need to enable profiling and then set the GUID for the COM object representing the profiler. This is something that will look very odd if you have an application you’re sending out to customers. I started fiddling with the idea of how I could get about this issue and came up with a solution I found interesting; our entrypoint will not be a managed executable, but an unmanaged entrypoint that hosts the CLR and configures the environment programmatically before starting the CLR.
My prototype at the moment is very very rough, so I won’t be publishing any code for this post, but sometime in the near future I will be sharing some of my findings and sourcecode. Seeing that the title of this post is postfixed with Part 1 – I’ve given myself the necessary pressure to create a Part 2.
Finally Microsoft has finished the long awaited Service Pack 1 for Vista. Congratulations!
You can read more about it over at the Windows Vista Team Blog.
It won’t be available for public download as of yet :
In mid-March, we will release Windows Vista SP1 to Windows Update (in English, French, Spanish, German and Japanese) and to the download center on microsoft.com. Customers who visit Windows Update can choose to install Service Pack 1. If Windows Update determines that the system has one of the drivers we know to be problematic, then Windows Update will not offer SP1. Since we know that some customers may want to update to SP1 anyhow, the download center will allow anyone who wants to install SP1 to do so.
In mid-April, we will begin delivering Windows Vista SP1 to Windows Vista customers who have chosen to have updates downloaded automatically. That said, any system that Windows Update determines has a driver known to not update successfully will not get SP1 automatically. As updates for these drivers become available, they will be installed automatically by Windows Update, which will unblock these systems from getting Service Pack 1. The result is that more and more systems will automatically get SP1, but only when we are confident they will have a good experience.
The remaining languages will RTM in April.
In addition the RTM version of Windows Server 2008 is also available, read more here.
Congrats on that one as well. π
I’ve been working lately a bit with WCF and find it very exciting and a true step up from .net remoting and .net WebServices.
The scenario we’re having is that we have one server application and at the moment two front-ends; Windows Forms and a ASP.net Web application. For our Windows Forms based application we need to be able to host our services in-process as well as on a server. In addition we do not want to be directly coupled to WCF for our contracts, so the declarative way of doing things with attributes (ServiceContractAttribute, OperationContractAttribute and so forth) is not acceptable, or at least not the optimal solution for our services to be exposed. Another issue I ran into was the lack of surrogate support for well known types such as XmlNode and XmlDocument and others.
With this in mind I’ve been working on a prototype were we share an assembly with all our contracts and then have our own ServiceModel component that will also be shared between the projects. This will then serve as our entrypoint for our services. When we have this principal with a shared assembly with all our interfaces, it is fair to say that the contracts and it’s operations are implicitly exposed and available, in other words; attribute decorations should really not be necessary.
The picture looks something like this (finally I got to use my tablet for blogging. π )Β :
In order to get this to work one need to have the ability to create service contracts programatically and be able to serialize and deserialize datacontracts without having to decorate them with different contract attributes or create surrogates. Fortunately, WCF has been made to be as flexible as possible and give 100% control to the developer, so it is pretty straight forward to do this.
First we start by setting up our host :
ServiceHost host = new ServiceHost(serviceType, this.BaseAddress); WSHttpBinding binding = new WSHttpBinding(SecurityMode.None);
We need to add the ServiceMetaDataBehavior and take advantage of a method on it called ExportContract(). This method will
export the contract for the service to the endpoint.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; smb.MetadataExporter.ExportContract(contractDescription); host.Description.Behaviors.Add(smb);
And then we add our endpoint :
ServiceEndpoint endPoint = new ServiceEndpoint( contractDescription, binding, new EndpointAddress(this.BaseAddress)); host.Description.Endpoints.Add(endPoint);
Then we open our host and make it start listening for requests – note : this implementation pretty much turns off security, probably
something one should look into. π
host.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.None;
host.Open();
As you’ve probably noticed, we need code to generate the contract description needed for the above implementation. A quick and dirty implementation should look like this :
public class ServiceHoster { public static readonly ServiceHoster Instance = new ServiceHoster(); public static readonly string DefaultNamespace = "http://www.dolittle.com/"; private readonly List<System.ServiceModel.ServiceHost> _hosts; private ServiceHoster() { this._hosts = new List<System.ServiceModel.ServiceHost>(); this.Namespace = DefaultNamespace; } public void ShutDown() { foreach (ServiceHost host in this._hosts) { host.Close(); } } public string Namespace { get; set; } public Uri BaseAddress { get; set; } private ContractDescription CreateContractDescription(Type contractType, Type serviceType) { ContractDescription contractDescription = new ContractDescription(contractType.Name); contractDescription.ProtectionLevel = ProtectionLevel.None; contractDescription.ContractType = contractType; contractDescription.ConfigurationName = contractType.FullName; contractDescription.SessionMode = SessionMode.NotAllowed; MethodInfo[] methods = contractType.GetMethods(); foreach (MethodInfo method in methods) { OperationDescription operationDescription = new OperationDescription(method.Name, contractDescription); string messagePath = this.Namespace + contractType.Name + "/"; string requestName = method.Name; string responseName = method.Name + "Response"; string requestPath = messagePath + requestName; string responsePath = messagePath + responseName + "Response"; string resultName = requestName + "Result"; MessageDescription inputMessage = new MessageDescription(requestPath, MessageDirection.Input); inputMessage.Body.WrapperName = requestName; inputMessage.Body.WrapperNamespace = this.Namespace; ParameterInfo[] parameters = method.GetParameters(); foreach (ParameterInfo parameter in parameters) { MessagePartDescription messagePartDescription = new MessagePartDescription(parameter.Name, this.Namespace); messagePartDescription.Type = parameter.ParameterType; inputMessage.Body.Parts.Add(messagePartDescription); } operationDescription.Messages.Add(inputMessage); if (null != method.ReturnType) { MessageDescription outputMessage = new MessageDescription(responsePath, MessageDirection.Output); outputMessage.Body.ReturnValue = new MessagePartDescription(resultName, this.Namespace); outputMessage.Body.ReturnValue.Type = method.ReturnType; outputMessage.Body.WrapperName = responseName; outputMessage.Body.WrapperNamespace = this.Namespace; operationDescription.Messages.Add(outputMessage); } contractDescription.Operations.Add(operationDescription); operationDescription.Behaviors.Add(new ServiceOperationBehavior(method)); OperationBehaviorAttribute operationBehaviourAttribute = new OperationBehaviorAttribute(); operationDescription.Behaviors.Add(operationBehaviourAttribute); DataContractSerializerOperationBehavior d = new DataContractSerializerOperationBehavior(operationDescription); operationDescription.Behaviors.Add(d); } return contractDescription; } public void AddService<T>(Type serviceType) { Type contractType = typeof(T); ServiceHost host = new ServiceHost(serviceType, this.BaseAddress); WSHttpBinding binding = new WSHttpBinding(SecurityMode.None); ContractDescription contractDescription = this.CreateContractDescription(contractType, serviceType); ServiceEndpoint endPoint = new ServiceEndpoint( contractDescription, binding, new EndpointAddress(this.BaseAddress)); host.Description.Endpoints.Add(endPoint); ServiceMetadataBehavior smb = new ServiceMetadataBehavior(); smb.HttpGetEnabled = true; smb.MetadataExporter.ExportContract(contractDescription); host.Description.Behaviors.Add(smb); host.Authorization.PrincipalPermissionMode = PrincipalPermissionMode.None; host.Open(); } }
As you can see it is pretty straight forward defining the contracts and its messages. The magic is located at the end of the method when all the behaviors are added. Behaviors are the real magic of WCF, they pretty much make WCF tick. πΒ We add a ServiceOperationBehavior that we’ll see the code for below, in addition we add some behaviors that ship with WCF; OperationBehaviorAttribute and DataContractSerializerOperationBehavior. The latter of the two will most likely be removed in Part 2 of this article when I will post that. The reason is that we will have to create our own DataContract serializer in order to be able to serialize any data types as mentioned earlier.
The purpose of the ServiceOperationBehavior is to intercept the handling of the request and response for the services we’re exposing. In this article we use the default XML serializer as you can see in the ApplyDispatchBehavior() method. Again for this example we are doing things very very simple and we don’t pay attention to things like security.
public class ServiceOperationBehavior : IOperationBehavior { private MethodInfo _methodInfo; private IOperationBehavior _innerBehavior; internal ServiceOperationBehavior(MethodInfo methodInfo) { this._methodInfo = methodInfo; } #region IOperationBehavior Members public void AddBindingParameters( OperationDescription operationDescription, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { } public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { if (null == this._innerBehavior) { this._innerBehavior = new XmlSerializerOperationBehavior(operationDescription) as IOperationBehavior; } this._innerBehavior.ApplyDispatchBehavior(operationDescription, dispatchOperation); dispatchOperation.DeserializeRequest = true; dispatchOperation.SerializeReply = true; dispatchOperation.Invoker = new ServiceInvoker(this._methodInfo); } public void Validate(OperationDescription operationDescription) { } #endregion }
In the ApplyDispatchBehavior method we setup an invoker to handle the invocation of the methods. The invoker looks like this :
public class ServiceInvoker : IOperationInvoker { private readonly MethodInfo _methodInfo; public ServiceInvoker(MethodInfo methodInfo) { this._methodInfo = methodInfo; } #region IOperationInvoker Members public object[] AllocateInputs() { return new object[0]; } public object Invoke(object instance, object[] inputs, out object[] outputs) { outputs = new object[0]; object returnValue = this._methodInfo.Invoke(instance, inputs); return returnValue; } public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state) { throw new NotImplementedException(); } public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result) { throw new NotImplementedException(); } public bool IsSynchronous { get { return true; } } #endregion }
You can download the sample VS2008 projectΒ here
Compile and run and open a browser and go to http://localhost:8000.