Welcome to MSDN Blogs Sign in | Join | Help

Mocking the Console

I’ve posted an update to the Microsoft.Activities.Simulation library.  Today at the team meeting I showed the library to the Windows Workflow team and Ed Pinto said “That is cool!” so I must be doing something right.

Today’s update is a better TestConsole.  This time I’ve had the TestConsole redirect the Console output stream by calling Console.SetOut.  Now the stream will go into a StringWriter backed by a StringBuilder as the buffer.

   1: StringBuilder _buffer;
   2:  
   3: public TestConsole()
   4: {
   5:     StringWriter outWriter = new StringWriter(_buffer);
   6:     Console.SetOut(outWriter);
   7: }

This way anything that writes to the console will now be captured and therefore it will become testable.

When I want to verify that something was written to the console there are two ways I can do it.  I can access the StringBuilder by calling TestConsole.Buffer.ToString() and then look for something in the string.

Or if I prefer a line oriented approach I can do something like this test.

   1: Assert.AreEqual("Scope 1 Number is 1", results.Console.Lines[0]);

Here I have a SimulationResults type with a TestConsole member named Console.  I can access a string[] named Lines that will return each line from the TestConsole buffer by calling Regex.Split

   1: public string[] Lines
   2: {
   3:     get
   4:     {
   5:         // Split it only if we need to
   6:         if (Buffer.Length != _lastBufferSplit)
   7:         {
   8:             _lastBufferSplit = Buffer.Length;
   9:             _lines = Regex.Split(Buffer.ToString(), Environment.NewLine);
  10:         }
  11:  
  12:         return _lines;
  13:     }
  14: }

Since splitting the buffer is a little work, I only split it if the length of the buffer has changed since the last time I split it.  One side effect of using Regex.Split is that you always get an empty last line.  Since the CancellationScope Activity Sample also uses this library I put the library in place and found that I had to update all the unit tests that relied on a line count.  If they asserted the count should be 2 I had to change it to 3. 

I’ m not enough of a Regex guru to know how to work around this.  For now I think it is ok to just say that you will always get one empty line at the end of the array and that is just the way it is.

If you are interested in the Microsoft.Activities.Simulation library, let me know by posting some discussion threads

Posted by ronjacobs | 1 Comments

How to test WF4 Workflows with Microsoft.Activities.Simulation

Recently I posted a new sample for the CancellationScope activity.  Of course, I’m building these samples on .NET 4 Beta 1.  But the team is already making rapid progress towards the next major milestone.  They are checking in changes that may or may not break my sample applications and hands on labs.  How will I know if things are broken?

Most people rely on manual testing to detect broken code.  The problem is that manual testing is time consuming and expensive.  I wanted to find a way to unit and acceptance test the sample applications and labs.  There are significant challenges to this but I’ve got some ideas that I think will work and I’m going to describe them to you on my blog as I get them in place.

Unit Testing A Workflow

I’ve covered this on my blog in the past.  In fact, the WF4 Hands On Labs (Lab 1) from the Visual Studio 2010 training kit includes unit testing.  One issue I did not cover was how to use a Test Double with workflow.  Why would you do this?  Because some activities do things that are not testable or desirable in a unit test.

  • The WriteLine activity writes text to the console
  • A Send activity sends a message to an endpoint that might not be available when testing
  • A Receive activity requires a message to cause the workflow to continue.

One response to things like this is to use Dependency Injection with Inversion of Control containers to replace these troublesome components with something more testable.  The Microsoft patterns & practices group has produced the Unity container for this very purpose.

These solutions do not work with workflow activities because they rely on having some measure of control over the creation of dependencies so they can resolve them at runtime. 

Microsoft.Activities.Simulation

I found a way to get around this specifically for workflow.  I’m using the term “Simulation” to describe it because in the long run I believe we can build something that would be useful to technical business users for testing workflows.  To understand how it works consider the CancellationScope activity sample.  If I want to test this sample, how would I do it?

The sample writes data to a console window to show how the cancellation scope allows you to execute activities that will be triggered when a workflow element is cancelled.  It uses the System.Activities.Statements.WriteLine activity to do this.  So what I need is a way to verify that the correct messages are output by WriteLine in the correct order.  What I really wanted to do was to replace WriteLine with another activity I call MockWriteLine.

