Contents tagged with WCF
-
WCF Certificates with IIS on Windows 7 Beta
I’ve blogged earlier about the problems with Cassini and WCF on Windows 7 Beta (build 7000) and your best bet is to install IIS locally test your services in there. Now, there might be some problems getting IIS to read your service certificate and my colleague Tomas helped me get things running. I thought I might as well blog it here so that I got it documented…
Open a VS2008 Command Prompt (I ran it as administrator) and create a certificate, then add it to your local store:
makecert.exe -sr LocalMachine -ss My -a sha1 -n CN=localhost -sky exchange -pe
certmgr.exe -add -r LocalMachine -s My -c -n localhost -r CurrentUser -s TrustedPeople
Then you have to give IIS access to the private part of the certificate and Tomas found some sample code to let you do that. The FindPrivateKey.exe source code is available on MSDN. Keep working on the command prompt:
FindPrivateKey.exe My LocalMachine -n "CN=localhost"
Note the output for private key directory and filename, for example:
Private key directory: C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys
Private key file name: 288538e27a2aebe9f77d2506bf6c836a_adf55683-4eae-4544-bbd1-d6844a44e538
Then use them to feed the final call to give the default IIS-user access to the private key, for example:
CACLS.exe C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\288538e27a2aebe9f77d2506bf6c836a_adf55683-4eae-4544-bbd1-d6844a44e538 /G "IIS_IUSRS":R
That should be it, and it worked on our machines.
-
Bad Request With WCF Service in Cassini On Windows 7 Beta
Trying to run a WCF service in Cassini on your Windows 7 Beta (7000) machine and get this error?
The remote server returned an unexpected response: (400) Bad Request.
Unless you’re running your service with basic http binding or with security specifically set to None in your bindings, you will get this security-related error. This problem was confirmed by Microsoft and will (hopefully) be fixed in next Windows 7 release.
The options you got:
- Create and run your own service host with code (I’ve been doing this in my integration tests until I tried Cassini and got the error)
- Use IIS (which I’m going to go for)
- Self-host it with WcfSvcHost.exe (which I’ve not tried yet)
Note that you need to add quite a few features to get WCF running in IIS running on Windows 7. See my previous post about this.
Richard Fennell had the same problems as well as a few others out there brave enough to try out a beta operating system.
-
Turn Windows 7 Features On or Off
I’m trying to install/add IIS features to my Windows 7 beta build 7000 laptop. You got pretty fine grained control over these features in Windows 7, and it’s not easy to know what you really need. I need to run WCF services on my machine, so I’m turning most things on, including WCF Activation stuff:
Then I’m adding these things that I think I need for your average ASP.NET application:
Finally I’m adding the management tools, including the IIS 6 compatibility stuff which I’ve been told is needed to play properly with VS2008:
Then restart and make sure you got everything in place.
-
Integration Testing WCF Services with Unity
I've been blogging a few times now about using Unity with WCF, but how do you integration test your service in an easy way without? The way I (and many others) do integration tests for a WCF service is by setting up my own service host and starting the service from test init:
[TestClass]
public class ServiceIntegrationTest
{
private static ServiceHost serviceHost;
[ClassInitialize]
public static void MyClassInitialize(TestContext testContext)
{
serviceHost = new ServiceHost(typeof(Service1), new [] { new Uri("http://127.0.0.1:8001/") });
serviceHost.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), "Service1");
serviceHost.Open();
}
[ClassCleanup]
public static void MyClassCleanup()
{
serviceHost.Close();
}
[TestMethod]
public void Should_get_data()
{
var ep = new EndpointAddress("http://127.0.0.1:8001/Service1");
var proxy = ChannelFactory<IService1>.CreateChannel(new BasicHttpBinding(), ep);
var data = proxy.GetData(1);
Assert.IsTrue(data == "You entered: 1", "Got wrong data back, got - '" + data + "'");
}
}
By doing it this way I don't have to make sure Cassini is started up before the test or having to deploy the service to a local IIS. There is no need for web.config or app.config files and I don't have to add any service reference. This way of doing integration testing of services is described by many others, and it should work quite well on a TFS build server or similar.
Integration Testing WCF Service with Unity
A few blog posts away I wrote about using Unity with WCF, but how do you integration test a setup like that? Remeber that if you have created your own ServiceHostFactory, you specify the factory to use in the .svc markup using the Factory attribute this:
<%@ ServiceHost Language="C#" Debug="true" Factory="IRM.Patterns.UnityService.UnityServiceHostFactory" Service="WcfService3.Service1" CodeBehind="Service1.svc.cs" %>
The "problem" here is that the factory doesn't have any decent public methods to let you create the service host from a given service type. True, there is a CreateServiceHost method which accepts a string representation of the type, but that means your service host factory has to have a reference to the type in question. The way I went around that small issue is by creating a small "harness" around the factory, with a public method which accepts a Type:
public class UnityServiceHostFactoryHarness : UnityServiceHostFactory
{
public ServiceHost CreateServiceHost(Type serviceType, string baseAddress)
{
return CreateServiceHost(serviceType, new[]
{
new Uri(baseAddress)
});
}
}
A small change to the test-initialize method makes use of this test-harness:
[ClassInitialize]
public static void MyClassInitialize(TestContext testContext)
{
var serviceHostFactoryHarness = new UnityServiceHostFactoryHarness();
serviceHost = serviceHostFactoryHarness.CreateServiceHost(typeof(Service1), "http://127.0.0.1:8001/");
serviceHost.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), "Service1");
serviceHost.Open();
}
Now we're running service integration tests and we have the Unity container loaded as well. I'm sure there are other, smarter and for me uknown ways of achieving the same, but it works for me :) If you want sample code for the UnityServiceHostFactory, please let me know, but know that my code is based on the this sample.
-
NHibernate and WCF is Not a Perfect Match
From the last days of playing around with and learning NHibernate it's quite clear to me that NHibernate is not a perfect match for a WCF solution. I'm perfectly aware of the fact that I'm still a total NH newbie, so please correct me or help me out if you can.
From the moment I heard of Hibernate years ago I thought it was best made for stateful solutions and not web apps or web services, and from what I can see that is still the case. I like many of the things I see in NH, especially the way you can map existing and bad looking databases to better looking domain entities, and the work on NHibernate Fluent looks promising.
You have to understand how lazy loading does (not) work with web services and serializing problems you may run into. But I think the biggest problem lies in the session management of NHibernate and where to open and close your NHibernate session. I won't even go into the different options proposed by hundreds of bloggers, just Google it. The thing is I don't want to be dependant on more 3rd party or open source components than necessary - it can easily get out of control.
I still want to use NHibernate for our WCF project because I do think can help us map the old, existing database we have to work with to decent domain entities, but I'm afraid we will run into weird problems later on. This approach seems to be one of the best so far, but I need to test it out some more and I'm not sure it will handle lazy loaded/HasMany data. Quite a few projects have run into problems with the session being closed before the serialization of lazy loaded objects happens :/
We may have to use EF instead.
-
WCF, Unity and NHibernate - First Findings
This blog post is to continue on the one I wrote a few days ago about a new architecture for a WCF project we're trying out.
My colleague Tomas and I sat down the whole day yesterday and dug into the topic and came out with a first rough code architecture that seems to work. Both of us knows WCF pretty well, but we're new to Unity and NHibernate so this baby has to be tested thoroughly :)
First, thanks to Ray Henry, who wrote a couple of nice posts about how to use Unity with WCF. That information was superb. Basically we're using a custom Service Host Factory which we point at from the .svc markup file:
<%@ ServiceHost Language="C#" Debug="true" Service="WcfUnity.TestService"
CodeBehind="TestService.svc.cs" Factory="WcfUnity.UnityService.UnityServiceHostFactory" %>The UnityServiceHostFactory is where we currently registers the types that is to be injected into our code. Right now we're doing it in code, and we're only working with 2 classes; the NHibernate Repository and the NHibernate Session Manager (which is a singleton):
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var unity = new UnityContainer()
.RegisterType<IRepository, NHibernateRepository>()
.RegisterType<INHibernateSessionManager, NHibernateSessionManager>(new ContainerControlledLifetimeManager());
var host = new UnityServiceHost(serviceType, baseAddresses)
{
Container = unity
};
return host;
}
The Session Manager is responsible for setting up the NHibernate Session Factory which is expensive and you only want to do that once. In short - the factory creates a new WCF service host which creates a service behavior which is called each time before a requested service class is instantiated. To be able to resolve and inject our registered classes, the behavior uses a specific instance provider which does Resolve as part of its GetInstance() method. It's all described in detail by Ray in his post, so go check it out. I've not seen a better example of Unity + WCF out there yet and from what I can see in our, so far limited, testing it works well.
When that plumbing is done (some 4 small classes, that's all), we got a very clean service implementation class with the IRepository injected into it:
public class TestService : ITestService
{
private readonly IRepository _repository;
public TestService(IRepository repository)
{
_repository = repository;
}
// ITestService members goes here...
}
You don't see any trace if a container, just the way it should be. Currently we're looking at our Repository interface and a decent syntax for a Unit Of Work. I'm fond of the lambda style of coding, and I'm playing something like this now:
var response = new GetPersonResponse();
_repository.UnitOfWork(() =>
{
var person = _repository.Find<Person>(request.Id);
ret.Person = person;
});
return response;
Or for a transaction:
var response = new AddPersonResponse();
_repository.TransactionalUnitOfWork(() =>
{
_repository.Save(request.Person);
response.Person = _repository.Find<Person>(request.Person.Id);
});
return response;
The TransactionalUnitOfWork method would do things like:
public void TransactionalUnitOfWork(Action action)
{
_session = sessionManager.GetSession();
var transaction = _session.BeginTransaction();
try
{
action();
transaction.Commit();
}
catch (Exception)
{
transaction.Rollback();
throw;
}
finally
{
transaction.Dispose();
_session.Close();
}
}
The "problem" is that the UoW shouldn't go into the repository implementation, it's wrong but I'm only trying things out here. I might as well wrap the opening and closing of a NH Session and transaction within an IDisposable and call it my UoW as many others have done before me, but I kind of like this. Have to think about not letting things that should stay inside the repository "leak" out... At this moment we're only playing around with things :)
We also need to encapsulate and inject business rules in a good way as we will host the services at more than one customer with different rules. MEF could be an option actually... more on that later :)
-
Please Feedback! Unity, nHibernate, Fluent, Linq... Trying New Architecture Combinations
We're thinking about a new architecture for a set of pretty large WCF (and perhaps also REST) services that's going to be developed during the next year and perhaps you dear reader would like to comment!
The services themselves are pretty straight forward, we're going to serve data from a huge SQL Server database which unfortunately is old and lacks relationship/fk/pk between most tables. Nothing we can do about that I'm afraid but we thought that nHibernate could be a good way to map data to domain objects. Some of the services will need to handle more complex business rules, but no heavy computing or long running stuff (not atm anyway).
What more can I say... everything is going to be running on .NET 3.5, and we have a pretty good view of the business domain, we're currently modelling the information/domain together with the customer and we will probably be developing the whole thing in a DDD-ish way, using unit and integration tests, IoC...
So, currently we're thinking of WCF/REST for the service layer, Unity as container and building something around nHibernate for the Repository (looking at the IRepository implementation in Fluent). We're new to nHibernate but have been looking at nHibernate.Linq which looks really nice, and I think we'll use the Fluent API and map the classes in code instead of using XML configuration (which I'm allergic against). Just have to figure out a good way to make it all fit together, especially to get a decent UnitOfWork to work with the nHibernate session and the repository. I'll see what I come up with and post it here.
Ideas? Please comment or send me an email of you like.
-
WCF Client Calling ASMX Service with Soap Headers
Need to send soap headers from WCF (Service Reference) clients to older ASMX services? The ASMX service not handling the header properly? It may have to do with namespaces being set in the soap header XML in a way differently from what the ASMX service is expecting.
So, how do you create and add the same type of headers, with the correct namespace, in a WCF client? For every outgoing call?
First, a simple ASMX service for your pleasure to play with:
[WebService(Namespace = "http://tempuri.org/")]
public class Service1 : WebService
{
public MyHeader myHeader;
[WebMethod]
[SoapHeader("myHeader")]
public string HelloWorld()
{
if (myHeader != null)
return "Got header: " + myHeader.MyFirstValue + " " + myHeader.MyOtherValue;
return "Got no header!!";
}
}
That's it on the server side. Over to the client side... Well, the header itself can be either a class which implements the MessageHeader class, but I prefer to use a normal class decorated with DataContract attribute. Notice the namespace property which matches the one on the service above:
[DataContract(Namespace = "http://tempuri.org/")]
public class MyHeader
{
[DataMember]
public string MyFirstValue { get; set; }
[DataMember]
public string MyOtherValue { get; set; }
}
In ASMX clients you normally create a soap extension to add the header to every outgoing call, but here the ASMX soap extension is replaced by a (Client)MessageInspector in WCF, which is added to a client endpoint via a behavior. I'm cramming the whole sample implementation into one class:
public class AddSoapHeaderBehavior : BehaviorExtensionElement, IClientMessageInspector, IEndpointBehavior
{
#region IClientMessageInspector Members
public void AfterReceiveReply(ref Message reply, object correlationState) { }
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
var myHeader = new MyHeader { MyFirstValue = "Yeeehaaaw!!", MyOtherValue = "Gaaah!" };
var messageHeader = new MessageHeader<MyHeader>() { Actor = "Anyone", Content = myHeader };
request.Headers.Add(messageHeader.GetUntypedHeader("MyHeader", "http://tempuri.org/"));
return null;
}
#endregion
#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior) { behavior.MessageInspectors.Add(this); }
public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher) { }
public void Validate(ServiceEndpoint serviceEndpoint) { }
#endregion
#region BehaviorExtensionElement Members
protected override object CreateBehavior() { return new AddSoapHeaderBehavior(); }
public override Type BehaviorType { get { return GetType(); } }
#endregion
}
The endpointbehavior and behaviorextensionelement member implementations are just boilerplate stuff that should be hidden as default behavior by WCF if you ask me, but you need to type this out.
Finally, the behavior must be loaded in the config (or via code):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="MyEndpointBehaviors">
<ClientSoapHeaderAdderBehavior />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="ClientSoapHeaderAdderBehavior"
type="MyBehavior.AddSoapHeaderBehavior, MyBehavior, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
<client>
<endpoint name="Service1Soap"
address="http://localhost:4221/Service1.asmx"
binding="basicHttpBinding"
behaviorConfiguration="MyEndpointBehaviors"
contract="ClientProxy.Service1Soap" />
</client>
</system.serviceModel>
</configuration>
Hope it helps someone.
-
Returning Json from RESTful Interface with WCF
Someone commented on an earlier blog post I did on REST, POX/POJO and WCF and the comment read:
How about REST WCF bits from .NET 3.5 SP1? Is it possible now to let the user decide in which format he wants the response (xml or json) like MySpace API for example?
The convention is to use a file like extension at the end of the resource to specify data return type (.xml or .json)
UPDATE/EDIT: Turns out I was doing this the hard way as there is support for json serialization right from the ServiceContract which makes this extremely easy. Just make sure to specify the ResponseFormat to be json. In a previous "version" of this blog post, I used the JavaScriptSerializer class, which is... dumb :)
First go take a look at the sample that Kirk Evans had on his blog.
Note that it may be easier to create a RESTful interface with ASP.NET MVC if you're into that tech, but that's another blog post.
So, first I'm modifying the REST interface somewhat, adding support for /details.xml and /details.json URI:
[ServiceContract] public interface IService { [OperationContract] [WebGet(UriTemplate="customers/{id}/details.xml")] Customer GetCustomer(string id); [OperationContract] [WebGet(UriTemplate = "customers/{id}/details.json",
ResponseFormat=WebMessageFormat.Json)]
Customer GetJsonCustomer(string id); }As you can see, on the GetJsonCustomer() method, I'm specifying the ResponseFormat to be json. That's it :)
A sample implementation for this interface looks like this:
public Customer GetCustomer(string id) { return new Customer { ID = id, Name = "Demo User" }; } public Customer GetJsonCustomer(string id) { return GetCustomer(id);
}
Using Fiddler to simulate client request and see what comes out of our RESTful service, we get this result from the /customers/123/details.xml request:
<Customer xmlns="http://schemas.datacontract.org/2004/07/RESTfulWCF" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><ID>1</ID><Name>Demo User</Name></Customer>
...and this from the /customers/123/details.json request:
{"ID":"123","Name":"Demo User"}
-
Why Developers Are Interested in REST
I had a laugh when I saw James Kovacs' blog post abot Why Developers are Interested in REST:
I'm doing some WCF work for a client, specifically around WS-Security. I stumbled upon the System.ServiceModel.MessageSecurityVersion class today. Its static properties alone should explain why developers are craving simpler technologies like REST...
- WSSecurity10WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10
- WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10
- WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12
- WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10
- WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11
- WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10
I think he's got a point there actually. Web services with WCF can be very easy to use, and it can be so very complex it'll get your head to spin. The REST and POX/POCO style of services is definitely getting more attention, even from within Microsoft. WCF now supports RESTful interfaces, and we've seen REST-related demos by well known Microsoft presenters several times now, especially around WCF, EF and Astoria/ADO.NET Data Service. Also, it's very easy to create a RESTful service with ASP.NET MVC. We saw several REST-related presentations at Mix07 and Mix08 and I'm sure there will be a lot of REST/POCO/POX/Atom demos at PDC later this year.
Ofcourse there will be a number of situations and type of applications which require a more complex protocol than what REST can offer, but as a developer and software architect who prefers simple solutions, I just love the simplicity of it all. Or maybe I'm just old and smilingly recognize old techniques coming back again - we did XML on (S)HTTP with ASP years and years ago, didn't we? And it worked pretty darn well I can tell you ;)
The "REST effect" is perhaps the result of the WS-* race, which in my opinion exceeded the speed limit a long time ago. It's just impossible for an average human beings to keep up with it unless you want to become a WCF/WS expert and do nothing much else, which is not an option for me. I know, there are people out there, like my colleague Eric, who groks it all, but he's not human ;)