Best Practices for Implementing Server-less RESTful Services

Introduction

With advancements in cloud technology, managed services are not only an option, they are becoming the standard. A managed services means little or no maintenance for you. Most of these services scale dynamically as demand increases and there are few fixed fees. Instead, you pay for usage.

This is a three part article which will walk you through how to create a server-less RESTful service starting with the architecture and methodology, then walking through how to create the business layer to apply rules and get data from the database, and finally, the connection through the web to tie it all together.

For this article, I will be referencing the Amazon AWS platform but the architecture and methodology is applicable to any cloud network including Azure. For a cross reference between the names between the two technologies, you can reference this page: https://azure.microsoft.com/en-us/campaigns/azure-vs-aws/mapping/

Note: Since this document is meant to be agnostic to the cloud technology, it will not go into the details on how to setup or configure your Amazon AWS applications. There are quite a few blogs describing this process. For information about setting up Lamdba, go to the AWS Lambda site located here: https://aws.amazon.com/lambda. For information about setting up Java to work with Amazon, look at the Java Development Center. The Java Development Center is located here: https://aws.amazon.com/java/


Principles

RESTful Principles

The key principles of REST involve separating your API into logical resources. These resources are manipulated using HTTP requests where the method (GET, POST, PUT, PATCH, DELETE) has specific meaning.

When generating your resource, it is important to remember the method is your verb so the resource should be a noun that makes sense from the perspective of the API consumer. Although your internal models may map neatly to resources, it isn’t necessarily a one-to-one mapping. The key here is to not leak irrelevant implementation details out to your API.

Once you have your resources defined, you need to identify what actions apply to them and how those would map to your API. RESTful principles provide strategies to handle CRUD actions using HTTP methods mapped as follows:

With the recent release of Amazon API Gateway, developers can now create custom RESTful APIs that trigger AWS Lambda functions, allowing for truly server-less back ends that include built-in authorization, traffic management, monitoring, and analytics.

GET /cats – Retrieves a list of cats

GET /cats/5 – Retrieves a specific cat

POST /cats – Creates a new cat

PUT /cats/5 – Updates cat #5 (including references)

PATCH /cats/5 – Partially updates cat #5 (only the cat record)

DELETE /cats/5 – Deletes cat #5

You will notice that I used plural endpoint names here to keep it simple and not having to deal with odd pluralization (person/people, goose/geese) makes the life of the API consumer better and is easier for the API provider to implement (as most modern frameworks will natively handle /cats and /cats/5 under a common controller).

If a relation can only exist within another resource, RESTful principles provide useful guidance. A cat consists of a number of paws. These paws can be logically mapped to the /cats endpoint as follows:

GET /cats/5/paws – Retrieves list of paws for cat #5

GET /cats/5/paws/2 – Retrieves paw #2 for cat #5

POST /cats/5/paws – Creates a new paw in cat #5

PUT /cats/5/paws/2 – Updates paw #2 for cat #5

PATCH /cats/5/paws/2 – Partially updates paw #2 for cat #5

DELETE /cats/5/paws/2 – Deletes paw #2 for cat #5

If a relation can exist independently of the resource, it makes sense to just include an identifier for it within the output representation of the resource. The API consumer would then have to hit the relation’s endpoint. However, if the relation is commonly requested alongside the resource, the API offers functionality (via an attribute to include child records) to automatically embed the relation’s representation and avoid multiple hits to the API.

Security Principles

SSL

Simply put, always use SSL with no exceptions. Today, your web APIs can get accessed from anywhere there is internet (like libraries, coffee shops, airports among others). Not all of these are secure. Many don’t encrypt communications at all, allowing for easy eavesdropping or impersonation if authentication credentials are hijacked.

Another advantage of always using SSL is that guaranteed encrypted communications simplifies authentication efforts – you can get away with simple access tokens instead of having to sign each API request.

Architecture

Versioning

Always version your API. Versioning helps you iterate faster and prevents invalid requests from hitting updated endpoints. It also helps smooth over any major API version transitions as you can continue to offer old API versions for a period of time.

There are mixed opinions around whether an API version should be included in the URL or in a header. Academically speaking, it should probably be in a header. However, the version needs to be in the URL to ensure browser explorability of the resources across versions.

An API is never going to be completely stable. Change is inevitable. What’s important is how that change is managed. Well documented and announced multi-month depreciation schedules can be an acceptable practice for many APIs. It comes down to what is reasonable given the industry and possible consumers of the API.

