AJ's blog

February 15, 2015

WCF Policy – Part 9: Making the Information Accessible on the Server

Filed under: .NET, .NET Framework, C#, SOA, Software Architecture, Software Development, WCF — ajdotnet @ 3:14 pm

On the client we can access the tracking information. On the server this would also come in handy, e.g. to add additional tracking entries, say for lengthy operations, such as database calls.

Whenever an application developer needs access to the current context during a service call, he does so via OperationContext. And OperationContext provides with its property Extensions exactly the extension point we need – if we can place an object in there, that implements our ITrackingInformation.

Operation extensions are classes implementing IExtension<OperationContext>. Providing a class that implements both, this interface and ITrackingInformation, is a simple exercise: Just deriving from TrackingInformation – the object we used to temporarily maintain the tracking information – and implementing the interface methods trivially is sufficient:

internal class TrackingOperationContextExtension : TrackingInformation, IExtension<OperationContext>
{
    void IExtension<OperationContext>.Attach(OperationContext owner) { }
    void IExtension<OperationContext>.Detach(OperationContext owner) { }
}

Now we need to change our message inspector to maintain the tracking information in an extension, rather than a temporary object. As on the client, due to some foresight, we only need to change one method:

private ITrackingInformation GetTrackingInformation()
{
    var extension = new TrackingOperationContextExtension();
    OperationContext.Current.Extensions.Add(extension); // register extension
    return extension;
}

And that’s it. Now the application developer can get hold of the incoming tracking information and add his own entries, as he likes:

var tracking = OperationContext.Current.Extensions.Find<ITrackingInformation>();
tracking.OutgoingHeaders.TrackingEntries.Add(new TrackingEntry(typeof(TestService).Name, "My tracking information..."));

 

After the first posts addressed the design time aspects, this post concludes the runtime aspects of our policy. The following image shows the related components at runtime:

And this screenshot shows the result generated from a sample application:

 

Our policy implementation is finished at this point, however, there is another post coming, looking at aspects we did not touch.

 

That’s all for now folks,
AJ.NET

January 31, 2015

WCF Policy – Part 8: Making the Information Available on the Client

Filed under: .NET, .NET Framework, C#, SOA, Software Architecture, Software Development, WCF — ajdotnet @ 4:37 pm

Our policy has its default behavior. All the information is collected, it just is not available to the developer yet. So let’s take care of that.

We already have the basics covered, namely we have an interface ITrackingInformation through which the application developer should have access to the information. All we need to do is to build a bridge between message inspectors and the application code.

On the client the application developer uses the generated client proxy class, thus we need to pass in the tracking information to that object. The class derives from ClientBase<TChannel> and thus inherits the property Endpoint of type ServiceEndpoint. This class in turn maintains a collection of endpoint behaviors. With a custom behavior which implements our interface, the developer has the gate to our policy. Going one step further, this behavior can also register a message inspector in IEndpointBehavior.ApplyClientBehavior, which utilizes the information passed in, instead of a temporary object, as we did when we implemented this last time.

The endpoint behavior is actually quite simple:

public class TrackingEndpointBehavior : IEndpointBehavior, ITrackingInformation
{
    public TrackingHeaders IncomingHeaders { get; private set; }
    public TrackingHeaders OutgoingHeaders { get; private set; }
    
    void IEndpointBehavior.ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        clientRuntime.MessageInspectors.Add(new TrackingClientMessageInspector(endpoint, this));
    }
    […]
}

And given the fact that I “kind of had this in mind”, the changes to the message inspector are also minor: We need an addition constructor and member for the information passed in, which is boilerplate enough. Additionally the method to get the tracking information object changes slightly:

private ITrackingInformation GetTrackingInformation()
{
    var tracking = _providedTrackingInformation ?? new TrackingInformation();
    return tracking;
}

The other code worked already against the interface and does not care where the tracking information object came from. I love it when a plan comes together.