The strategy I use is to modify the XAML for testing.  Consider the following XAML snippet.

   1: <p:CancellationScope DisplayName="Cancellation Scope 1">
   2:     <p:CancellationScope.CancelHandler>
   3:       <p:WriteLine DisplayName="WriteLine Cancel Scope 1">["Cancelling scope 1..."]</p:WriteLine>
   4:     </p:CancellationScope.CancelHandler>

Here  you can see the solution staring you in the face.  If you could just change <p:WriteLine to <p:MockWriteLine and made the MockWriteLine activity have the same properties as WriteLine then you can do whatever you want from MockWriteLine to make the workflow testable.

Great, but what should MockWriteLine do?  I want to capture what it would have written to the console.  I need to get data from this activity without modifying the workflow more than I already have.  The solution is to use the Test Spy pattern with a workflow extension.

I created a class called TestConsole that will store up the WriteLine output in a buffer that I can verify later.  I can then add this extension to the workflow instance.

   1: WorkflowInstance workflowInstance = new WorkflowInstance(wfElement, inputs);
   2: TestConsole testConsole = new TestConsole();
   3:  
   4: // Add the testConsole to the extensions collection
   5: workflowInstance.Extensions.Add(testConsole);
   6:  
   7: // Run the test...
   8: RunTheTest();
   9:  
  10: // Check the first line of the buffer
  11: Assert.AreEqual("Some text to verify", testConsole.Buffer.ElementAt(0));
There is much more to say about this but I’m running out of time.  To see it in action, check out the updated version of the CancellationScope Activity Sample.
Posted by ronjacobs | 1 Comments

CancellationScope Activity

Last Edit: 2-Jun-2009

How do you cancel work in your application?  Many middle tier components and services rely on transactions to handle cancellation for them.  This makes a great deal of sense because transactional programming is well understood.  However there are many times when you must cancel work that cannot be done under a transaction.  Cancellation can be very difficult because you have to track work that has been done to know how to cancel it.  WF4 also includes compensation activities that can be used to do clean up work as well.

Windows Workflow Foundation 4 helps you with this by providing a CancellationScope activity. 

Cancellation Scope 1

In today’s example I’m going to show you how you can use a cancellation scope to manage cleanup work.

How does cancellation happen?

Before we consider how the CancellationScope, let’s think about how cancellation happens in a workflow.  There are 2 ways it can happen, from inside of a workflow or from the outside.  Child workflow activities are scheduled by their parent activity (such as a Sequence, Parallel, Flowchart or some custom activity).  The parent activity can decide to cancel child activities for any reason.  For example, a Parallel activity with three child branches will cancel the remaining child branches whenever it completes a branch and the  CompletionCondition expression evaluates to true.

The workflow can also be cancelled from the outside by the host application by calling the Cancel method on the WorkflowInstance.

How does the cancellation scope work?

It’s very simple really, the cancellation scope has a Body.  This is where you do the work that you might have to cancel later.  The CancelHandler contains the activities you want to run if the activity is canceled. 

Does an unhandled exception cause the cancellation handler to be invoked?

No it does not.  Unhandled exceptions cause the workflow to abort, cancellation handlers are not invoked.

What if my cancellation handler throws an unhandled exception?

If you have an unhandled exception in the cancellation handler the workflow will immediately terminate with the exception.  This is similar to throwing an exception from within a catch block.

Show me a sample

I created some sample code for this blog post that cancels the workflow from the outside.  In this example you can observe the behavior of nested cancellation.

When it starts you enter a number between 1 and 3 to determine the number of nested levels you want to call.  When you get to the limit of that level the workflow will call a custom activity I created call GoIdle that simply sets a bookmark.  This will cause the workflow to become idle and the WorkflowInstance.OnIdle handler will be invoked handing control back to the host.

In program.cs I’ve created two AutoResetEvents, one that will be signaled when the workflow goes idle and another that will be signaled when the workflow completes or terminates with an exception.  This is a little unusual but I know that my workflow will go idle when it matches one of the nesting levels 1,2 or 3.

Try It Out