Result filtering, sorting & searching

It’s best to keep the base resource URLs as lean as possible. Complex result filters, sorting requirements and advanced searching (when restricted to a single type of resource) can all be easily implemented as query parameters on top of the base URL. Let’s look at these in more detail:

Filtering

Use a unique query parameter for each field that implements filtering. For example, when requesting a list of cats from the /cats endpoint, you may want to limit these to only those in the open state. This could be accomplished with a request like GET /cats?state=open. Here, state is a query parameter that implements a filter.

Sorting

Similar to filtering, a generic parameter sort can be used to describe sorting rules. Accommodate complex sorting requirements by letting the sort parameter take in list of comma separated fields, each with a possible unary negative to imply descending sort order. Let’s look at some examples:

GET /cats?sort=-birthdate – Retrieves a list of cats in descending order of birth date

GET /cats?sort=-birthdate,birthplace – Retrieves a list of cats in descending order of birth date and within a specific birth date, the birth place in order

Searching

Sometimes basic filters aren’t enough and you need the power of full text search. Perhaps you’re already using ElasticSearch or another Lucene based search technology. When full text search is used as a mechanism of retrieving resource instances for a specific type of resource, it can be exposed on the API as a query parameter on the resource’s endpoint. Let’s say q. Search queries should be passed straight to the search engine and API output should be in the same format as a normal list result.

Combining these together, we can build queries like:

GET /cats?sort=-lastUpdateDate – Retrieve recently updated cats

GET /cats?state=vaccinated&sort=-lastUpdateDate – Retrieve recently vaccinated cats

GET /cats?q=sick&state=unvaccinated&sort=-lastUpdateDate Retrieve the list of cats that are unvaccinated that mentioning the word ‘sick’

Note: If you do support these advanced features, ensure that you support the basics too. You want to allow developers flexibility without requiring them to know everything about your API.

Aliases for common queries

To make the API experience more pleasant for the average consumer, consider packaging up sets of conditions into easily accessible RESTful paths. For example, the recently closed cats query above could be packaged up as GET /cats/vaccinated

Limiting which fields are returned by the API

The API consumer doesn’t always need the full representation of a resource. The ability select and chose returned fields goes a long way in letting the API consumer minimize network traffic and speed up their own usage of the API.

Use a fields query parameter that takes a comma separated list of fields to include. For example, the following request would retrieve just enough information to display a sorted listing of vaccinated cats:

GET /cats?fields=id,name,birthdate,lastUpdateDate &state=vaccinated&sort=-lastUpdateDate

Updates and inserts should return a resource representation which would include any server generated fields such as id, create date, modified date, etc.

JSON only responses

It’s time to support JSON only and leave XML behind in APIs. It’s verbose, make the output much larger, it’s hard to parse, it’s hard to read, its data model isn’t compatible with how most programming languages model data and its extendibility advantages are irrelevant when your output representation’s primary needs are serialization from an internal representation.

snake_case vs camelCase for field names

If you’re using JSON (JavaScript Object Notation) as your primary representation format, the "right" thing to do is to follow JavaScript naming conventions – and that means camelCase for field names! If you then go the route of building client libraries in various languages, it’s best to use idiomatic naming conventions in them – camelCase for C# & Java, snake_case for python & ruby.

Many popular JSON APIs use snake_case. I suspect this is due to serialization libraries following naming conventions of the underlying language they are using. Perhaps we need to have JSON serialization libraries handle naming convention transformations.

JSON encoded POST, PUT & PATCH bodies

If you’re following the approach in this post, then you’ve embraced JSON for all API output. Let’s consider JSON for API input.

Many APIs use URL encoding in their API request bodies. URL encoding is exactly what it sounds like – request bodies where key value pairs are encoded using the same conventions as one would use to encode data in URL query parameters. This is simple, widely supported and gets the job done.

However, URL encoding has a few issues that make it problematic. It has no concept of data types. This forces the API to parse integers and booleans out of strings. Furthermore, it has no real concept of hierarchical structure. Although there are some conventions that can build some structure out of key value pairs (like appending [ ] to a key to represent an array), this is no comparison to the native hierarchical structure of JSON.

If the API is simple, URL encoding may suffice. However, complex APIs should stick to JSON for their API input. Either way, pick one and be consistent throughout the API.

