Tim Scott's Blog

March 30, 2012

Self-Hosting WebApi as a Windows Service with TopShelf

Filed under: C#, WebApi — Tim Scott @ 5:24 pm

Are you using WebApi for your services. If not (and you’re a Microsoft shop), you should be.

I’m creating a REST service. I want to host it on a machine without IIS.  No problem, WebApi supports self hosting.  But in production, it really needs to run as a Windows Service, not a console app.  How to do that?  Enter TopShelf.  TopShelf makes it easy to host a service either in a console or as a Windows Service.

My service class.

public class MyWebApiService
{
    private readonly HttpSelfHostServer server;
    private readonly HttpSelfHostConfiguration config;

    public MyWebApiService(string baseAddress, IDependencyResolver resolver)
    {
        config = new HttpSelfHostConfiguration(baseAddress);
        config.ServiceResolver.SetResolver(resolver);
        config.Filters.Add(new ExceptionFilter());
        config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
        server = new HttpSelfHostServer(config);
    }

    public void Start()
    {
        server.OpenAsync();
    }

    public void Stop()
    {
        server.CloseAsync();
        server.Dispose();
    }
}

And here’s how to make that service run under TopShelf.

static void Main(string[] args)
{
    var container = Bootstrapper.RegisterDependencies();
    var resolver = new StructureMapDependencyResolver(container);

    HostFactory.Run(x =>
    {
        x.Service<MyWebApiService>(s =>
        {
            s.SetServiceName("My Web Api Service");
            s.ConstructUsing(name => new MyWebApiService(BASE_ADDRESS, resolver));
            s.WhenStarted(svc => svc.Start());
            s.WhenStopped(svc => svc.Stop());
        });
        x.RunAsLocalSystem();
        x.SetDescription("Does really cool stuff.");
        x.SetDisplayName("My Web Api Service");
        x.SetServiceName("MyWebApiService");
    });
}

To create a Windows Service, run your console app with a switch.

MyWebApiService.SelfHost.exe install

That’s it! Enjoy.

Advertisements

July 17, 2009

ShouldIt Gets More Fluent

Filed under: C#, Test Driven Development, Unit Testing — Tim Scott @ 3:26 am

ShouldIt now gives you the option to use a more fluent syntax.  For example, the following:

result.ShouldNotBeNull();

Can now be expressed as:

result.Should().Not.Be.Null();

You can still chain asserts as before.  So this:

personList
    .ShouldCount(1)
    .ShouldContainOne(x => x.Id == exptected.Id)
    .FirstName.ShouldEqual("Jim")

Can now alternatively be expressed as:

shouldList
    .Should().Count.Exactly(1)
    .Should().Contain.One(x => x.Id == exptected.Id)
    .FirstName.Should().Equal("Jim");

The new syntax can be found in the ShouldIt.Clr.Fluent namespace in the Should.Clr assembly.

Why the new syntax?  Whether it’s more or less readable is largely a matter of taste.  For me, words separated by dots are an improvement over Pascal cased phrases.    However, the extra parentheses surely do not help. (Anyone else wish that parens were optional for calls to methods with no parameters?)  Nonetheless, I think that the new syntax has some nice advantages.

  1. Better Intellisense. With the old style, Intellisense offers a long list of every possible assertion for the target type.  It’s annoying to scroll through the list and/or type the entire word “should” plus one more letter before the list shirinks.  Using the new style, only one extension method appears at first.   As you type each new node, the list remains very small until you narrow down to the assertion that you want.   Overall I believe that this will facilitate faster and more accurate coding.
  2. More Maintainable And Extensible. The original extension methods all live together in one big fat static class.  The new code is more object oriented and spreads responsibilities over more small classes.  While this does not immediately provide any value to the user, it will make it easier to add nice features over time.

Give it a try and let me know what you think.

November 24, 2008

MvcFluentHtml – Fluent HTML Interface For MS MVC

Filed under: C#, FluentHtml, MS MVC — Tags: , — Tim Scott @ 6:45 pm

UPDATE: MvcFluentHtml has been moved to MvcContrib where it lives in its own assembly, MvcContrib.FluentHtml.

A few weeks ago I attended a presentation at the KaizenConf by Jeremy Miller and Chad Myers in which they showed their “opinionated” approach to MS MVC.  One of the things that caught my attention was the fluent interface they had created for HTML generation.   So I went home and started working on this for my own application.