Download the sample code from here.  (This sample requires Visual Studio 2010 / .NET 4 Beta 1)

  1. Explore the sample, check out program.cs and Sequence1.xaml
  2. Press Ctrl+F5 to compile and run the sample
  3. When it prompts you for a level try level 1 or 2.  You will see that cancellation happens in reverse order of invocation (level 2 cancels before level 1).
  4. To see what happens when you have an unhandled exception thrown in the cancel handler, try level 3.

CancelCmd

Posted by ronjacobs | 1 Comments

Ready to learn WF/WCF 4?

Tomorrow Visual Studio 2010 and .NET 4 beta 1 will be available for everyone to download.  I’ve been keeping quiet about the work I’ve been up to for the last month and a half while we got some great resources ready for you.

Ok – I let some of this out on endpoint.tv already but now you can get hands on with the technology and learn it yourself.

Download the WF / WCF 4 Hands On Labs

Introduction to Workflow 4

In this lab you will get to know the basics of creating, hosting and running a workflow. This lab is also intended to be an introduction to the new workflow authoring constructs in the .NET Framework 4 and Visual Studio 2010, including the new Workflow Designer, expressions, variables and arguments. Additionally, you will explore the use of some basic built-in activities.

Introduction to Workflow Services using .NET Framework 4

This hands-on lab is intended to introduce developers to writing workflow services using .NET Framework 4. You will examine the different messaging activities of Windows Workflow, and learn how to configure them to create a distributed application. This lab is built around a specific HR business scenario where candidates submit their applications and are hired or rejected based on an evaluation process.

Workflow Designer Programming Model

This hands-on lab introduces you to the designer programming model of Windows Workflow 4. You will learn how to rehost the workflow designer in a WPF desktop application and how to create composite custom designers for your workflow activities.

Creating Flowchart Workflows

This lab is intended to be an introduction to the Flowchart paradigm used in Workflow development. In this lab you will learn how to create Flowchart Workflows using the designer, and you will also learn the usage of several of the provided activities and how to create custom activities easily.

Monitoring Workflow Services using .NET Framework 4

During the life cycle of an application, developers and system administrators often need to monitor running services in order to perform health checks or troubleshoot issues. The Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) runtimes already come with a built-in tracking infrastructure, making it easy to enable monitoring within your WCF and WF applications. In this hands-on lab you will learn how you can leverage some of the main WF and WCF monitoring features to track application execution and troubleshoot problems with services when necessary.

WCF Service Discovery using .NET Framework 4

Windows Communication Foundation 4 includes a new feature that enables service discovery. Service discovery allows you to locate services on the same subnet using ad hoc discovery, or using a proxy to establish connections with servers regardless of where they are. In this lab you will create a simple chat application that will use both methods to learn about available services.
Posted by ronjacobs | 3 Comments

Configuring a VPC for the REST Starter Kit Hands On Labs

Today I was given a VPC image that someone had started and asked to put the WCF REST Starter Kit Hands On Labs on the image so we can use it at Tech-Ed.

I ran into some interesting problems and I thought I would share the solutions with you in case you run into the same thing.

Problem #1 SQL Server Name

The REST Starter Kit labs assume that the SQL Server is “.\SQLExpress”.  Normally this works pretty well since Visual Studio installs this instance.  However the image I was working with did not have this server present.  They had uninstalled it (since it was SQL Server 2005) and replaced it with a SQL Server 2008 install at (local).

I had two choices now.  I could go through all the labs and docs and change the connection strings or… I could use a SQL Alias.  If you have never used these, they are way cool.  SQL Server allows you to create an alias for a server and that is just what I did.

sqlalias

Now I can refer to the server as (local) or as “.\SQLExpress” which means I don’t have to change any scripts, docs or connection strings.

Problem #2 Default.htm is blank

Every now and then I run into something I had never seen before.  When I opened Lab 2, I right clicked on default.htm and selected “View in browser” which promptly launched IE and displayed an empty page.  I thought that perhaps I had accidentally deleted the content of the page so I opened it in Visual Studio and the HTML was there and displaying properly in the VS Design Mode editor.

I launched the site in the debugger and refreshed IE several times… no luck.  I did View Source and saw that an empty HTML was being returned.  Now I was really confused.  Then I realized that the IIS7 installation allows you to pick and choose features.  Once of those features is “Static Content”.  I’ve always selected this option and didn’t know what would happen if I didn’t.  Sure enough, this option was not enabled.  I had to go into Server Manager (on Windows Server 2008) and enable the feature.  No big deal but this sure threw me for a minute.