An API that accepts JSON encoded POST, PUT & PATCH requests should also require the Content-Type header be set to application/json or throw a 415 Unsupported Media Type HTTP status code.

Pagination

Envelope loving APIs typically include pagination data in the envelope itself. And I don’t blame them – until recently, there weren’t many better options. The right way to include pagination details today is using the Link header introduced by RFC 5988.

An API that uses the Link header can return a set of ready-made links so the API consumer doesn’t have to construct links themselves. This is especially important when pagination is cursor based. Here is an example of a Link header used properly, grabbed from GitHub’s documentation:

https://api.github.com/user/repos?page=3&per_page=100&rel=next

But this isn’t a complete solution as many APIs do like to return the additional pagination information, like a count of the total number of available results. An API that requires sending a count can use a custom HTTP header like X-Total-Count.

Auto loading related resource representations

There are many cases where an API consumer needs to load data related to (or referenced) from the resource being requested. Rather than requiring the consumer to hit the API repeatedly for this information, there would be a significant efficiency gain from allowing related data to be returned and loaded alongside the original resource on demand.

However, as this does go against some RESTful principles, we can minimize our deviation by only doing so based on an embed (or expand) query parameter.

In this case, embed would be a comma separated list of fields to be embedded. Dot-notation could be used to refer to sub-fields. For example:

GET /cats/12?embed=breeds.name,immunizations.*

This would return a ticket with additional details embedded, like:

 


  "id": 12,
  "name": "Bella",
  "birthdate": "1/31/2015",
  "breeds": {
    "name": "Calico"
  },
  "immunizations": {
    "id": 42,
    "name": "Rabies",
  }
}

 

Of course, ability to implement something like this really depends on internal complexity. This kind of embedding can easily result in an N+1 select issue.

Overriding the HTTP method

Some HTTP clients can only work with simple GET and POST requests. To increase accessibility to these limited clients, the API needs a way to override the HTTP method. Although there aren’t any hard standards here, the popular convention is to accept a request header X-HTTP-Method-Override with a string value containing one of PUT, PATCH or DELETE.

Note that the override header should only be accepted on POST requests. GET requests should never change data on the server!

Rate limiting

To prevent abuse, it is standard practice to add some sort of rate limiting to an API. RFC 6585 introduced a HTTP status code 429 Too Many Requests to accommodate this.

However, it can be very useful to notify the consumer of their limits before they actually hit it. This is an area that currently lacks standards but has a number of popular conventions using HTTP response headers.

At a minimum, include the following headers (using Twitter’s naming conventions as headers typically don’t have mid-word capitalization):

X-Rate-Limit-Limit – The number of allowed requests in the current period

X-Rate-Limit-Remaining – The number of remaining requests in the current period

X-Rate-Limit-Reset – The number of seconds left in the current period

Why is number of seconds left being used instead of a time stamp for X-Rate-Limit-Reset?

Authentication

A RESTful API should be stateless. This means that request authentication should not depend on cookies or sessions. Instead, each request should come with some sort authentication credentials.

By always using SSL, the authentication credentials can be simplified to a randomly generated access token that is delivered in the user name field of HTTP Basic Auth. The great thing about this is that it’s completely browser explorable – the browser will just popup a prompt asking for credentials if it receives a 401 Unauthorized status code from the server.

However, this token-over-basic-auth method of authentication is only acceptable in cases where it’s practical to have the user copy a token from an administration interface to the API consumer environment. In cases where this isn’t possible, OAuth 2 should be used to provide secure token transfer to a third party. OAuth 2 uses Bearer tokens & also depends on SSL for its underlying transport encryption.

An API that needs to support JSONP will need a third method of authentication, as JSONP requests cannot send HTTP Basic Auth credentials or Bearer tokens. In this case, a special query parameter access_token can be used. Note: there is an inherent security issue in using a query parameter for the token as most web servers store query parameters in server logs.

For what it’s worth, all three methods above are just ways to transport the token across the API boundary. The actual underlying token itself could be identical.

Caching

HTTP provides a built-in caching framework! All you have to do is include some additional outbound response headers and do a little validation when you receive some inbound request headers.

There are 2 approaches: ETag and Last-Modified

ETag: When generating a request, include a HTTP header ETag containing a hash or checksum of the representation. This value should change whenever the output representation changes. Now, if an inbound HTTP requests contains a If-None-Match header with a matching ETag value, the API should return a 304 Not Modified status code instead of the output representation of the resource.