There is one thing left: The contract behavior created during code generation is still in place and still registers its own message inspector. This is still necessary in cases where the application developer does not provide the above endpoint behavior, but hurts if he does. Luckily the contract behavior’s ApplyClientBehavior method is called after the endpoint behavior’s method. So all we need to do is to check:

void IContractBehavior.ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
    var endpointBehavior = endpoint.Behaviors.OfType<TrackingEndpointBehavior>().FirstOrDefault();
    if (endpointBehavior == null)
        clientRuntime.MessageInspectors.Add(new TrackingClientMessageInspector(endpoint));
}

And, finally, the application developer can provide the endpoint behavior and use it to pass additional tracking entries in or read the tracking entry collections after the call:

var client = new TestServiceReference.TestServiceClient();
var behavior = new TrackingEndpointBehavior();
behavior.OutgoingHeaders.TrackingEntries.Add(new TrackingEntry("my code", "just for fun"));
client.Endpoint.Behaviors.Add(behavior);

var response = client.Ping(“Ping text”);
var trackingEntries= behavior.IncomingHeaders.TrackingEntries;
[…]

So far for the client, next time, we will look at the server.

 

That’s all for now folks,
AJ.NET

January 24, 2015

WCF Policy – Part 7: Implementing the Default Behavior

Filed under: .NET, .NET Framework, C#, SOA, Software Architecture, Software Development, WCF — ajdotnet @ 3:43 pm

Our policy demands that we read and manipulate the messages going in and out, on client and service. The WCF component designated for this demand is a message inspector, which is available in two flavors, designated by the interface: IClientMessageInspector for the client, and IDispatchMessageInspector for the service. Both interfaces provide two methods; one is called for the incoming message, the other for the outgoing message. The respective runtimes – ClientRuntime und DispatchRuntime – each maintain a collection of respective message inspector instances.

On the client the contract behavior created by our import extension can add the message inspector in IContractBehavior.ApplyClientBehavior, nothing more than a one-liner:

void IContractBehavior.ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
    clientRuntime.MessageInspectors.Add(new TrackingClientMessageInspector(endpoint));
}

On the server, our service behavior can do the same, only it needs to address all eligible endpoints:

void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
    foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
    {
        foreach (EndpointDispatcher ep in cd.Endpoints)
        {
            var inspector = new TrackingDispatchMessageInspector(ep);
            ep.DispatchRuntime.MessageInspectors.Add(inspector);
        }
    }
}

If the application developer calls a service method on the client proxy class, the WCF creates a message object for the resulting SOAP message. It the proceeds to call IClientMessageInspector.BeforeSendRequest on all message inspectors.

In this method our TrackingClientMessageInspector creates an ITrackingInformation object to maintain the information, creates the first tracking entry for sending the message, passes it to your header class, which will later serialize it as SOAP header, and adds it to the collection of headers. Finally it returns the ITrackingInformation object as correlation state:

private ITrackingInformation GetTrackingInformation()
{
    var tracking = new TrackingInformation();
    return tracking;
}

object IClientMessageInspector.BeforeSendRequest(ref Message request, IClientChannel channel)
{
    // get headers
    var tracking = GetTrackingInformation();
    
    // add send information
    tracking.OutgoingHeaders.TrackingEntries.Add(new TrackingEntry(_thisClient, "Send Request to " + _calledService));
    
    // tracking entries header
    var trackingEntriesHeader = new TrackingEntriesHeader(tracking.OutgoingHeaders.TrackingEntries);
    request.Headers.Add(trackingEntriesHeader);
    
    // pass headers via correlation state
    return tracking;
}

Now the SOAP message makes its journey to the service, where the WCF will create a respective message object and call IDispatchMessageInspector.AfterReceiveRequest on all message inspectors there.

Our TrackingDispatchMessageInspector deserializes the SOAP header, puts the information in a ITrackingInformation object, adds its tracking entry for receiving the message, and, again, returns the ITrackingInformation object as correlation state.