IISStatic

Problem #3 Network Service login to SQL Server

Now that I have the web page showing, I test and get a security exception.  The Network Service account doesn’t have permission to open the database.  I’m sure that everybody has run into this a dozen times, I know that every now and then I have to fix up a server like this but it seems like I can never remember the exact way to do it.  Fortunately my friends in the patterns & practices team have published a great “How to” document on this called How To: Use the Network Service Account to Access Resources in ASP.NET.  This document tells me exactly how to grant access.

 

And now everything is working great for the people who are going to be at Tech-Ed North America 2009.

Posted by ronjacobs | 2 Comments

Installing Microsoft URL Rewrite Module on Windows 7 Beta

Recently I said that the IIS 7 URL rewrite module will not work on Windows 7.  Someone commented on my blog post that there is a workaround posted on the iis.net site.  I know the IIS team says this works but I’ve tried it on multiple machines and it never works for me.  I have not tried it on Windows Server  2008 R2 so perhaps it works there.

Posted by ronjacobs | 2 Comments

Today on endpoint.tv – The REST Collection Template

20090325endpointLab3_large_ch9[1] 

One of the more interesting (challenging?) things we did with the WCF REST Starter Kit is the REST Collection Service Template.  The idea behind this template was to produce a service that allows you read/write access to a service using a simple REST style interface.  The idea is to provide both a contract and base class that takes care of most of the REST-“isms” and you simply override the methods to support your business logic.

And how does this template help?

  • Provides the URI templates for your service based on a very simple model of a resource per service with an ID parameter
  • Supports content negotiation with a query string parameter i.e. “?format=json”
  • Supports HTTP status codes such as 201 – “Created” when you add a new item or 404 – Not Found when you try to update or delete an item that does not exist
  • Supports append to the collection via POST

What do you think?

One of the reasons we are putting this out to the community in a Codeplex release is that we want to get your constructive feedback.   Here is a good starting point.  Answer this question

What is wrong with this template?

I’m not tying to sound defensive, I just want to know what you really think.

We know that it isn’t perfect, but if you don’t like it, what do you not like about it?  How can we improve it?

The best way to answer these questions is to give it a test drive by running through Lab 3 from the WCF REST Starter Kit Hands On Labs so download and give it a go.  You can help us make it better.

Posted by ronjacobs | 3 Comments

RESTful Services and Business Exceptions

Last week I had the privilege of speaking at MIX09.  My session RESTful Services for the Programmable Web with Windows Communication Foundation is already available for online viewing (pretty cool how fast they turned that around).  This morning I got an email from Francois who saw the session on the web and he had an excellent question.

“I just wanted to know how you deal with business exceptions (concurrency, invalid state transitions, ...) when an update or delete is performed. Do you simply return HTTP error codes? How do you do the equivalent of returning a Soap Fault?”

Great question, to answer it let me first lay some foundation then consider the second part of your question with regard to SOAP faults and finally use some examples to hopefully make this more clear.

REST and HTTP Status Codes

One of the key values of REST is that you are using a universal API known as HTTP.  Because of this you must try to understand the way that HTTP wants you to deal with this.  And how does HTTP want me to deal with this issue?  By using an HTTP Status code.

The first line of an HTTP response is the status line – HTTP clients look to this line to understand the outcome of their request.  It isn’t just a matter of errors, there are many different response codes you could return or encounter when invoking RESTful services.    (For more information on the Status-Line see the HTTP spec, section 6.1)

       Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF

The status code comes from a long list of codes, according to the spec, the list of codes is extensible but you should follow the model based on the categories of errors

      - 1xx: Informational - Request received, continuing process
      - 2xx: Success - The action was successfully received,
        understood, and accepted
      - 3xx: Redirection - Further action must be taken in order to
        complete the request
      - 4xx: Client Error - The request contains bad syntax or cannot
        be fulfilled
      - 5xx: Server Error - The server failed to fulfill an apparently
        valid request

Even so, I would not go about creating custom HTTP status codes.  Instead I would try to use the commonly used status codes listed in section 10 of the HTTP spec.

REST equivalent of SOAP faults

