Gunnar Peipman's ASP.NET blog

ASP.NET, C#, SharePoint, SQL Server and general software development topics.

Sponsors

News

 
 
 
DZone MVB

Links

Social

August 2010 - Posts

Planning common membership provider for different authentication providers

I am trying to implement form based authentication (FBA) membership provider that is able to support multiple authentication mechanisms. Take it as an self-training experiment. In this posting I will introduce bases of my experiment and introduce my current plans and ideas.

Why membership provider for multiple authentication mechanisms?

There are many people in the world who are users of some social network or some open services provider. Today Facebook and Twitter are very popular social networks. Also Google and Microsoft Live services are very popular although they are not social networks. But all mentioned systems provide their own authentication channels also to other applications. The question is: why should I have another username and password if I have already one at some of systems I mentioned before?

Where is Estonia?Here, in Estonia, we are building local Microsoft community portal with local Microsoft. We analyzed the situation and decided to use Live ID as authentication mechanism in our portal. We were a little it worried too because we were afraid that there are load of users who are not happy with Live ID as authentication mechanism. And guess what – as time has shown us there is no reason to worry! Our ~2000 users (Estonia is small country) are all happy with Live ID and the ones who doesn’t have Live ID yet can go and join Live ID – it’s free.

If you have no idea where I live then take a look at map on right. The small and strong screen splash there is Estonia. If you don’t see it well then feel free to click on this image to see it at original size. :)

Profile store

To give you better idea what I am thinking about take a look at the following diagram.

multi-auth-provider

Every user has one account. Each account has account specific information and custom profile fields. Profile fields can be customized because different sites need different profiles. My profile store will be common enough to live over almost all common situations. Or at least I hope so.

Authentication tokens is the place where I store tokens for users returned by different authentication mechanisms. This way each user is able to use authentication mechanism he or she likes. Also users will be able to use Twitter and Live ID both if they like. Same goes for all the other authentication providers I am able to support.

Implementation details

I have some implementation details on my mind. I am sure that the end result is maybe a little bit different but in big picture things hopefully does not change a lot.

  • There will be one common membership provider that is able to authenticate users to ASP.NET site by querying the authentication tokens table.
  • It is possible that each authentication provider gets it’s own membership provider that is extended from common one. I am not very sure yet if this is the great idea.
  • Usernames will be in form: ProviderName:ProfileName so I am able to detect which authentication mechanism I have to look to find out correct profile.
  • There will be additional field for profile or membership provider that returns me ProfileName without authentication mechanism information.
  • Data will be held in SQL Server at first place. Later I plan to support also the other databases or data stores.
  • There will be common login page that is automatically able to offer authentication mechanisms it knows about.

I think these points are good enough for start.

What’s next?

Well…. as a next thing I try to implement support for different authentication mechanisms and when all common providers are covered then it is time to write generic membership and role providers for ASP.NET. My first four candidates are Twitter, Facebook, Google and Live ID and after these I plan to write providers. Stay tuned, it will be interesting experiment!

Visual Studio: Microsoft should simplify producing quality software

I am looking at features of different versions of Visual Studio and I less and less understand how and why is the quality of software handled as fun of few seasoned professionals. Although Visual Studio is best development platform I have ever seen I really don’t understand why Microsoft hates people who want to provide quality to their customers.