private ITrackingInformation GetTrackingInformation()
{
    var extension = new TrackingInformation();
    return extension;
}

object IDispatchMessageInspector.AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
    // install operation extension
    var tracking = GetTrackingInformation();
    
    // tracking entries header
    var trackingEntriesHeader = TrackingEntriesHeader.ReadHeader(request.Headers);
    if (trackingEntriesHeader != null)
        tracking.IncomingHeaders.TrackingEntries.AddRange(trackingEntriesHeader.TrackingEntries);
    
    // add receive information
    tracking.IncomingHeaders.TrackingEntries.Add(new TrackingEntry(_thisService, "Received Request" ));
    
    // and pass on to outgoing headers
    tracking.OutgoingHeaders.TrackingEntries.AddRange(tracking.IncomingHeaders.TrackingEntries);
    
    // pass headers via correlation state
    return tracking;
}

The WCF proceeds to call the service method, the application developer provided. Afterwards the same process goes backwards for the reply. The WCF calls IDispatchMessageInspector.BeforeSendReply for all message inspectors. It also passes in the correlation state we returned earlier. Without this information we wouldn’t be able to link the two calls in case several requests came in in parallel.

Our message inspector adds the respective tracking entry, puts in in our header class, and is done:

void IDispatchMessageInspector.BeforeSendReply(ref Message reply, object correlationState)
{
    var tracking = (ITrackingInformation)correlationState;
    
    // add send information
    tracking.OutgoingHeaders.TrackingEntries.Add(new TrackingEntry(_thisService, "Send Reply"));
    
    // tracking entries header
    var trackingEntriesHeader = new TrackingEntriesHeader(tracking.OutgoingHeaders.TrackingEntries);
    reply.Headers.Add(trackingEntriesHeader);
}

The SOAP message is sent back to the client. There the WCF again creates a message object and calls IClientMessageInspector.AfterReceiveReply for all message inspectors, passing in the correlation state, similar to what we saw on the server.

Our message inspector deserializes the SOAP header, adds its own tracking entry, and we’re done:

void IClientMessageInspector.AfterReceiveReply(ref Message reply, object correlationState)
{
    var tracking = (ITrackingInformation)correlationState;
    
    // tracking entries header
    var trackingEntriesHeader = TrackingEntriesHeader.ReadHeader(reply.Headers);
    if (trackingEntriesHeader != null)
        tracking.IncomingHeaders.TrackingEntries.AddRange(trackingEntriesHeader.TrackingEntries);
    
    // add receive information
    tracking.IncomingHeaders.TrackingEntries.Add(new TrackingEntry(_thisClient, "Received Reply from " + _calledService));
}

That’s it.

Let recap that in context: The application developer has put a service behavior on his service. This has lead to a respective contract behavior on the client. And with what we just provided, the two of them are working together at runtime to create a protocol of calls at runtime.

The final topic we have to address is making the information available to the developer.

 

That’s all for now folks,
AJ.NET

January 18, 2015

WCF Policy – Part 6: Implementation Basics

Filed under: .NET, .NET Framework, C#, SOA, Software Architecture, Software Development, WCF — ajdotnet @ 12:37 pm

We’ve come pretty far, but we haven’t done anything worthwhile yet.

As a reminder: Our tracking policy is pretty simple: Client and server should keep track of sending and receiving messages, and accumulate that information along a request/reply call as part of the SOAP call. In the end this should create a timing protocol of the complete call.

So far we’ve got the design part covered: The server announces the policy, the client recognizes it. The next major aspect is actually doing something. In this post I’m going to provide some basics we are going to need further on. Classes to maintain the tracking information, as well as SOAP related helpers.

For a single tracking entry:

public class TrackingEntry
{
    public DateTime TimeStamp { get; private set; }
    public string Source { get; private set; }
    public string Reason { get; private set; }
    […]
}

TrackingHeaders combines the information going to the SOAP headers of one message, in our case a collection of tracking entries:

public class TrackingHeaders
{
    public List<TrackingEntry> TrackingEntries { get; private set; }
    […]
}

Since we have incoming and outgoing information, an interface abstracts the two of them, complemented with a respective class:

public interface ITrackingInformation
{
    TrackingHeaders IncomingHeaders { get; }
    TrackingHeaders OutgoingHeaders { get; }
}

internal class TrackingInformation : ITrackingInformation
{
    public TrackingHeaders IncomingHeaders { get; private set; }
    public TrackingHeaders OutgoingHeaders { get; private set; }
    […]
}

In case you are wondering about this setup: It’s modeled after the MessageHeaders class containing the headers natively supported by the WCF, and the way they are made available in the Message class.

We are going to include the information in the SOAP message as SOAP header – we do not want it to interfere with the actual contract and content – thus we need a MessageHeader class that deals with serialization/deserialization. Unfortunately the class supports only serialization of data based on data contracts, which in turn do not support XML attributes. Therefore, if more efficient XML is desired, one needs to take serialization into his own hands. Writing the header can be done by overriding the respective method:

internal class TrackingEntriesHeader : BaseMessageHeader
{
    public IEnumerable<TrackingEntry> TrackingEntries { get; private set; }
    
    protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion)
    {
        foreach (var entry in TrackingEntries)
        {
            writer.WriteStartElement(NamespacePrefix, "Entry", Namespace);
            writer.WriteAttributeString("Source", entry.Source);
            writer.WriteAttributeString("TimeStamp", entry.TimeStamp.ToString("o"));
            writer.WriteAttributeString("Reason", entry.Reason);
            writer.WriteEndElement();
        }
    }
    […]
}

Reading the header includes looking it up, requesting a reader and actually reading it:

public static TrackingEntriesHeader ReadHeader(MessageHeaders headers)
{
    return (TrackingEntriesHeader)ReadHeader(headers, Defines.HeaderElementTrackingEntries, Defines.HeaderNamespace, ReadHeaderContents);
}

protected static TrackingEntriesHeader ReadHeader(MessageHeaders headers, string name, string ns, Func<XmlDictionaryReader, BaseMessageHeader> readHeaderContents)
{
    int headerIndex = headers.FindHeader(name, ns);
    if (headerIndex < 0)
        return null;
    
    // Get an XmlDictionaryReader to read the header content
    var reader = headers.GetReaderAtHeader(headerIndex);
    var header = readHeaderContents(reader);
    
    // NOTE: We must(!) remove ("consume") the header if MustUnderstand=1,
    // otherwise it will be considered "not understood" and an exception will be thrown.
    headers.RemoveAt(headerIndex);
    
    return header;
}

static BaseMessageHeader ReadHeaderContents(XmlDictionaryReader reader)
{
    reader.ReadStartElement(Defines.HeaderElementTrackingEntries, Defines.HeaderNamespace); // skip …
    var entries = new List<TrackingEntry>();
    while ((reader.LocalName == "Entry") && (reader.NamespaceURI == Defines.HeaderNamespace))
    {
        var entry = ReadEntry(reader);
        entries.Add(entry);
        
        reader.Read();
        if (reader.NodeType == XmlNodeType.EndElement)
            reader.ReadEndElement();
    }
    return new TrackingEntriesHeader(entries);
}

static TrackingEntry ReadEntry(XmlDictionaryReader reader)
{
    var source = reader.GetAttribute("Source");
    var timeStamp = reader.GetAttribute("TimeStamp");
    var message = reader.GetAttribute("Reason");
    var ts = DateTime.ParseExact(timeStamp, "o", null, DateTimeStyles.RoundtripKind);
    return new TrackingEntry(source, message, ts);
}

In case you’re wondering: Some of these methods reside in a separate base class, which I omitted to simplify things a bit; it will be included in the sample code, though. 

Now we have the bits and pieces we are going to need. In the next posts we’ll start using them to actually implement the policy.

 