The designers of SOAP had exceptions in mind when they created SOAP faults.  Previous distributed computing environments (DCOM, CORBA etc.) did not have a model for propagating exceptions across boundaries.  SOAP came along 10+ years after these technologies a time during which exceptions became accepted as a better way of dealing with errors.  Many SOAP stacks (WCF being the prime example) will catch an exception, turn it into a SOAP fault and pass it along to the client side which will unpack the message and throw an exception on the client side.

SOAP faults are different than HTTP status codes because they are always errors and there is no taxonomy of errors, just whatever you want them to be.  In other words, the “error protocol” is application specific.

In REST HTTP status codes are common and they are not always errors.  However the errors do fall into 2 categories 4XX (Client) and 5XX server errors.   Now let’s consider some common scenarios where you must deal with errors and status codes.

Error Scenarios

The first class of errors you must consider are (4XX) client request errors.  Generally it means that the server rejected the request for some reason.

Get or Update record that does not exist

Client does an HTTP GET for a resource ID that does not exist in the database.  On the server you might call into the data layer to update a record an get a KeyNotFoundException (like I did in the video).  What happens if you do nothing?  Well WCF will catch all unhandled exceptions and return a status code of 500 - “Internal Server Error”.  This is not what you want, because it implies that the problem is a server problem. 

In this case you should return a HTTP status code of 400 404 “Not Found”  (edit – 3/25 – thanks Clemens!)

10.4.1 400 Bad Request

The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.

Here is some code that processes a GET request by looking it up in a dictionary.  This is the fixed version of what I showed in the video.  As you can see I’m converting an exception into a status code by throwing a WebProtocolException.

[OperationContract]
[WebGet(UriTemplate = "/{id}")]
SessionData GetSession(string id)
{
    try
    {
        return _sessions[id];
    }
    catch (KeyNotFoundException)
    {
        throw new WebProtocolException(
            HttpStatusCode.NotFound);
    }
}

Add a resource with missing or invalid data

Client does an HTTP POST with missing or invalid data in the request body.  The server attempts to validate the request and rejects it because of the invalid or missing data.  The HTTP status code should be 400 – Bad request

Server Processing Errors

Suppose that the request is valid, the resource exists and for whatever reason (concurrency or some other processing error) the server cannot complete the request.  Then what?

10.5 Server Error 5xx

Response status codes beginning with the digit "5" indicate cases in which the server is aware that it has erred or is incapable of performing the request. Except when responding to a HEAD request, the server SHOULD include an entity containing an explanation of the error situation, and whether it is a temporary or permanent condition. User agents SHOULD display any included entity to the user. These response codes are applicable to any request method.

You should return a HTTP status code of 500 along with some text to let the user know what is happening (if you want to).  Here is an example of code that would do this kind of processing. 

[OperationContract]
[WebInvoke(Method = "PUT", UriTemplate = "/{id}")]
SessionData UpdateSession(string id, SessionData updatedSession)
{
    try
    {
        if (!_sessions.Contains(updatedSession.ID))
            throw new WebProtocolException(HttpStatusCode.BadRequest);
        if (!_sessions.IsValidSession(updatedSession))
            throw new WebProtocolException(HttpStatusCode.BadRequest);
        return _sessions.Update(updatedSession);
    }
    catch (TimeoutException)
    {
        throw new WebProtocolException(HttpStatusCode.InternalServerError,"Update session timeout",null);
    }
}

WebProtocolException does provide mechanisms for passing more detail in a SOAP Fault like way as a part of the HTTP response body.  Sounds like a good topic for my next post.

Posted by ronjacobs | 3 Comments

WCF REST Starter Kit Preview 2, Windows 7 and the IIS 7 URL Rewrite Module

Someone was asking on the WCF REST Starter Kit Forum if the WCF REST Starter Kit Preview 2 release works with Windows 7.  My first reaction was to say yes!

Then I remembered an issue I had when developing the hands on labs.  Lab 2 – Addressability uses the IIS7 URL rewrite module.  This module when installed does a number of things and one of them is to install an ASP.NET hotfix.  Currently the hotfix setup fails because Windows 7 is missing some part of .NET 3.5 SP1 that it requires.  Some people on the web have found ways to trick the installer into getting past this, I tried the tricks and though the installer completed, the URL rewrite module still didn’t work so I don’t recommend trying this.