I have put my work in progress here: MvcFluentHtml.

Incidentally, since I started working on MvcFluentHtml, Chad and Jeremy have put out some bits of their code as opinionatedmvc.  And Karl Seguin, who also saw their presentation, has created some fluent HTML stuff which he shows in this blog post.

So what problem does MvcFluentHtml solve?  Can’t I be happy with the HtmlHelpers that come with the framework?

I have come to truly hate the overloading approach taken by the out-of-the-box Html helpers.  Methods with long signatures are hard to read, and it takes investigation to see what’s happening.  What’s worse, you must worry about problems with overload resolution, especially when some parameters are typed as object.  As a result, HtmlHelper is not easily extensible.  It’s hard to bend it to do new things without breaking existing functionality.  We saw an example of this when Beta1 was released with breaking changes.  With a fluent interface, it’s much easier to extend with new behaviors while leaving existing behaviors closed.

So how does it work?  Let’s start with some examples of how you might use it in your views:

<%=this.TextBox(x => x.FirstName).Class("required").Label("First Name:")%>
<%=this.Select(x => x.ClientId).Options((SelectList)ViewData["clients"]).Label("Client:")%>
<%=this.MultiSelect(x => x.UserId).Options(ViewModel.Users)%>
<%=this.CheckBox("enabled").LabelAfter("Enabled").Title("Click to enable.").Styles(vertical_align => "middle")%>

As you can see in this example, the helpers are methods of the view itself, not of some helper class.  You will also notice two different kinds of methods.  One kind takes the name as a string which is meant to evaluate to an object in the ViewData dictionary.  These methods are extensions of IViewDataContainer, and as such they can be used in any type of view (ViewPage, ViewPage<T>, ViewUserControl, ViewUserControl<T>, ViewMasterPage, ViewMasterPage<T>).   The other kind takes a lambda expression that refers to a member of ViewData.Model.  This kind of method extends a new interface that is defined in MvcFluentHtml MvcContrib.FluentHtml:

public interface IViewModelContainer<T> where T : class
{
    T ViewModel { get; }
    IEnumerable<IMemberBehavior> MemberBehaviors { get; }
}

Both kinds of methods set the value (value attribute, inner text, etc.) from ViewData.  Both kinds set the name of form elements so that most binders will pick up the value on post.

So what must you do before you can use these methods in your views?  To use the methods that extend IViewDataContainer, nothing.  To use the methods that extend IViewModelContainer<T>, you have some options:

  1. Derive your strongly-typed views from ModelViewPage<T>, ModelViewUserControl<T> or ModelViewMasterPage<T> which are bits of MvcFluentHtml.
  2. Implement IViewModelContainer<T> directly on your views.
  3. Define your own base view classes that implement IViewModelContainer<T>.

There is a fourth option.  MvcFluentHtml contains a set of classes, ConventionModelViewPage<T>, ConventionModelViewUserControl<T> and ConventionModelViewMasterPage<T>.  These classes apply some default behaviors.  These behaviors operate on certain model attributes, which are also part of MvcFluentHtml MvcContrib.

So given this model:

public class Person
{
    [Required]
    [MaxLength(200)]
    public string Name { get; set; }
}

And this in the view:

<%this.TextBox(x => x.Name)%>

The resulting HTML would be something like:

<input type="text" maxlength="200" id="Name" name="Name" class="required" value="Pete"/>

These attributes are found in a separate assembly, MvcFluentHtml.Attributes MvcContrib.ModelAttributes.  So in case your models are in a separate assembly from your MVC web UI, you don’t have to reference the UI specific bits in your model assembly.

But what if you want different behaviors and different attributes?  You can create custom behaviors by implementing IMemberBehavior.

public interface IMemberBehavior
{
     void Execute(IMemberElement element);
}

For example:

public class MyMemberBehavior1 : IMemberBehavior
{
    public void Execute(IMemberElement element)
    {
        var helper = new MemberBehaviorHelper<RequiredAttribute>();
        var attribute = helper.GetAttribute(element);
        if (attribute  != null)
        {
            element.SetAttr("class", "req");
        }
    }
}

Then create your own “opinionated” views something like this:

public class MyOpinionatedModelViewPage<T> : ModelViewPage<T> where T : class
{
     public MyOpinionatedModelViewPage() : base(new MyMemberBehavior1(), new MyMemberBehavior2()) { }
}