Usually n00bs and start-ups start with minimum versions to get their work done. Many of them start with some version of Visual Studio Express or cheapest one of the full versions. These products have this far caused me hell load of problems because specially n00bs have no way how to control or measure the quality of their work. n00bs make also a lot of stupid mistakes and they need some way to rollback those mistakes. And don’t forget how many other mistakes n00bs can make. Now let’s put it all together and see how hard is for n00bs to get started their professional life on Visual Studio.

  • No advanced debugging – there is IntelliTrace but not for guys who need it at first years almost every day. They have to waste their and their seniors time to get mysteries solved. I need IntelliTrace rarely because usually stack trace of Exception is enough for me. But I have seen n00bs who try to debug their applications using only message part of exceptions. IntelliTrace is only available with Visual Studio Ultimate.
  • No versioning support – SVN, Git and other version controlling systems are must-be in today’s software development. I cannot see this in Express editions of Visual Studio. Guys come from universities and they have no idea how to save their work and how to rollback the changes they don’t really need. Well… if we take Eclipse then it is only matter of minutes to get connected to some version controlling system.
  • No support for database projects – you must be very professional guy if you want to be able to develop your databases as integral part of your project. At least so good that seniors agree to buy you at least Premium license of Visual Studio 2010. On all other versions of Visual Studio 2010 you have to manage your database versions manually. Okay, I have seen what it means specially for younger d00ds who come from schools.
  • No testing support – another must-be thing is integral support for some testing framework. This far I have seen no testing support in Visual Studio Express editions and I still wonder why n00bs on MS platform are forced to produce crap – forced by money and sick marketing politics. If I take Eclipse… well, you can start with tests after couple of minutes. And using some hacks I can make nUnit work with Express Editions too, but is it normal?
  • No code metricscode metrics is also there to help only guys like me who are coding dinosaurs and know without Visual Studio what is the current state of code. N00bs are usually not able to write code like pros and for them measuring code quality daily is mandatory. Code metrics are available starting from Premium Edition of Visual Studio. Well… those who are starting must be wiser than pros to get their job done. Seems like not very normal situation to me. Okay, I solved the problem with NDepend and I am happy with it.
  • No support for profiling – well… same stuff as previous. It is something that also beginners need to do and still they have to find other ways how to do it. Like using some external frameworks, struggling with them and wasting time instead of getting wiser and smarter on mainstream tools.

I don’t think that all these features must me 100% available for “smaller” versions but at least some level these features must be there. It is awful waste of time right now to get n00bs work at Visual Studio if you don’t want to buy a lot of money and still you need external tools to accomplish some team tasks (I have very good CI story to tell that ends with simple question – why TFS when I have working solution for free that takes less time to set up and manage then TFS?).

I think that instead of building another tools like WebMatrix Microsoft should put their focus heavily on quality topics for couple of years and work out all editions of Visual Studio (and other development tools) with software quality as most important goal in their mind.

Book review: Patterns of Enterprise Application Architecture

Patterns of Enterprise Application Architecture  
Patterns of Enterprise Application Architecture
Lately I finished reading the famous patterns book by Martin Fowler - Patterns of Enterprise Application Architecture. This book introduces and describes design patterns you will usually see when building enterprise applications. There are also examples for patterns and although they are simple and primitive they give you the idea how to implement or use specific patterns. If you are working on enterprise applications every day you will find this book very useful and I’m sure you will use it as manual. Yes, you can read this book as any other book and you can also use it as manual. In the end of this review you can find table of patterns with links to short introduction for each pattern.

Are these patterns platform specific somehow? No, they are not. It doesn’t matter what platform or language you are using. Of course, you must know your platform well because some of problems solved in this book maybe also already solved on platform you are working on. Don’t try to push all available patterns to your application – use patterns of this book when you face problems that your tools doesn’t solve or that your tools solve poorly. Of course, you can consult with this book if you are not sure how to implement one or another pattern in your application.

My suggestion is to read this book with two other books (of course, there are more recommended books but let’s make a quick start, okay?):

As the result you have better idea of patterns, domain driven design and how to use them in your .NET projects. Enterprise application patterns and domain driven design are both somehow complex topics and Applying Domain-Driven Design and Patterns gives you some ideas about how to apply this knowledge in practice.

Table of contents

Introduction.
Architecture.
Enterprise Applications.
Kinds of Enterprise Application.
Thinking About Performance.
Patterns.
The Structure of the Patterns.
Limitations of These Patterns.

I. THE NARRATIVES.
1. Layering.
2. Organizing Domain Logic.
3. Mapping to Relational Databases.
4. Web Presentation.
5. Concurrency (by Martin Fowler and David Rice).
6. Session State.
7. Distribution Strategies.
8. Putting it all Together.