For now, run through lab 2 using Vista or Windows Server 2008.  You will notice the screenshots in the lab came from Windows Server 2008.  Ultimately the URL Rewrite install problem will be fixed as Windows 7 gets closer to RC.  I installed the latest build on Friday and I tried installing it again just now and I can tell you that the problem still exists.

Posted by ronjacobs | 1 Comments

WCF REST Starter Kit Preview 2 Is Here

Last night we posted the WCF REST Starter Kit Preview 2 release.  This release features an all new client side library that is just fantastic.  My part in this was to create the WCF REST Starter Kit Hands On Labs – these  labs are a great way to quickly get up to speed on RESTFul development with WCF.

Lab 1 – Hello REST

If you don’t know anything about REST, this simple lab is for you. It will help you to build a SOAP service and convert it into a REST service quickly and simply.

Lab 2 – Addressability

As you advance in building RESTful services you will want to control the URI that is used to address the service. In this lab you will learn the techniques for making the URI into just what you want it to be.

Lab 3 – REST Collection

In this lab you will begin with the REST Collection template from the starter kit and build a read/write collection service testing it along the way with the Fiddler HTTP Debugging proxy

Lab 4 – Consuming RESTFul Services

In this lab you will consume the RESTful service you built in Lab 3 using the new HttpClient class in the REST Starter Kit

Posted by ronjacobs | 2 Comments

REST Starter Kit, ServiceBehavior and Thread safety

If you have seen the REST Starter Kit (Preview 1) perhaps you noticed a TODO comment about the ServiceBehavior attribute.  We decided to make this comment a little more explicit in Preview 2.

 

/// TODO: Modify the service behavior settings (instancing, concurrency etc) based on the service's requirements. 
/// Use ConcurrencyMode.Multiple if your service implementation is thread-safe.
/// TODO: NOTE: Please set IncludeExceptionDetailInFaults to false in production environments
[ServiceBehavior(IncludeExceptionDetailInFaults = true, 
    InstanceContextMode = InstanceContextMode.Single, 
    ConcurrencyMode = ConcurrencyMode.Single)]

 

What does this ServiceBehavior attribute do?  It controls the runtime behavior of the service.   Let’s examine what each of the settings mean.

IncludeExceptionDetailsInFaults

This value controls how WCF will respond to unhandled exceptions.  When in development it is helpful to have this value set to true so that the client application can see what errors the server is throwing.  Typically for production systems you turn this off.

InstanceContextMode

This value controls how WCF will create new objects to service clients.  The important thing to notice here is that the default setting for services in the WCF Starter Kit template is InstanceContextMode.Single.  This means you will have only one instance of your service class created by WCF to service all clients.

ConcurrencyMode

This value controls how WCF will dispatch calls to your service.  The default value for the starter kit is ConcurrencyMode.Single.  This means that your service will process only 1 request at a time on the 1 service object created by WCF.

What do the default values give me?

With these values you have a singleton.  One instance of your service class that can process 1 request at a time.  This means that you can write code that is not thread safe and you will be fine, but the scalability of your service will be limited.

What values should I use?

If you can write your class so that it is thread safe, set the concurrency mode to ConcurrencyMode.Multiple.  This means that though you have only once instance of your service, multiple threads will call into it allowing your service to be more scalable.

How should I design my service class to be thread safe?

Your service class should be a pretty thin layer, a facade that simply forwards calls to a business logic or data layer.  You want to avoid the use of shared state in your service class as you process requests.

What state is shared?

This depends on the InstanceContextMode value. 

InstanceContextMode.Single

When it is set to Single then you have only one service instance created.  Any fields or properties declared at the class level will be shared among all instances.  This is ok if those objects are thread safe, if they are not you will have to do something to make the code thread safe.

Static members are shared as well and they will have to be synchronized if they are not thread safe.

InstanceContextMode.PerSession / PerCall

Because the RESTful services do not support sessions either of these settings will result in PerCall behavior.  This means that every request to your service will have a new object created to handle the call.  In this case member fields or properties will not be shared but static members will be and must be synchronized.

This makes my head hurt, just tell me what should I do

Design your service so that it and the business logic it calls is stateless.  Treating each call as a separate task and not sharing state between calls. 

For example, a typical service will do something like this