Or using your favorite IoC container:

public class MyOpinionatedModelViewPage<T> : ModelViewPage<T> where T : class
{
     public MyOpinionatedModelViewPage(IMyMemberBehavior1Marker myBehavior1, IMyMemberBehavior2Marker myBehavior1) : base(myMemberBehavior1, myMemberBehavior1) { }
     public MyOpinionatedModelViewPage() : base(IoC.Resolve<IMyMemberBehavior1Marker>(), IoC.Resolve<IMyMemberBehavior2Marker>()) { }

}

One final point.  The goal of MvcFluentHtml was to leave the opinions to you.  We did this by allowing you to define your own behaviors.  However, it is not without opinions regarding practices. For example the Select object does not have any “first option” functionality. That’s because in my opinion adding options to selects is not a view concern. Also, while we allow you to set inline styles we do not expose any methods that abstract styling (e.g., Width, TextAlign).  That’s because we want to encourage semantic HTML and leave the styling to CSS.  For the same reason we do not render any layout tags (e.g. <br/>).  Also we generally don’t try to abstract the language of HTML (e.g., we use “Select” instead of “DropDownList”).  In my opinion, MvcFluentHtml is more of a helper library than an abstraction over HTML, and moving developers away from understanding what’s going on with the HTML is not a good thing.

I heartily welcome critique, especially if you want to contribute! Areas that I know need some work are: radio button, radio button list, checkbox list, performance tweaks, XML comments, and CI.

March 20, 2008

Introducing DbVerse – A Tool For Database Change Management

Filed under: C# — Tim Scott @ 8:25 pm

I have just released DbVerse, an open source solution to the problem of database change management in software development.

Let me describe the problem that DbVerse seeks to solve:

Your team has gotten a good start developing a new application. Like most business applications, yours uses a relational database for persistence. You’ve partially defined the database schema. Each developer has a copy of the dev database on their local machine. Things are humming along nicely. Then Sally adds a new feature which requires adding a column to the Orders table. How do you get that change applied to all other developer machines, your CI server and your QA server all in lockstep with the code that depends on that change? Before you’re done dealing with Sally’s change, Jim adds an record to the OrderTypes lookup table. The code will break without it.

So you have struggled through development by emailing change scripts here and there. Or perhaps you periodically replace every instance of the database with a master copy that is kept in the source code repository. You are not too bothered by the fact that once you week or so you chase your tale for an hour because your local database is missing some recent change. You’re also not too worried that 20% of your integration tests no longer pass because they are never run on the CI server. But now you have gone into production. Version 1 of the database is deployed and is piling up production data. Development continues. By what process will you apply new schema changes to production? How will you keep track of which changes go with the new version you’re about to deploy? How will you be certain they have not yet been applied?

DbVerse provides a system to manage this whole process. Developers author database changes in .NET code or SQL scripts. These changes are versioned with rest of the source code and thus immediately available to the entire development team. Developer and CI databases can be automatically rebuilt to match the current code from a command line (and therefore a build script) or via a Windows UI. Likewise QA and production databases can be automatically updated with only new changes via command line or via a Windows UI.

Under the hood, DbVerse uses SQL Management Objects (SMO) for authoring changes in code. Therefore it is targeted at SQL Server based applications. DbVerse uses a project template for easy setup, which creates a C# project. It would be possible to use DbVerse with Visual Basic, but this has not been tested.

September 11, 2007

Monorail: CheckboxListComponent

Filed under: C#, Castle Project, Monorail — Tim Scott @ 1:10 pm

I have recently created CheckboxListComponent and added it to CastleContrib ViewComponents. This Monorail view component provides a simple way to render data-bindable checkbox lists. Check it out. I hope you like it and find it useful!

July 21, 2007

Monorail: ColumnChartComponent

Filed under: C#, Castle Project, Monorail — Tim Scott @ 7:04 pm

Many Webforms developers are resistant to Monorail and for various reasons. I would guess that the second biggest reason, behind simple intertia, is the perceived lack of rich UI components. Recently Ayende decided to do something about it by adding a Castle.MonoRail.ViewComponents to Castle Contrib. It’s a place to aggregate view components that might be generally useful to Monorail UI development.