That’s all for now folks,
AJ.NET

January 15, 2015

WCF Policy – Part 5: Addendum: Policy Support in WCF

Another addendum before we move on…

As MSDN states in regard to WS-Policy 1.2 and 1.5:

“WCF uses the WS-Policy specification together with domain-specific assertions to describe service requirements and capabilities.”

(In case you are wondering: you can choose the policy version for your service using configuration, namely the serviceMetadata element, policyVersion attribute; default is WS-Policy 1.2.)

Regarding WS-PolicyAttachment the claim is:

“WCF implements WS-PolicyAttachment to attach policy expressions at various scopes in Web Services Description Language (WSDL).”

Sounds great, doesn’t it? But if you read carefully, WCF “using” WS-Policy and “implementing” WS-PolicyAttachment to achieve something actually does not imply fully supporting it.

 

The one pitfall I have found is the way policy expressions are identified and referenced. WS-Policy supports two ways to identify policy expressions, either by a Name attribute, or by a wsu:Id attribute (as shown in part 2 of this series). wsu:Id is used to identify policies residing in the same XML document, Name becomes necessary for policies in separate XML documents, for example imported using wsdl:import. The pitfall I mentioned: WCF does not support policies in separate XML documents, i.e. policy references using the Name attribute.

Now, as long as you are working within WCF on both client and server, this will never be an issues. However if your policy is provided by a Java Metro service, there is a choice, as documented here. Example 19.1 works fine with WCF clients, examples 19.2 and following are not supported. Other technologies may provide similar options, or – even worse – be limited to the Name attribute.

It’s not as if Microsoft doesn’t know the standards, they explained it quite well in “Understanding Web Services Policy”, chapter 2.8, “Referencing Policy Expressions”. They also know about the issue. Unfortunately they are not going to do something about it:

“At this point of time WCF only supports policies included in the same WSDL file and identified via the wsu:ID attribute.
Unfortunately, we are not seeing large customer demand supporting policies residing in secondary WSDL documents, so I will be resolving this bug as "Wont Fix".”

Sic!

Having had to support both, .NET and Java, I ended up writing a little command line application, that downloads and patches the WSDL of services using the Name attribute…

 

That’s all for now folks,
AJ.NET

December 14, 2014

WCF Policy – Part 4: Addendum: Creating the Client Proxy via Command-Line

Filed under: .NET Framework, SOA, Software Development, .NET, C#, Software Architecture, Design Time, WCF — ajdotnet @ 12:52 pm

A minor addendum to the last post

Last time I described the client proxy generation as it happens from within Visual Studio (“Add service reference…”). For those who want to use the command line tool svcutil.exe, there are a few things to keep in mind:

  • It is not sufficient, to provide the app.config via the /config parameter. This configuration file is only for output; to provide a configuration file as input you need to pass it in via the /svcutilConfig parameter.
  • Additionally the assembly containing the import extension has to be found by svcutil.exe. This works automatically if the assembly resides in the GAC. In other cases the assembly has to be provided using the /reference parameter.
  • Lastly the namespace for the generated code needs to be provided as it is not automatically inferred by the tool. This involves a somewhat awkward syntax…

All together results in a command line similar to this (line feeds for better readability):

svcutil
    /config:app.config
    /svcutilConfig:app.config
    /reference:TrackingPolicy.ServiceModel.dll
    /namespace:*,TrackingPolicy.TestClient.TestService
    http://localhost:33333/Services/TestService.svc?singleWsdl

Best put in in a batch file, you don’t wan to retype that every time…

That’s all for now folks,
AJ.NET

December 7, 2014

WCF Policy – Part 3: Evaluating the Policy on the Client

The last part placed our policy assertion in the WSDL:

On the client the WCF evaluates policy assertions during proxy generation, for code and configuration. If you try to import a WSDL containing a policy assertion, the WCF does not know – as is the case with our policy assertion so far – the generated configuration will contain the following warning:

To provide respective import logic the WCF provides an interface IPolicyImportExtension. While this is conceptually similar to what is provided for the export, there is one difference: It is not placed on a binding. In fact, it would not make sense to put it on a binding, as the binding configuration configuration does not yet exist; rather it is part of what is going to be generated during the import. That is why the interface has to be implemented by an arbitrary class, which has then to be announced in the configuration:

During import the WSDL will call respective extensions for all policies it finds. Our job is to check whether the we know the policy assertion. If so, we need to remove it, to prevent the above warning from showing up. Within IPolicyImportExtension.ImportPolicy and it with its parameter of type PolicyConversionContext, this is just one line of code to satisfy the WCF and get rid of the warning:

Now we need to do something with our policy assertion. For our tracking policy I want to place a contract behavior on the generated contract, similar to the service behavior on the server side. This is supported by yet another interface, namely IServiceContractGenerationExtension, and again, on behaviors. So we provide a respective behavior and let our importer add that behavior for the contract. Just one additional line of code:

Still during proxy generation, but some time after our importer has done its job, the WCF will call IServiceContractGenerationExtension.GenerateContract on our behavior. At this time the actual contract interface will have already been created using CodeDOM, so we can party on it and manipulate it as we like. In our case add a contract behavior attribute:

All other methods of the behavior are simply empty. Of course we also need to provide the TrackingContractBehaviorAttribute, also – for the time being – with empty methods.

Note: Strictly speaking, we could use the behavior class. But I want to emphasis the fact that the behavior used to manipulate the code is only present during proxy generation, while the one we just added as attribute is present at runtime.

Running the import again will remove the warning in the configuration. And it will also create a contract amended with our attribute:

In case the policy contains more complex parameters, there is more work to do – analyzing the XML from the policy assertion, generating code with parameters – but the general principle stays the same.

This completes the design time aspects of our policy. The following image depicts the process on server and client (i.e what we covered this post and the last) in overview:

First order of the day fulfilled. The service announces the policy in the WSDL for everyone to take notice and act accordingly. The client proxy generation can be taught to evaluate the policy assertion. What’s important: The bridge between server and client is the WSDL and WS-Policy – common standards, nothing WCF-specific. Similar mechanisms can also be set up on other platforms, e.g. Java with Metro.

The next post will be an addendum, before we take care about the runtime aspects. After all, our implementation doesn’t do anything worthwhile yet.

 

That’s all for now folks,
AJ.NET

November 29, 2014

WCF Policy – Part 2: Advertising the Policy

Filed under: .NET, C#, SOA, Software Architecture, Software Development, WCF — ajdotnet @ 12:40 pm

The last post provided the introduction about what “policy” in the context of WCF is about. Now we are going to go ahead and actually build our own policy.

Note: This post is part of a series. The TOC can be found here

Defining the policy

For this endeavor we keep the actual functionality simple: During a service call, client and server are to add timestamps whenever a message goes out or comes in. Those timestamps shall be maintained in a list that is forwarded with each message, doing so as SOAP header, since this is not part of the regular contracts. This will create a trace of the whole request/response chain. (“Chain” may sound a little presumptuous, but if one service calls others, this might become more of a challenge.) We’ll call this (a little snobbish) “tracking policy”.

Configuring the policy

The first step of the implementation is relatively unspectacular. Since we want to influence the behavior of the service, we need some kind of WCF behavior. I chose a service behavior, other demands may call for a different behavior type. The canonical implementation for a respective attribute looks like this…

… with all the method bodies empty. This is sufficient to be put on a service:

For details on behaviors (including extension elements to be used in configuration rather than code) see here.

Publishing the policy

Now for the first interesting part: How do we insert a policy assertion for our policy into the WSDL? WCF supports writing policy assertions via IPolicyExportExtension, however only for binding elements, not for behaviors. Of course we could provide a respective binding element and ask the developer to configure it – on top of the behavior that he already put on his service. Not exactly comfortable and a source of errors.