Last-Modified: This basically works like to ETag, except that it uses timestamps. The response header Last-Modified contains a timestamp in RFC 1123 format which is validated against If-Modified-Since. Note that the HTTP spec has had 3 different acceptable date formats and the server should be prepared to accept any one of them.

Errors

Just like an HTML error page shows a useful error message to a visitor, an API should provide a useful error message in a known consumable format. The representation of an error should be no different than the representation of any resource, just with its own set of fields.

The API should always return sensible HTTP status codes. API errors typically break down into 2 types: 400 series status codes for client issues & 500 series status codes for server issues. At a minimum, the API should standardize that all 400 series errors come with consumable JSON error representation. If possible (i.e. if load balancers & reverse proxies can create custom error bodies), this should extend to 500 series status codes.

A JSON error body should provide a few things for the developer – a useful error message, a unique error code (that can be looked up for more details in the docs) and possibly a detailed description. JSON output representation for something like this would look like:

 

{
  "token": "00F316BC-9E43-4D9E-9333-713BDCE21E4D",
  "versionNumber": 1.0,
  "lastRecord": 25,
  "responseCode": 500,
  "responseMessage": "Unable to connect to database."
}

 

Validation errors for PUT, PATCH and POST requests will need a field breakdown. This is best modeled by using a fixed top-level error code for validation failures and providing the detailed errors in an additional errors field.

HTTP status codes

HTTP defines a bunch of meaningful status codes that can be returned from your API. These can be leveraged to help the API consumers route their responses accordingly. I’ve curated a short list of the ones that you definitely should be using:

200 OK – Response to a successful GET, PUT, PATCH or DELETE. Can also be used for a POST that doesn’t result in a creation.

201 Created – Response to a POST that results in a creation. Should be combined with a Location header pointing to the location of the new resource

204 No Content – Response to a successful request that won’t be returning a body (like a DELETE request)

304 Not Modified – Used when HTTP caching headers are in play

400 Bad Request – The request is malformed, such as if the body does not parse

401 Unauthorized – When no or invalid authentication details are provided. Also useful to trigger an auth popup if the API is used from a browser

403 Forbidden – When authentication succeeded but authenticated user doesn’t have access to the resource

404 Not Found – When a non-existent resource is requested

405 Method Not Allowed – When an HTTP method is being requested that isn’t allowed for the authenticated user

410 Gone – Indicates that the resource at this end point is no longer available. Useful as a blanket response for old API versions

415 Unsupported Media Type – If incorrect content type was provided as part of the request

422 Unprocessable Entity – Used for validation errors

429 Too Many Requests – When a request is rejected due to rate limiting

In the next release, we will go into a walk through on how to develop the business and data access layers for your RESTful service.

Dark Matter Software

http://darkmattersoftware.co/DarkMatterLogo.jpg

Posted in Amazon AWS, Amazon RDS, API Gateway, Best Practices, Cloud, Java 8, Lambda, RESTful Services | Tagged , , , | Leave a comment

Source Code & PowerPoint from Seminar

I have the source code and the PowerPoint that I used during my seminar.  You can download it from my main blog site:

http://blogs.windowsclient.net/airborneengineer/archive/2009/10/08/source-amp-powerpoint-from-seminar.aspx

Posted in Uncategorized | Leave a comment

Using Silverlight & WCF Seminar

I have a confirmed date and place for my next lecture.  I will be presenting a seminar on using Silverlight and WCF.  This will tutorial rather than just the technologies capabilities. 

October 6th at 6:00 PM (food & drinks are served starting @ 5:00). 

Location:

SpringHill Suites by Marriott
2437 Metrocentre Blvd.
West Palm Beach, FL 33407

Hope to see you there.

Posted in Uncategorized | Leave a comment

WPF Styles and Templates – Part II (ComboBox Customization)

This is the second part of my article on customizing controls in WPF. If you have not read the first part and are not familiar with Styles you may want to read part I http://windowsclient.net/blogs/airborneengineer/archive/2009/06/09/wpf-styles-and-templates-part-i.aspx . In this article we will focus on ComboBoxes. We make a ComboBox that is capable of displaying an Image and Text and also show how binding works when storing classes in ComboBoxes.

For the complete article:

http://blogs.windowsclient.net/airborneengineer/archive/2009/06/25/wpf-styles-and-templates-part-ii-combobox-customization.aspx