II. THE PATTERNS.
9. Domain Logic Patterns.
10. Data Source Architectural Patterns.
11. Object-Relational Behavioral Patterns.
12. Object-Relational Structural Patterns.
13. Object-Relational Metadata Mapping Patterns.
14. Web Presentation Patterns.
15. Distribution Patterns.
16. Offline Concurrency Patterns.
17. Session State Patterns.
18. Base Patterns.

References
Index.

Table of Patterns

Martin Fowler introduces all these patterns also on his homepage. There is special patterns catalogue for that. Patterns here are linked to Martin Fowler’s catalogue.

Managing business object locks on application level

Today I worked out simple application side object locking solution for one server scenario. My motivation came from ASP.NET architecture forum thread How to solve concurrent site issue where one user asks for locking solution that works without changing database. Here is my simple and primitive solution that should help this guy out. I added also sample solution to this posting.

My solution is simple:

  1. Create class for locked items.
  2. Create manager class that holds locks and manages them.
  3. Clear locks when session ends.
  4. Create page to release all locks.

If you need something more serious then you should keep locks information in database or better than that – use some lock server. Also you may consider developing WCF service.

LockItem class

As a first thing let’s create class that keeps lock information. I call this class as LockItem. This class doesn’t hold references to locked objects – only type and ID as there are many business layers that doesn’t use globally unique identifiers for objects.


public class LockItem
{
    public Type ObjectType { get; set; }
    public int ObjectId { get; set; }
    public string SessionId { get; set; }
    public DateTime LockedAt { get; set; }
}

LockItem class also contains property for session because otherwise it is not possible to know what objects session should release. LockedAt property is used to release expired locks.

LockManager

LockManager is the most complex part of this example. It handles all the locking actions and keeps internal locks registry that contains information about locks. Here is the source for LockManager.


public static class LockManager
{
    private static List<LockItem> _lockedItems;
 
    static LockManager()
    {
        _lockedItems = new List<LockItem>();
    }
 
    public static bool IsLocked(BusinessBase obj)
    {
        var locksQuery = from l in _lockedItems
                         where l.ObjectType == obj.GetType()
                               && l.ObjectId == obj.Id
                         select l;
 
        return (locksQuery.Count() > 0);
    }
 
    public static bool Lock(BusinessBase obj, string sessionId)
    {
        if (IsLocked(obj))
            return false;
 
        lock (_lockedItems) 
        {
            var lockItem = new LockItem 
            { 
                ObjectType = obj.GetType(), 
                ObjectId = obj.Id,
                LockedAt = DateTime.Now,
                SessionId = sessionId
            };
 
            _lockedItems.Add(lockItem);
            return true;
        }
    }
 
    public static void ReleaseLock(BusinessBase obj, string sessionId)
    {
        lock (_lockedItems)
        {
            var locksQuery = from l in _lockedItems
                             where obj.GetType() == obj.GetType()
                                   && obj.Id == l.ObjectId
                                   && sessionId == l.SessionId
                             select l;
 
            ReleaseLocks(_lockedItems);
        }
    }
 
    public static void ReleaseSessionLocks(string sessionId)
    {
        lock (_lockedItems)
        {
            var locksQuery = from l in _lockedItems
                             where sessionId == l.SessionId
                             select l;
 
            ReleaseLocks(locksQuery);
        }
    }
 
    public static void ReleaseExpiredLocks()
    {
        lock (_lockedItems)
        {
            var locksQuery = from l in _lockedItems
                             where (DateTime.Now - l.LockedAt)
.TotalMinutes > 20
                             select l;
 
            ReleaseLocks(locksQuery);
        }
    }
 
    public static void ReleaseAllLocks()
    {
        lock (_lockedItems)
        {
            _lockedItems.Clear();
        }
    }
 
    private static void ReleaseLocks(IEnumerable<LockItem> lockItems)
    {
        if (lockItems.Count() == 0)
            return;
 
        foreach (var lockItem in lockItems.ToList())
            _lockedItems.Remove(lockItem);
    }
}

You can write special page to administrator interface that has button for calling ReleaseAllLocks(). It is good idea because at least during development I am sure you are creating many situations where locks are not released due to exceptions.