There is an alternative, though: Our behavior can add the binding element during the IServiceBehavior.Validate call, as shown here:

(This depends on the employment of a custom binding. I will address the question of other bindings in a later post.)

Now, IServiceBehavior.Validate is obviously not intended for this kind of manipulations, but what the heck, it works, and it makes things easier for the application developer.

Whenever the WSDL is generated, the binding elements implementing IPolicyExportExtension will be asked to insert their policy assertion. IPolicyExportExtension.ExportPolicy will be called and the parameter of type PolicyConversionContext provides the plumbing we need. The policy assertion itself is nothing more than an arbitrary XML fragment – the identifying part is an XML element – which we can create on the fly:

With this code in place, the WSDL should include the XML we just generated. Perhaps in combination with other policy assertions, depending on how the service is configured, but similar to this:

In our case we only needed the existence of the XML element to publish the policy. More complex policies may need to publish additional information. In this case all you need to do is to include XML attributes and/or elements as you like as children of the root element of the policy assertion. WS-Security Policy goes even further and provides several different policy assertions.

That concludes the server perspective for our policy assertion. The next post will look at it from the client perspective.

That’s all for now folks,
AJ.NET

November 23, 2014

Building Your Own Policy with WCF

Filed under: .NET, .NET Framework, C#, SOA, Software Architecture, Software Development, WCF — ajdotnet @ 2:55 pm

Flexibility and extensibility of WCF is really great. You need a feature provided by the platform? Just switch it on, via code or configuration, and all the bits and pieces follow suit. The fact is advertised in the WSDL; the client proxy generation will pick that up and produce respective code and configuration; both, client and server, do their part to make it work at runtime; and last not least the developer usually gets the means to access or manipulate the respective information, should the need arise.

Wouldn’t it be nice to have the same apply to your custom demands, demands not covered by the platform? Demands like…

  • New versions of standards you need to support, but which are not supported by the platform yet.
  • Homegrown authentication schemes.
  • Tenants for multi-tenant solutions.
  • Billing information for services in B2C scenarios.
  • SLA and diagnostics information for operations

Whatever the reason, it would be very nice if we could implement our custom policy in a way that the application developer could use it in a way very similar to policies provided by the platform.

The good news is: It is actually possible to support custom demands in a way very similar to the built-in features of WCF.
The not-so-good news: It is not that simple or straight-forward to do, as there a a lot of bits and pieces working together – and no single information source putting them together. Well, this is what I’m trying to accomplish…

So, here’s the agenda for this little adventure:

Design time aspects:

Runtime aspects:

Looking back:

  • Part 11: Famous Last Words…

Quite a bit more than one post…

So stay tuned…

That’s all for now folks,
AJ.NET

August 14, 2011

RIA with Silverlight–The Business Perspective

If you read this, chances are that you are a developer and that you like Silverlight. And why not? Exciting platform, great features, outstanding tooling. But! If you’re a corporate developer, have you sold it to your management yet? If not, this post is for you.

Silverlight is for RIA, and the domain of RIA applications is largely intranet or closed/controlled extranet user groups. This again is what is usually found in larger enterprise companies. Companies that usually have a vested interest in controlling their environment. And in terms of bringing software into production and of operations and maintenance afterwards, every new platform is one platform to many.

So, the odd developer comes along and talks about this great new technology. Does the management care? Probably not. What does it care about? Simple. Money! Money, as in costs for deployment and user support, hardware and licenses to get the stuff up and running, operations and developer training, maintenance. And money as in savings in the respective areas and – the cornerstone, as the business usually pays the bill – impact on the business. All usually subsumed under the term ROI.

About a year ago, I finished an analysis looking into RIA with Silverlight, conducted for a major customer. Not from the point of view of the developer, but that of business people, operations, and IT management:

So, let’s look briefly at each aspect…

User/Business perspective…