Posted in Uncategorized | Leave a comment

WPF Styles and Templates – Part I

I originally started out with the intention on describing how to make an image or image and text display in a ComboBox.  As I started writing the article, I realized that instead of making one massive article describing what needs to be done, I would break it down is to functional areas.  – Now, even blogs need to have design documents.  🙂

Read the rest of the article on my blog here: 

http://blogs.windowsclient.net/airborneengineer/default.aspx

Posted in C#, Silverlight, WPF | Tagged , , | Leave a comment

WPF Using WinForms – Wrong Approach

Background

It has been quite a while since I have been excited about something new is software development that made me want to spend my off hours playing around with it.  When WPF first came out I did not even give it a look.  I figured it was another one of Microsoft’s attempts to reinvent something.

I was mainly a middleware developer and wrote WinForms applications to access the middle tier.  I really hated ASP.Net so when I took a contract which required ASP.Net, I was looking around for alternatives and that is when I found Silverlight.  What I liked about Silverlight is it allowed me to create all of the cool functionality that Flash has without having to learn something complete different.  Silverlight was laid out in the same format as the rest of the Microsoft libraries so it just made sense how to wire things up and get up and running.  During my course of learning and playing with Silverlight I found references to WPF and how basic WPF xaml could be used for Silverlight.  I picked up WPF and haven’t looked back.  It does take some time to get used to, when I first started, if I needed to make a quick test harness I used WinForms but now I use WPF for everything.  It takes some time to hit the epiphany where it just all comes into place and makes sense.  When it does, it is really a pleasure to code.

During the last year, I have been given or should I say have had two projects dropped in my lap that were written in WPF (and I use that phrase liberally).  I think the more accurate description is the application was written in WinForms with a xaml front end.  Both applications had one thing in common, they either could not get into QA or could not get out of QA due to performance issues or random exception faults.  After having to basically re-write both applications I made some notes on some of the mistakes I saw in the code with the hope that it will help others who are new to WPF from making the same mistakes.

User Controls

When using WinForms, the common approach to have controls have the same look and feel or common functionality is to use user controls.  Though you certainly can do this in WPF, user controls mainly used to encapsulate behavior or group controls together for a specific purpose.  You also have custom controls which basically allows you to build a control from the ground up.  For a good article on user controls vs. custom controls read more here: http://wangmo.wordpress.com/2007/09/28/user-controls-vs-custom-controls/

So if you want to customize the OK and Cancel buttons in your application to have an image with text next to it, instead of creating a user control library which defines this functionality, a style can more easily be defined.  (Style abbreviated for size)

    <Style x:Key=”ImageButtonStyle” BasedOn=”{StaticResource {x:Type Button}}” TargetType=”{x:Type Button}”>
        <Setter Property=”HorizontalContentAlignment” Value=”Center”/>
        <Setter Property=”VerticalContentAlignment” Value=”Center”/>
        <Setter Property=”Template”>
            <Setter.Value>
                <ControlTemplate TargetType=”{x:Type Button}”>
                        <StackPanel>
                            <Image Source=”{Binding RelativeSource={RelativeSource Self}, Path=DataContext}” Stretch=”Fill” Width=”45″ Height=”45″ />

                            <ContentPresenter HorizontalAlignment=”{TemplateBinding HorizontalContentAlignment}” Margin=”{TemplateBinding Padding}” VerticalAlignment=”{TemplateBinding VerticalContentAlignment}” SnapsToDevicePixels=”{TemplateBinding SnapsToDevicePixels}” RecognizesAccessKey=”True”/>
                        </StackPanel>
                    <ControlTemplate.Triggers>
                        <Trigger Property=”IsEnabled” Value=”false”>
                            <Setter Property=”Foreground” Value=”{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}”/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

This style can then be applied to a button as shown here:

<Button Style=”{StaticResource ImageButtonStyle}”     DataContext=”/WpfApplication1;component/Close.png” Name=”CloseButton”>Close</Button>

The other advantage to using styles is the ability to change all object types to a particular style.  For example if you have a common library that is used in multiple applications, you can define the controls to be generic (no specific colors, size, etc.) and allow each of the applications to change the color and size to it’s own specifications.  To tell WPF to make the style apply to all controls, simply change the style declaration to use the type as the key as shown here:

<Style x:Key=”{x:Type Button}” TargetType=”Button”>