I have recently created ColumnChartComponent and added it to CastleContrib. ColumnChartComponent renders fairly basic column charts. (By “column chart” I mean charts with vertical bars.) Check it out.  I hope you like it and find it useful!

June 14, 2007

Ordering Computed Fields In ActiveRecord With ICriteria

Filed under: Active Record, C#, Castle Project — Tim Scott @ 11:48 pm

If you use ActiveRecord and ICriteria to fetch collections, this probably looks familiar:

DetachedCriteria criteria = DetachedCriteria.For(typeof(TaskEstimate));
...
criteria.AddOrder(Order.Asc("OptimisticHours"));
IList<TaskEstimate> estimates = TaskEstimate.FindAll(criteria);

The criteria object tells the FindAll method to sort the results ascending by the persisted property, “OptimisticHours.” But let’s say you have another persisted property “PessimisticHours,” and you want to sort by the difference between the optimistic and pessimistic estimates. That is to say, you want to sort by a computed value instead of a persisted property. Here’s how:

First you add the following to the TaskEstimate class:

private int _estimateDelta;
[Property(Formula = "PessimisticHours - OptimisticHours")]
public int EstimateDelta
{
    get { return _estimateDelta; }
    set { _estimateDelta= value; }
}

Then you can do this:

criteria.AddOrder(Order.Asc("EstimateDelta"));
IList<TaskEstimate> estimates = TaskEstimate.FindAll(criteria);

What’s happening here is that ActiveRecord is providing us access to the NHibernate mapping feature that allows you to define a property with a formula attribute.

May 9, 2007

Remoting Using WCF and NHibernate

Filed under: C#, NHibernate, WCF — Tim Scott @ 5:00 am

By Tim Scott and Greg Banister

UPDATE – 3/5/09 – There is ongoing discussion in the community over remoting versus a service oriented architecture (SOA).  Almost two years after its publication this post continues to to get a lot of traffic, and so we feel it’s appropriate to add a small comment with our opinion on the matter.   We generally do not recommend remoting (sending domain objects over the wire), and would in almost all cases today, prefer an SOA approach. This article shows how we solved a specific technical problem in implementing a smart client application using a remoting architecture.   It has value on that basis.

Introduction

Windows Communication Foundation (WCF) is Microsoft’s unified messaging framework for building distributed applications. It is targeted at two types of applications:

  • distributed objects applications
  • service oriented applications (SOA)

Let’s define what we mean by each. “Distributed objects applications” are applications where client and service share common custom business object types and pass these objects back and forth over the wire. Conversely, SOAs typically hide business object types and pass lighter data transfer objects between client and service. Microsoft intends for WCF to supersede ASMX Web Services for SOA applications and .NET Remoting for distributed objects applications.

NHibernate is a port of Hibernate, the popular open source object‑relational mapper for Java. NHibernate has been gaining popularity in the .NET world, and we are avid users. As we will discuss in this article, it is possible to build a distributed objects application using WCF for messaging and NHibernate for object persistence. But to pull this off you have to know some tricks. As one wades into the WCF waters, one discovers that WCF has a lot of tricks. Articles and samples abound for WCF, but we could find none that address the issues that we faced. In this article we will share what we learned.

The Application

In early 2006 our team committed to create a “smart client” application using WCF for communications between a WinForms client and a Web service. Client and service would contain a common business domain assembly and would pass business objects back and forth. We also decided to use NHibernate for object persistence. This sounded great on paper, and after a little hacking we got it to work, or so we thought.

As we prepared to develop this application, we studied many WCF articles and “getting started” examples. We even created a “spike” application using WCF together with NHibernate. Based on all this research we made dozens of explicit configuration choices. We made many more choices by default.

The Problem

One such default choice was to use the DataContractSerializer. Only much later did we learn that Microsoft recommends the DataContractSerializer specifically because it assumes the client knows nothing of .NET types. This keeps coupling between client and service loose and so maximizes cross‑platform interoperability. The DataContractSerializer, we realized at long last, was the problem.

So why was it the problem? In a word, collections. Complex business objects typically have collections (e.g., Order has LineItems). One thing we love about NHibernate is how nicely it handles persistent collections. It provides various custom collection types that implement IList. We use the NHibernate Bag for all of our collections. Bag contains several properties that help NHibernate detect changes to collections and persist them properly. By using some clever versioning techniques, NHibernate always knows which members of collections to insert, update and delete any time you save its parent object.