The business doesn’t exactly care for the platform Silverlight itself; it cares for its business benefits. Benefits as in improved user experience, streamlined business workflows, office integration, and so on. And since we had some lighthouse projects with Silverlight we were able to collect some customers’ voices:

“This [streamlining with Silverlight] would reduce a […] business process […] from ~10 min to less than a minute.”

“Advanced user experience of Silverlight UI helps raising acceptance of new CRM system in business units”

“I was very impressed of the prototype implementation […] with Silverlight 3. Having analyzed the benefits of this technology I came to the conclusion that I want the […] development team to start using Silverlight as soon as possible. […]”

This is also confirmed by the typical research companies, like Gartner or Forrester:

“Firms that measure the business impact of their RIAs say that rich applications meet or exceed their goals” (Forrester)

Operations perspective…

In production, the benefit of Silverlight applications (compared with respective conventional web based applications) is reduced server and network utilization.

For example, we had a (small but none-trivial) reference application at our disposal, which was implemented in ASP.NET as well as Silverlight (as part of an analysis to check the feasibility of Silverlight for LOB applications). We measured a particular use case with both implementations – starting the application and going through 10 steps, including navigation, searches, and selections. Both applications were used after a warm-up phase, meaning that the .xap file, as well as images and other static files had already been cached.

The particular numbers don’t matter, what matters is the difference between the amount of data that has been exchanged for each step (in case of navigations none at all for Silverlight). For the single steps:

And accumulated over time:

A ratio of roughly a tenth of the network utilization is quite some achievement – considering that the Silverlight application wasn’t even optimized to use local session state and caching, it should be even higher.

This should have a direct impact on the number of machines you need in your web farm. Add the fact that session state management on the client drastically reduces the demand for ASP.NET session state – usually realized with a SQL Server (Cluster) – there is yet another entry on the savings list.

On the down side is the deployment of the Silverlight plugin. For managed clients – especially if outsourcing the infrastructure comes into play – this may very well become a showstopper.

IT Management perspective…

With respect to development and maintenance, what IT Management should care about includes things like ability to deliver the business demands, development productivity, bug rates in production, costs for developer training, and so on.

Actually all areas in which Silverlight can shine, compared with other RIA technologies, and with the typical mix of web technologies as well:

  • Rich, consistent, homogenous platform
    • .NET Framework (client and server), Visual Studio, Debugger, C#
    • Reduced technology mix, less technology gaps, less broad skill demands
  • Improved code correctness and quality…
    • compiler checks, unit testing, code coverage, debugging, static code analysis, in-source-documentation, …
  • Improved architecture and code
    • Clean concepts, coding patterns, clear separation of client code, lead to better architectures
    • Powerful abstractions lead to less code (up to 50% in one project), less complexity, less errors

Customers’ voices in this area:

“between our desktop app and the website, we estimate 50% re-use of code”

“a .NET developer can pretty much be dropped into a SL project. […] This is a huge deal […]”

“As alternative for Silverlight we considered Flash. […] only Silverlight could provide a consistent development platform (.NET/C#). […]”

 

Conclusion…

Taking all this together, and considering that enterprise companies usually have the tooling and test environments (well…) readily available, this all adds up to something like the following bill:

RIA Return on Invest

Whether the bill looks the same for your company or for one particular project, of course, depends on many things. Especially nowadays with all the hubbub around HTML5 and mobile applications (without any relevant Silverlight support). But if RIA is what you need, the Silverlight will quite often yield far more benefits than any other option.

Still, you need to do your own evaluation. However, I hope to have given you some hints on what you might focus on, if you want to sell technology to the people who make platform decisions in your company.

The actual analysis was fairly detailed and customer specific. But we also prepared a neutralized/anonymized version, which we just made available for download (pdf). (Also directly at SDX.)

That’s all for now folks,
AJ.NET

kick it on DotNetKicks.com

Older Posts »

The Shocking Blue Green Theme. Create a free website or blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 244 other followers