For the control, you do not need to specify any style, it will use the one defined in you dictionary as the default.

Binding

Binding can be one of the more difficult concepts to grasp because of its flexibility.  There are several good posts on binding including http://msdn.microsoft.com/en-us/magazine/cc163299.aspx  Here are a couple of the mistakes that I have seen:

In the first example, the idea is to load an xml file with state codes and descriptions for a combo box.  The user creates a dataset, reads all of the codes and then assigns the result to the combo box.  

DataSet ds = new DataSet();
XElement statesElement = XElement.Load(“/Data/StateCodes.xml”);
ds.ReadXml(statesElement.CreateReader());
cboState.DataContext = ds.Tables[0];
cboState.DisplayMemberPath = Settings.Default.StateMemberPath;

If you use the XmlDataProvider, you can bind the source to the provider as shown here:

<XmlDataProvider x:Key=”StateData” Source=”/Data/StateCodes.xml” XPath=”//State” />

<ComboBox ItemsSource=”{Binding Source={StaticResource StateData}}”
          DisplayMemberPath=”@id” Name=”cboState” />

In the second example, there are two controls that work together.  Some examples would be using a label to display the value of a scrollbar or making two controls have the same width.  Here is an example of how you bind two controls together:

<Slider Name=”sliderScale” Orientation=”Horizontal” Value=”1.0″ />

<Label Content=”{Binding ElementName=sliderScale, Path=Value, Mode=Default}”/>

If you have types that are not compatible (e.g. a string to update a double) you will need to use a Converter.  This goes beyond the scope of this posting.

Resources

Resources can be stored internally or externally to the application.  If have a resource such as an image which will remain static, the resource can be compiled into the application and referenced in that manner.  Here is example of improperly referencing a static image:

imageBackground.Source = LoadBitmap(“/Images/GpsConnected.png”);

BitmapImage LoadBitmap(string path)
{
    byte[] bytes = File.ReadAllBytes(path);
    MemoryStream memoryStream = new MemoryStream(bytes);
    BitmapImage image = new BitmapImage();
    image.CacheOption = BitmapCacheOption.OnLoad;
    image.BeginInit();
    image.StreamSource = memoryStream;
    image.EndInit();
    bytes = null;

    return image;
}

The following code does the same thing:

imageBackground.Source = new BitmapImage(new Uri(GetBitmapFileName(“/eSketch;component/Images/GpsConnected.png”)));

Callbacks

The final piece that I will touch on is callbacks.  Though I have not tracked down the exact instances or cause, I have found that using in the following manner results in unpredictable exceptions.  It will sometimes cause the application to hang for no apparent reason.  The worst part about it is that it is not consistent.

delegate void SetTextCallback(string Text);
private void WriteLongitude(string Text)
{
    if (txtGpsLongitude.Dispatcher.Thread != Thread.CurrentThread)
    {
        SetTextCallback callBack = new SetTextCallback(WriteLongitude);
        Dispatcher.Invoke(DispatcherPriority.Send, callBack, Text);
    }
    else
    {
        txtGpsLongitude.Text = Text;
    }
}

As a result, I recommend using this method:

private void WriteLongitude(string text)
{
    Dispatcher.Invoke(DispatcherPriority.Send,
                        new Action(() =>
                        {
                            txtGpsLongitude.Text = text;
                        }));
}

Summary

With the flexibility that WPF provides, it can be difficult to get started and you can make more work for yourself.  My intent was to provide some pointers to help you from making more work for yourself. 

In the future I will provide some more guidance including how to extent functionality such as comboboxes.  Feedback is always appreciated.

Posted in C#, WPF | Leave a comment

WPF in South Florida

I have been working with WPF for about a year and a half now.  I really enjoy the flexibility that it provides but it does have quite a learning curve when you have been working with WinForms for most of your programming career.

In the past 7 months, I have been given two different WPF applications which were started by other developers but could not get the application to QA or get it out of QA.  Digging into the code, it was pretty easy to see why they were having issues.  They were writing WinForms code with a Xaml front end.  This can have some rather strange and unpredictable behavior.  I decided that I would take some of these issues and create a blog to help out others who are attempting to make the transition to WPF.

This is my first attempt at a blog and comments and advice are always appreciated.  If you have specific questions or topics that you would like to see covered, feel free to contact me. 

Posted in C#, Silverlight, WPF | Tagged , , , | Leave a comment