As an aside, NHibnerate has other choices for collections besides Bag. There are Sets, Lists, Maps, Arrays, SortedSets, SortedMaps and IdBags, all of which, like Bag, inherit from NHibernate.Collection.PersistentCollection. This article addresses only the Bag type. We would guess the same problems and solutions apply to these other types as well; however, we have not used these types, so we cannot say for sure.

Back to the DataContractSerializer. It is capable of serializing custom objects. To accomplish this you simply decide which classes and class members to share and decorate them with DataContract attribute and DataMember attribute respectively. If the class members are not primitive types, you can further decorate your classes with KnownType attributes. This attribute tells WCF that both sender and receiver understand the custom type. Here is an example of a Company class decorated for WCF:

[DataContract]
[KnownType(typeof(NHibernate.Collection.Bag))]
[KnownType(typeof(NHibernate.Impl.CollectionEntry))]
[KnownType(typeof(CompanyRole))]
[KnownType(typeof(Person))]
public class Company : IEntity
{
    [DataMember]
    private Guid id;
    private string name;
    [DataMember]
    private IList employeesList;   

    public Guid Id
    {
        get { return id; }
    }   

    [DataMember]
    public string Name
    {
        get { return name; }
        set { name = value; }
    }   

    private IList EmployeesList
    {
        get
        {
            if (employeesList == null)
            {
                employeesList = new ArrayList();
            }
            return employeesList;
        }
        set { employeesList = value; }
    }   

    public Person[] Employees
    {
        get
        {
            Person[] employees = new Person[EmployeesList.Count];
            EmployeesList.CopyTo(employees, 0);
            return employees;
        }
    }   

    .
    .
    .   

}

When NHibernate fetches a Company from the database, employeesList will be a Bag of Persons. We assumed that by setting Bag as a known type, WCF would properly handle employeesList. However, even with the KnownType attribute, DataContractSerializer does not properly handle NHibernate Bags. The employeesList enters the serializer as a Bag and comes out the other end as an object array. Before serialization:

bag.jpg

After serialization:

objectgraph.jpg

The following test further illustrates the problem:

[TestMethod]
public void DataContractSerialization_will_change_the_type_of_a_Collection()
{
    Company company = GetCompanyFromNhibernate();   

    //company.EmployeesList made public for the purpose of this demo
    Assert.AreEqual(typeof(NHibernate.Collection.Bag), company.EmployeesList.GetType());   

    List<Type> knownTypes = new List<Type>();
    knownTypes.Add(typeof(Person));
    knownTypes.Add(typeof(NHibernate.Collection.Bag));
    knownTypes.Add(typeof(NHibernate.Impl.CollectionEntry));
    DataContractSerializer serializer = new
             DataContractSerializer(typeof(Company),knownTypes);   

    //serialize company to a memory stream
    Stream stream = new MemoryStream();
    serializer.WriteObject(stream,company);   

    //deserialize the memory stream back to a company
    stream.Position = 0;
    company = (Company) serializer.ReadObject(stream);   

    Assert.AreNotEqual(typeof(NHibernate.Collection.Bag), company.EmployeesList.GetType());
    Assert.AreEqual(typeof(object[]), company.EmployeesList.GetType());
}

One might expect that NHibernate to blow up when it encounters a persisted collection that has morphed into a simple object array. Not so! After a small hack that we created, NHibernate was able to persist updates and inserts just fine. However, it was not able to figure out deletions. Rather than deleting an item that had been removed from the collection, it simply de‑referenced it. That is, it updated the foreign key to its parent (in the preceding example, CompanyID) to NULL. These de-referenced items end up as orphaned records in the database. In our case, for certain collections, the result was hundreds of thousands of orphans.

The Solution

We recall vividly the moment we discovered this problem. Once we stopped sobbing uncontrollably, we pressed on and worked out a solution (sort of). We added a bunch of tricky code to our persistence layer to detect orphans and delete them from the database. We’ll not belabor the point by explaining this complex hack; suffice it to say it was both ugly and inefficient!

Then one day, almost by accident, we found the NetDataContractSerializer. Actually we had known about it, but we hadn’t grasped what it was. The NetDataContractSerializer, unlike its brother the DataContractSerializer, serializes .NET type information. To use it both client and server must understand .NET types. Cross‑platform interoperability is lost, which was fine in our case. Our client and service are by nature tightly coupled – they share a business domain.