protected override WineData OnGetItem(string id)
{
    Int32 wineID;
    if (!Int32.TryParse(id, out wineID))
    {
        throw new WebProtocolException(HttpStatusCode.BadRequest);
    }
    return CohoDB.WineGateway.GetWine(wineID);
}

Is this code thread safe?  What you see here is, but the CohoDB.WineGateway.GetWine method may or may not be so you have to look at what it does.

public WineData GetWine(int wineID)
{
    using (CohoDBEntities context = new CohoDBEntities())
    {
        return (WineData)context.Wines.
            Include("Accolades").
            Include("WineTypes").
            FirstOrDefault((w) => w.WineID == wineID);
    }
}

This simple class uses the ADO.NET Entity Framework to create a context and get the WineData.  Each request to GetWine will create a new context so it is thread safe.

Because my code is thread safe I can change the ServiceBehavior for my service.

[ServiceBehavior(
// Still in development - I want exception details    
IncludeExceptionDetailInFaults = true,
// Only create one instance of the service class - it has no state to protect
InstanceContextMode = InstanceContextMode.Single,
// Process requests from multiple threads on the shared instance 
// the data layer is thread safe
ConcurrencyMode = ConcurrencyMode.Multiple        
)]

If this is so great, why does the starter kit default to being a Singleton?

Because the sample code included in the template uses shared state.  It services requests from a Dictionary and there is no locking to synchronize access to the shared state.

Be Careful about Momentum

I found that many developers ignore things in the code that they don’t understand.  I’ve been guilty of this myself.  You assume that the default setting must be the best possible setting and because you are busy and don’t have the time to think it through you deploy your app into production with the setting included in the code from the template.

With RESTful services based on this template, the end result of this will be a safe but not very scalable implementation.  My advice to you is that you carefully consider the thread safety of your code all the way down the call stack.  Avoid sharing state across calls and set the concurrency mode to Multiple if you can be sure that you are thread safe for a more scalable service.

Posted by ronjacobs | 4 Comments

Today on endpoint.tv: What is “Dublin” and why should I care?

With the many new technologies that are coming your way in 2009 you have probably heard a lot of code names.  If you are like me, you have thought to yourself… What is “<insert code name here>”?  Or more importantly… Why should I care about “<code name>”?

Well if you develop web services, there is a new technology coming your way that is something you should care about.  It is code named “Dublin”.

Today we feature Dan Eshner (Product Unit Manager) and Ford McKinstry (Group Program Manager) explaining “Dublin” and the reasons why they are building it.

endpoint.tv - "Dublin" what is it and why should I care?

Posted by ronjacobs | 1 Comments

Partial Trust, System.ServiceModel.Activation.WebServiceHostFactory and ASP.NET Development Server

Recently I was doing some testing in partial trust scenarios with RESTful services and I ran into a problem.  If you use the WebServiceHostFactory to create your RESTful service and  you have no System.ServiceModel configuration (which you don’t need – that is why you are using the factory) you will get an exception.

That is the bad news…  The good news is that this scenario works fine with IIS hosting.  The problem occurs only with the ASP.NET Development Server “Cassini”.

Here are the steps to reproduce

  • Create a WCF Service web application
  • Add a reference to System.ServiceModel.Web
  • Delete the IService1.cs file you won’t need it
  • Modify the Service1.svc.cs file
using System.ServiceModel;
using System.ServiceModel.Web;
[ServiceContract]
public class Service1
{
    [OperationContract]
    [WebGet(UriTemplate = "/")]
    public string Test()
    {
        return "This is a test of partial trust";
    }
}
  • Modify the Service1.svc file
<%@ ServiceHost 
Language="C#" 
Debug="true" 
Service="Service1" 
CodeBehind="Service1.svc.cs" 
Factory="System.ServiceModel.Activation.WebServiceHostFactory"%>
  • Modify web.config and delete or comment out the entire <system.serviceModel> section and set the site to use partial trust
    <system.web>
      <!--Set the trust level to medium to see the problem-->
      <trust level="Medium"/>
  • Right click on Service.svc and select view in browser and boom!

Server Error in '/' Application.

Security Exception