Release session locks when session ends

When session ends you have to release all locks that this session has. Otherwise those objects will be locked until you restart your web application or call ReleaseLocks method. Although ASP.NET Session_End event is called god knows when and you should not use this method due to this uncertainty I base my example exactly on that event. Copy this method to your Global.asax.ascx file.


protected void Session_End()
{
    LockManager.ReleaseSessionLocks(Session.SessionID);
}

Now we have almost everything in place to start using locks.

Testing locks

I created simple view to test locks. You need two browsers to test if locks work okay. One browser locks the object for 20 seconds and the other gives you messages that object is locked. You have to make this second request with another browser during this 20 seconds when object is locked. Here is the ASP.NET MVC controller action for that purpose.


public ActionResult Index()
{
    Response.Clear();
    Response.ContentType = "text/plain";
 
    var product = new Product { Id = 1, Name = "Heineken", 
Price = 1.2M };
 
    if(!LockManager.Lock(product, Session.SessionID))
    {
        Response.Write("Object has already lock on it!\r\n");
        Response.End();
        return null;
    }
 
    Response.Write("Object successfully locked\r\n");
    Response.Flush();
    Thread.Sleep(20000);
 
    Response.Write("Releasing lock\r\n");
    LockManager.ReleaseLock(product, Session.SessionID);
    Response.Write("Lock released\r\n");
 
    Response.End();
    return null;
}

If you are using old ASP.NET application then paste this code to Page_Load event of your application.

From here …

… you can go on and make your own modifications and customizations to this code. Before going to live with your own locking strategy test it hundred times at least. To make administration easier you can also create page that shows active locks and lets them release one lock at time or by session ID.

Sample solution

Application.Data.Locks.Example.zip Application.Data.Locks.Example.zip
VS2010 | 45KB
ASP.NET MVC meets HTML5

Today I tried out ASP.NET MVC HTML5 Helpers Toolkit by Dean Hume. Although browsers today support HTML5 partially it is time to start playing with it. As soon as HTML5 gets common standard in web you should be able to react fast. In this posting I will introduce you HTML5 Helpers Toolkit and some HTML5 field types.

HTML5 Helpers Toolkit is easy to install. Just download the package, unpack it and reference the DLL you found from package. That’s all. You don’t have to do anything more. If your browser doesn’t support HTML5 then HTML5 fields are rendered as usual textboxes and you can extend them using jQuery by example.

E-mail field

HTML5 defines many types for input boxes. One of the types is e-mail. Here is the demo of e-mail field with placeholder value. Yes, in HTML5 textboxes support placeholders and we don’t have to mess with JavaScript anymore. This is how e-mail box is defined.


<form>
    <%= Html.Html5TextBox("userEmal", InputTypes.InputType.Email,
"plah@plah.com") %>
</form>

And here is the result on Firefox 4 Beta.

HTML5 e-mail box with placeholder value

Nice, isn’t it? I discovered one cool thing when I tested HTML5 Helpers Toolkit with Opera. I tried to submit form where e-mail address is not valid. And this is what happened:

HTML5 date box with validation on Opera

Form was not submitted and all I got was this error message in red box. Cool!

Slider

As a next thing let’s see how to get numeric slider on page without any JavaScript. Numbers in slider box definition have the following meaning: minimum is 1 and maximum is 50, step is 2 and default value is 25.


<form>
    <%= Html.Html5Range(1, 50, 2, 25, null) %>
</form>

And here is the result on Chrome.

HTML5 numeric slider on Chrome

If we want we can use usual HTML to decorate slider with numbers mentioned above. But I like the result – simple, calm and clean.

Date picker

Now let’s do something that only Opera seems to support right now – let’s create HTML5 date picker. Definition is here.


<form>
    <%= Html.Html5TextBox("deliveryDate", InputTypes.InputType.Date) %>
</form>

And here is the result on Opera.

HTML5 date picker on Opera

Seems good to me. And again – no additional JavaScript is needed. Until other browsers also start supporting this kind on input box you can use jQueryUI Datepicker component.

Conclusion