So we gave the NetDataContractSerializer a try. To our delight it serialized NHibernate Bags just fine. Problem solved! The following test illustrates:

[TestMethod]
public void NetDataContractSerialization_will_Not_change_the_type_of_a_Collection()
{
    Company company = GetCompanyFromNhibernate();   

    //company.EmployeesList made public for the purpose of 
    //this demo
    Assert.AreEqual(typeof(NHibernate.Collection.Bag), company.EmployeesList.GetType());   

    NetDataContractSerializer serializer = new NetDataContractSerializer();   

    //serialize company to a memory stream
    Stream stream = new MemoryStream();
    serializer.Serialize(stream, company);   

    //deserialize the memory stream back to a company
    stream.Position = 0;
    company = (Company)serializer.Deserialize(stream);   

    Assert.AreEqual(typeof(NHibernate.Collection.Bag),company.EmployeesList.GetType());
    Assert.AreNotEqual(typeof(object[]), company.EmployeesList.GetType());
}

Soon we learned that NetDataContractSerializer solved other problems too. From the start we had wanted to pass generic types between client and service. We could not figure out how to do this using DataContractSerializer. Again, KnownType attributes did not seem to work. There might be some way to do it, but we did not find it. No matter, NetDataContractSerializer handles .NET generic types just fine.

We should mention that this application uses NHibernate 1.02. As of this writing, NHibernate has released version 1.2. We tested the application with NHibernate 1.2 before changing to the NetDataContractSerializer, and verified that it exhibits the same problem. We have not verified that the solution described here will work with NHibnerate 1.2, although we expect it will.

Using NetDataContractSerializer

Unfortunately you cannot simply flip a config switch and change serializers. You need to write some code. We created two classes, like so:

public class NetDataContractOperationBehavior : DataContractSerializerOperationBehavior
{
    public NetDataContractOperationBehavior(OperationDescription operation)
        : base(operation)
    {
    }   

    public NetDataContractOperationBehavior(OperationDescription operation, DataContractFormatAttribute dataContractFormatAttribute)
        : base(operation, dataContractFormatAttribute)
    {
    }   

    public override XmlObjectSerializer CreateSerializer(Type type, string name, string ns,
        IList<Type> knownTypes)
    {
        return new NetDataContractSerializer(name, ns);
    }   

    public override XmlObjectSerializer CreateSerializer(Type type, XmlDictionaryString name,
        XmlDictionaryString ns, IList<Type> knownTypes)
    {
        return new NetDataContractSerializer(name, ns);
    }
}   

public class UseNetDataContractSerializerAttribute : Attribute, IOperationBehavior
{
    public void AddBindingParameters(OperationDescription description, BindingParameterCollection parameters)
    {
    }   

    public void ApplyClientBehavior(OperationDescription description,
        System.ServiceModel.Dispatcher.ClientOperation proxy)
    {
        ReplaceDataContractSerializerOperationBehavior(description);
    }   

    public void ApplyDispatchBehavior(OperationDescription description,
        System.ServiceModel.Dispatcher.DispatchOperation dispatch)
    {
        ReplaceDataContractSerializerOperationBehavior(description);
    }   

    public void Validate(OperationDescription description)
    {
    }   

    private static void ReplaceDataContractSerializerOperationBehavior( OperationDescription description)
    {
        DataContractSerializerOperationBehavior dcsOperationBehavior =
        description.Behaviors.Find<DataContractSerializerOperationBehavior>();   

        if (dcsOperationBehavior != null)
        {
            description.Behaviors.Remove(dcsOperationBehavior);
            description.Behaviors.Add(new NetDataContractOperationBehavior(description));
        }
    }
}

Then in the service contract, to every method we added the UseNetDataContractSerializer attribute, like so:

[UseNetDataContractSerializer]
[OperationContractAttribute]
Company SaveCompany(CompanyUpdater companyUpdater);

NOTE: We derived the code to use NetDataContractSerializer from code examples we found on the web:

Conclusion

Our specific conclusion is, to serialize objects with NHibernate Bags using WCF, use the NetDataContractSerializer. A more general conclusion might be, if you want to distribute custom business objects between a .NET client and WCF service only, such as with a distributed objects application, use NetDataContractSerializer unless there is some compelling reason not to.

Blog at WordPress.com.