Description: The application attempted to perform an operation not allowed by the security policy.  To grant this application the required permission please contact your system administrator or change the application's trust level in the configuration file.
Exception Details: System.Security.SecurityException: Request for the permission of type 'System.Configuration.ConfigurationPermission, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' failed.
Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[SecurityException: Request for the permission of type 'System.Configuration.ConfigurationPermission, System.Configuration, Version=2.0.0.0,…
   System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet) +0
   System.Security.CodeAccessPermission.Demand() +58
   System.Configuration.BaseConfigurationRecord.CheckPermissionAllowed(String configKey, Boolean requirePermission, Boolean isTrustedWithoutAptca)


Version Information: Microsoft .NET Framework Version:2.0.50727.4900; ASP.NET Version:2.0.50727.4900

Problem

The problem appears to be related to how the ASP.NET Development Server is treating config in partial trust scenarios (update 2/27 – is in how WCF uses the configuration system when running under the ASP.NET Development Server host).  The problem is still being investigated but the good news is that there is a workaround

Workaround

You can work around this issue by using IIS to develop, debug and test the partial trust REST service. 

(update 2/27: One other workaround is to use the <system.serviceModel> configuration section)

Posted by ronjacobs | 1 Comments

Easy REST

In designing software there is a fundamental trade-off between simplicity and power.  Great products have just the right mix of the two.  When it comes to REST the team has been grappling with this balance.  If you have seen the WCF REST Starter Kit then you have seen a feature packed solution for building RESTful services.  However, some people say they want more simplicity.  Today I’m going to show you the easiest way to build a RESTful service.  For the scenario let’s imagine I’m building a website for a conference.  I want the website to provide a REST service that returns one or all conference sessions.

Step 1 – Describe your resource

The resource is just a class that will be serialized to return the data to your callers.  It is typically a very simple class with public properties.

    public class ConferenceSession
    {
        public string ID {get;set;}
        public string Title { get; set; }
    }

Notice this is a very simple class with no attributes, interfaces or base class required.

Step 2 - Create the Information Model

It makes sense to keep this simple. We are going to provide a service that returns one or all conference sessions

URI Method Description
Conference.svc/ GET Returns all sessions
Conference.svc/{id} GET Returns session {id}

Step 3 – Describe the contract

Since this model is so common, I created a generic contract that you can use over and over again if you use this information model.

using System.ServiceModel;
using System.ServiceModel.Web;
namespace EasyREST
{
    [ServiceContract]
    public interface IEasyREST<T> where T:class
    {
        [OperationContract]
        [WebGet(UriTemplate="/{id}")]
        T GetItem(string id);
        [OperationContract]
        [WebGet(UriTemplate = "/")]
        T[] GetItems();
    }
}

 

Step 4 – Create your service

Now I can create a service for my website.  These are the manual steps, you can create a template that already has most of this done if you want.

  1. Add a reference to System.ServiceModel.Web and System.ServiceModel
  2. Right click and select Add New Item… then choose WCF Service from the list.  Name the service Conference
  3. Visual Studio created an interface for your service called IConference – you won’t need this so delete it
  4. Delete the entire <System.ServiceModel> section from web.config – you won’t need this either
  5. Edit the markup for Conference.svc to add the WebServiceHostFactory.  Right click on Conference.svc and select View Markup and add the highlighted line
<%@ ServiceHost 
Language="C#" 
Debug="true" 
Service="EasyREST.Conference" 
CodeBehind="Conference.svc.cs"
Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>
  1. Edit the service implementation to use the IEasyREST<T>
    public class Conference : IEasyREST<ConferenceSession>
    {
        public ConferenceSession GetItem(string id)
        {
            ConferenceSession session =  ConferenceGateway.GetSession(id);
            if (session == null)
                WebOperationContext.Current.OutgoingResponse.SetStatusAsNotFound();
            return session;
        }
        public ConferenceSession[] GetItems()
        {
            return ConferenceGateway.GetSessions();
        }
    }

Bottom Line

This is a very simple reusable REST solution.  The question is… is this enough?  I suspect for a large number of RESTful services this will provide just what you are looking for.  It’s easy to grasp and easy to use is it not?

I’d be interested in hearing what you think about it.  I’ve added this project to the MSDN Code Gallery at http://code.msdn.microsoft.com/easyrest

Posted by ronjacobs | 8 Comments
More Posts Next page »
 
Page view tracker