Although HTML5 is not here yet it is coming very soon and seems like ASP.NET MVC will be soon ready for it. Although HTML5 Helpers Toolkit doesn’t provide all HTML5 controls yet it is still great start and I think this project is worth keeping eye on it. It is very easy to install and very easy to use and I suggest you to try it out as soon as possible.

Posted: Aug 16 2010, 12:30 AM by DigiMortal | with 27 comment(s)
Filed under: ,
ASP.NET MVC 3: Using HttpNotFoundResult in controller tests

Lately I blogged about HttpNotFoundResult and HttpStatusCodeResult action results that come with ASP.NET MVC 3. These results are ideal for controller tests as we don’t have to mess with HttpContext and Response objects anymore. In this posting I will show you how to use HttpNotFoundResult in controller tests to check if errors are given correctly to user.

Let’s suppose we have controller method that displays product details.


public ActionResult Details(int productId)
{
    var product = _repository.GetProductById(productId);

    if (product == null)
    {
        var result = new HttpNotFoundResult("Product not found");
        return result;
    }
           
    // ...

    return View();
}

If product is not found (whatever the reason is) then Details() returns HttpNotFoundResult to let user know that requested product doesn’t exist. If product is there then Details() makes some processing and returns regular view that displays product information.

Now let’s write test to make sure that in the case of missing product error 404 will be returned.


[TestMethod]
public void ProductPageShouldReturn404IfProductNotFound()
{
    var productId = 1;
    Product product = null;

    var repositoryMock = new Mock<IProductRepository>();
    repositoryMock.Setup(c => c.GetProductById(productId))
                    .Returns(product)
                    .Verifiable();

    var result = _controller.Details(productId);

    repositoryMock.Verify();
    Assert.IsNotNull(result);
    Assert.IsInstanceOfType(result, typeof(HttpNotFoundResult));
}

This test makes sure that GetProductById() method is called from product repository mock and also it makes sure that this method returns null. After calling Details() method from controller we check three things:

  1. is GetProductById() method called?
  2. is return value not null?
  3. is return value of type HttpNotFoundResult?

If all these conditions are met then test succeeds. Our tests as you can see, is pretty short and all it does is checking returned type. We don’t have here any dealing with HttpContext and Response and that saves us a lot of trouble. At least in more complex tests.

Conclusion

HttpNotFoundResult and HttpStatusCodeResult are very good choices if we want our ASP.NET MVC applications to be more easily testable. This way we can avoid HttpContext and other related objects. If you want to customize HttpStatusCodeResult then please read my blog posting ASP.NET MVC 3: Creating HttpStatusCodeResult with view based body.

Posted: Aug 15 2010, 07:46 PM by DigiMortal | with 7 comment(s)
Filed under: , ,
ASP.NET MVC 3: Introducing Razor view engine

ASP.NET MVC 3 brings us new view engine called Razor. Razor view engine was made available with WebMatrix first beta. Razor brings us new and very short syntax for writing views. In this posting I will introduce you shortly ASP.NET MVC Razor view engine.

New ASP.NET MVC project type

There is new ASP.NET MVC project type for Razor projects so you can start new application with Razor support already there.

ASP.NET MVC 3 projects

The other options are project with ASPX based views and empty ASP.NET MVC project. As I am going to write sample application that uses Razor then it is not hard to guess which option I chose. Smile

Razor files

ASP.NET MVC Razor ApplicationNew ASP.NET MVC Razor application is created like default ASP.NET MVC web application. The difference is that views are using Razor view engine. Project structure at file system level is same as before as you can see if you take a look at image on right.

There are some things you should know at this point:

  • Extension of Razor based views is .cshtml for view that use C# and .vbhtml for views that use VB.NET.
  • Files that cannot be shown by direct requests (master pages, partial views etc) have underscore (_) in the beginning of their names.

So if you try to make the request to _Layout.cshtml (this is master page) you will get error from server.

You can also see that there are controllers and models folders – things you don’t see in WebMatrix projects.

Razor syntax

Razor syntax is different from what we have seen this far. Razor provides us with way shorter and cleaner syntax and this is the reason why we should consider using it in our ASP.NET MVC projects. After playing with WebMatrix and Razor based pages I was pretty happy with Razor because my views looked cleaner than before.

Here is the example of Razor based view. This is the same Account/LogOn view that comes also with usual ASP.NET MVC default application. Although there is no syntax highlight yet you get the point.

Example of Razor based view
Click on image to see it at original size.

Basically the rules are simple: everything that starts with @ is server-side code. If it is some known language structure that has body then it must be followed by { and }. Between them you can write whatever you want. Okay, there are more rules but all this is documented in WebMatrix tutorial Introduction to ASP.NET Web Programming Using the Razor Syntax.

Should I try it?

Well… Razor was a little bit weird for me when I started playing with it. For smaller views it does not give any strong effect. But when you try it out on more complex views you will see that views are much readable than before. Current preview of ASP.NET MVC 3 doesn’t support syntax highlight for Razor views but syntax highlight is coming with next releases. I still suggest you to try out Razor to find out if it makes anything better for you.

Posted: Aug 15 2010, 04:09 AM by DigiMortal | with 6 comment(s)
Filed under: ,
ASP.NET MVC 3: Global action filters

ASP.NET MVC 3 supports global action filters. Global action filters are applied to all actions in web application. By example, you can use global action filters for common security checks. In this posting I will show you how to write dummy action filter, register it as global and test it.

Source code

You can find source code of this example from Visual Studio 2010 experiments repository at GitHub.

Source code @ GitHub Source code repository
GitHub

Example is located in Experiments.AspNetMvc3NewFeatures.GlobalActionFilters project.

Creating action filter

Let’s start with our primitive action filter that is able in some cases ruin page layout for IE. Am I evil? Yes, I am! But I want this example to work on IIS and Cassini both so let’s make something trivial.


public class MyActionFilterAttribute : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext context)
    {
        base.OnResultExecuting(filterContext);

        context.RequestContext.HttpContext.Response.Write("<!-- Buuu! -->");
    }
}

All this evil filter does is it writes string <!—Buuu! –> to response stream, so it is the first line of output.

Global action filters: no filters yetNow open one of your ASP.NET MVC projects and run it. It does not matter if you run it on IIS or Cassini (ASP.NET development web server). If you look at page source you should see usual HTML there. Something like you see on image on right.

Registering global action filter

Now, without touching any controller let’s put our evil Buuu! in place. Open global. asax and modify Application_Start event so it looks like follows.


protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    // Register global filter
    GlobalFilters.Filters.Add(new MyActionFilterAttribute());
   
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);
}

Compile your project and run application again. Now you should see output like this.

Global action filters: evil filter is registered

Without any additional modification to controllers and their methods we got our action filter work for all controllers. You can surf around your site and for every request you should see now my evil message.

Conclusion

Global application filters are powerful and easy to use features. You can use global filters for different purposes like establishing global security policies and controlling output. Of course, you may find many other uses for global action filters. ASP.NET MVC makes is very easy to register filters at global level and I think it is another great addition to MVC framework.

Posted: Aug 15 2010, 12:03 AM by DigiMortal | with 17 comment(s)
Filed under: ,
Example: Creating workflow to request songs from radio station

Today I played with WF 4.0 declarative workflows. This posting shows you simple workflow that you can extend to add songs to online radio station queue. My main focus here is workflow and I will provide here no logic for actual queue implementation. You can find here also Visual Studio 2010 sample solution.

Windows Workflow Foundation 4.0 that came with Visual Studio 2010 introduces many improvements over previous version like new workflow designer, flowchart workflows and better integration with WCF. This example is based on new project type in Visual Studio 2010: WCF Workflow Service Application. Basically this is type of WCF application that hosts workflows (and other stuff you add to the project). There is no need to manually make these two to work together – everything is already done.

Workflow: add song to queue

Let’s take a quick look at workflow to see what we are talking about. Take this screenshot also as example of new workflow designer. This screenshot is taken simply by clicking on flowchart and selecting Copy to clipboard. So it is very easy to add workflow diagrams also to your documents, wikis, etc.

Workflow: Add song to queue
Click on image to see at original size.

The workflow is simple. It takes artist and song name in its first step and these parameters are coming in through WCF service. Workflow itself is just XML file. If song is not found then workflow returns “Song not found” message. If song exists then workflow checks if song is already in queue. If it is then “Song already queued” message will be returned. If song is not in queue then song will be queued and “Song added to queue” message will be returned.

Bridging between WCF and WF

First activity of workflow is “Receive message from service”. This activity is bridge between WCF service and workflow for input data. If you click on “View paramters” part of receive activity in sample application you can see dialog like this.

Receive activity parameters

I defined input parameters artist and song. Also I defined global parameters with same name in flowchart scope. This way I can use input parameters everywhere in my workflow.

Using static method in FlowDecision

The next interesting piece in workflow is how to use external classes in decisions. Click on decision, press F4 to open properties window and click on ellipses right after Condition. You should see something like this.

Flowchart Decision with expression
Click on image to see it at original size.

Condition is boolean condition. PlaylistClient is my custom class that serves as bridge between workflow and external system or data source. You can see that I can use parameters defined in flowchart scope. We will see my methods as next thing.

PlaylistClient – bridge between workflow and playlist

As this kind of workflow needs to communicate with external code because information about songs and queue is located in some other system. To play with this scenario I created simple class with static methods. You can put some real logic there to try out scenarios with real data or real systems.


public class PlaylistClient
{
    public static bool SongInQue(string artist, string song)
    {
        return false;
    }

    public static bool SongExists(string artist, string song)
    {
        return true;
    }

    public static void AddToQueue(string artist, string song)
    {

    }
}

I made these methods static as they are basically functions that retrieve data from some other source and they don’t carry any logic. These methods are just gateways to other system for workflow.

Adding songs to queue

Now let’s see how to call AddToQueue() method form workflow. This is done by using InvokeMethod activity. InvokeMethod activity is perfect fit – it is able to call static and instance methods and also provide methods with parameters.

InvokeMethod activity with method parameters
Click on image to see it at original size.

After adding song to queue workflow finishes it’s job and returns message to user.

Testing workflow

Select workflow before hitting F5You can use Visual Studio 2010 to test how workflow works with WCF. Visual Studio has WCF Test Client that is able to connect to WCF services and it lets you to call service methods with parameters you manually provide.

NB! You must select service in solution explorer before hitting F5. If you don’t then project is run as usual web application on built-in web server. Take a look at image on right.

When you run your service then WCF Test Client will be opened and is shows you structure of your service in left pane. If you select some method then method call editor will be shown in right pane.

Here is the screenshot with sample request and response. Notice the second line in request definition. When you open RequestSong() method then there is now value in Value column. You have to select this tempuri.org.RequestSong from dropdown to see artist and song selection.

WCF Test Client: Testing RequestSong workflow
Click on image to see it at original size.

Conclusion

It is not hard to create web based workflows using Visual Studio 2010 project template called WCF Workflow Service Application. A lot of things are handled and managed automatically for user and developers can focus on functionality they have to create. Visual Studio 2010 tools are enough in most cases and these tools are fast and easy to use.

Sample solution

MyWcfWorkflowService.zip MyWcfWorkflowService.zip
VS2010 | 30KB
There is no context attached to the incoming message for the service and the current operation is not marked with "CanCreateInstance = true"

CanCreateInstance = trueI got this error when testing my example WF 4.0 workflow that runs on WCF. To get over this error just open your workflow, select Receive activity and make check to checkbox called CanCreateInstance (click on image at right to see it at original size).

Cite from CanCreateInstance documentation:

”Service workflows that do not have a ReceiveActivity activity with CanCreateInstance set to true cannot be instantiated by a client using a service operation invocation. Such workflows can be created using the CreateWorkflow method of the associated WorkflowRuntime object.

The default value for this property is false.

You have to set this property to true for every workflow you want to use through WCF service.

Posted: Aug 13 2010, 02:45 AM by DigiMortal | with no comments
Filed under: , ,
More Posts